Skip to content

Allow user to save patch file to disk#424

Open
tebeka wants to merge 2 commits intoroborev-dev:mainfrom
tebeka:save-patch
Open

Allow user to save patch file to disk#424
tebeka wants to merge 2 commits intoroborev-dev:mainfrom
tebeka:save-patch

Conversation

@tebeka
Copy link
Contributor

@tebeka tebeka commented Mar 4, 2026

When user hits s in patch view, it'll be prompted for file name (default to /tmp/roborev-<id>.patch).

Somewhat related to #407

@roborev-ci
Copy link

roborev-ci bot commented Mar 4, 2026

roborev: Combined Review (e70f1f5)

Summary Verdict: Adds an interactive "save patch to file" flow in the TUI patch viewer, but
introduces medium-severity path construction bugs and file-creation security risks.

Medium Severity Findings

1. Non-portable / Incorrect Default Save Path Construction

  • File: cmd/roborev/tui/handlers_modal.go (lines 512, 514)

  • Description: The default path is constructed with hardcoded slashes using fmt.Sprintf("/%s/roborev-%d.patch", os.TempDir(), m.patchJobID). This results in invalid absolute paths on Windows (e.g., /C:\Temp\...) and redundant double
    -slashes on POSIX systems (e.g., //tmp//...).

  • Suggested Fix: Import path/filepath and use filepath.Join(os.TempDir(), fmt.Sprintf("roborev-%d.patch", m.patchJobID)).

2.
Predictable /tmp Filename / Insecure File Creation (Symlink Clobbering)

  • File: cmd/roborev/tui/handlers_modal.go (lines 514, 548)
  • Description: The default save path is deterministic (
    /tmp/roborev-<jobID>.patch), and os.WriteFile will follow symlinks and truncate existing targets. On multi-user systems, another local user could pre-create a symlink at that path and cause overwrite of arbitrary files writable by the victim user.
  • Suggested Fix: Use
    a secure creation flow: os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600) (or os.CreateTemp for default path generation), and verify targets are not symlinks.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@tebeka
Copy link
Contributor Author

tebeka commented Mar 4, 2026

Fixed 1, ino 2 is a non issue

@roborev-ci
Copy link

roborev-ci bot commented Mar 4, 2026

roborev: Combined Review (c50df69)

Verdict: The new patch saving feature is functional but contains a few medium-severity issues regarding predictable temporary files, byte-based string truncation, and a lack of targeted test coverage.

Medium

  • Predictable filename in shared temp space / Symlink overwrite

  • Location: cmd/roborev/tui/handlers_modal.go:515, cmd/roborev/t ui/handlers_modal.go:549

    • Issue: Default save path uses a predictable filename in shared temp space (/tmp/ roborev-<jobID>.patch) and writes via os.WriteFile, which follows symlinks. On multi-user systems, another local user can pre-create that path as a symlink, causing overwrite/truncation of an arbitrary file the victim can write.
    • Remediation: Use
      os.CreateTemp (randomized filename) in a private directory (0700) and write through the returned file descriptor. If supporting user-provided paths, open with safer flags (O_CREATE|O_EXCL) and reject symlinks (Lstat/EvalSymlinks +
      policy, or platform-specific no-follow behavior).
  • Filename input truncation is byte-based

    • Location: [cmd/roborev/tui/render_tasks.go:501-503](/home/roborev/repos/roborev
      /cmd/roborev/tui/render_tasks.go:501)
    • Issue: Slicing the display string using its byte length (len(display) > inputWidth) can split multi-byte characters in half, resulting in invalid UTF-8 sequences and
      rendering artifacts if the file path contains non-ASCII characters.
    • Remediation: Convert display to a slice of runes before checking its length and slicing (e.g., runes := []rune(display) then string(runes[len(runes)-inputWidth:]) ), or use a display-width aware function consistent with other TUI rendering code.
  • New save flow lacks targeted tests

    • Location: [cmd/roborev/tui/handlers_modal.go:470](/home/roborev/repos/robore
      v/cmd/roborev/tui/handlers_modal.go:470), [cmd/roborev/tui/handlers_msg.go:657](/home/roborev/repos/roborev/cmd/roborev/tui/handlers
      _msg.go:657), cmd/roborev/tui/render_tasks.go:498, cmd/ roborev/tui/types.go:233
    • Issue: No new _test.go coverage appears for: entering/ex
      iting save-input mode, default path population, save success/error handling, and patch-view rendering while input is active.
    • Remediation: Add unit tests for handlePatchKey, handleSavePatchResultMsg, and renderPatchView save-mode UI branches.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant