Fix five security scan findings - #8
Merged
Merged
Conversation
platform::git only added --ignore-submodules=dirty when args[0] was "status" or "diff". diff_file passes --literal-pathspecs first, so the guard was skipped and viewing a staged submodule's Unstaged diff let git run `git status` inside it, loading that repository's own clean/process filters. Leading --options are now passed through as global options and the guards apply to the real subcommand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recovery_notes read the settings-supplied path with an unbounded read_to_string before its 256 KB check, so a path like /dev/zero (for example from an imported setup bundle) exhausted memory. Non-regular files are now refused and the read stops at 256,001 bytes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
save_settings wrote settings.json with the umask default (usually 0644) and copied the .bak with the same mode, although it can hold repository addresses, password-file names and custom commands. Both now go through platform::atomic_write like the app's other private stores. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The embedded-password check parsed rest:https://user:pass@host as an opaque "rest" URL and never saw the password, so REST-server credentials reached restic's argv. The check now also inspects the address after the rest: prefix, with the same error pointing to Restic's credential environment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cleanOutput's /\x1b\][^\x07]*(?:\x07|\x1b\\)/g let the body run past later ESC bytes, so a flood of unterminated "ESC ]" pairs, for example in git sideband output from a hostile remote, backtracked quadratically and froze the renderer on every launch while the job stayed in history. An indexOf scan now reproduces the regex's result exactly (first BEL after the introducer, otherwise the last ST) in linear time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change
Fixes five findings from a security scan of
e7163bb. There is one commit per finding, and each commit adds its own regression test.platform::gitadded--ignore-submodules=dirtyonly whenargs[0]wasstatusordiff.diff_filepasses--literal-pathspecsas its first argument, so the guard was skipped. Opening the Unstaged diff of a staged submodule then let git rungit statusinside that submodule, and a filter defined in the submodule's config could execute a command. The wrapper now treats leading--options as global options and applies the guards to the real subcommand./dev/zero, which an imported setup bundle can supply, was read without limit before the 256 KB check ran. The read now refuses anything that is not a regular file and stops at 256,001 bytes.settings.jsonand its backup were world-readable (low). Both files were written with the umask default, usually 0644. They now go throughplatform::atomic_writeand are created with 0600.rest:https://user:pass@hostas an opaquerestURL, so it never saw the password. It now also checks the address after therest:prefix.cleanOutput's OSC regex,/\x1b\][^\x07]*(?:\x07|\x1b\\)/g, the body could run past later ESC bytes. A flood of unterminatedESC ]pairs in git sideband output from a hostile remote therefore made it backtrack quadratically. Because the job stays in activity history, the renderer froze on every launch. AnindexOfscan replaces the regex. It produces exactly the same result (the first BEL after the introducer, otherwise the last ST) in linear time.Validation
cargo test: 71 passed, including 4 new regression tests. Each new test fails on the unpatched code.cargo clippy --all-targets -- -D warnings: clean.npm test: 78 passed, including 2 newcleanOutputtests. One pins the existing output, the other checks a 2 MB flood.npm run check: passed.cleanOutputwas compared against the original regex on 500,000 random inputs built from ESC,],\, BEL, CSI characters and CR/LF, with no differences. Adversarial 2 MB inputs finish in 1–3 ms.Review notes
rest:Restic repository with a password in the address is now refused, with the existing error that points to Restic's credential environment. Move those credentials toRESTIC_REST_USERNAMEandRESTIC_REST_PASSWORD.-dirtymarker. This matches the file list and the full diff view, which already had the guard.cleanOutputchange affects only speed.🤖 Generated with Claude Code