fix: strip control characters from info field values - #1829
Conversation
Version and Project (repo name) fall back to a package.json/Cargo.toml manifest field when git tags/remote are absent, and those values were styled and written to the terminal with no filtering of control characters. A manifest field has no character restrictions, unlike a git tag/ref, so a crafted manifest could inject terminal escape sequences into onefetch's own output. Adds sanitize_for_display in InfoField::style_value, the single choke point every field's value already passes through, so the fix covers every manifest-derived field, not just version.
| /// come from data with no character restrictions and shouldn't be trusted | ||
| /// to display as-is. `\n` is preserved since some fields intentionally span | ||
| /// multiple lines. | ||
| fn sanitize_for_display(s: &str) -> String { |
There was a problem hiding this comment.
can you add some unit tests for this?
|
This would only realistically happen with a repository that isn't trustworthy IMO, so I'd argue that this would be a symptom of a much greater problem, which is the user running Git has had a feature for repository trust/ownership for a while now. Should we perhaps rely on that to determine if it's safe to read and output repository contents? Also, rather than clean the contents, perhaps it would be better to wrap the string in a result? |
Covers the control-byte-to-replacement-character behavior directly (including an OSC title-set style payload), confirms newlines and normal printable text are left untouched, and adds a style_value-level test exercising the sanitizer through the same path real field values take.
|
Added unit tests for On the trust question: Perhaps a repo does not need to already look untrustworthy for this to matter. Running onefetch is often how someone forms that first impression, cloning a new dependency or browsing an unfamiliar repo before deciding whether to trust it. Escape sequences in a manifest field let the repo act on the terminal (change the window title, and depending on the emulator, worse) before that judgment ever gets made. git's safe.directory/ownership check is also a different boundary: it stops git from running config or hooks from a repo you don't own, not display of arbitrary file content like a manifest's version or description field. On |
Unless there's a legitimate reason to have a bad byte, I think it's safe to assume the field is malformed at best, malicious at worst, and is an edge case where it's okay to just drop the whole field. |
Fixes #1828
VersionandProject(repo name) fall back to apackage.json/Cargo.tomlmanifest field when git tags/remote are absent, and those values were styled and written to the terminal inInfoField::style_valuewith no filtering of control characters. A manifest field has no character restrictions, unlike a git tag/ref, so a crafted manifest could inject terminal escape sequences into onefetch's own output.Change
Adds
sanitize_for_display(src/info/utils/info_field.rs), which replaces control characters (other than\n, since some fields intentionally span multiple lines) with the Unicode replacement character. Applied insidestyle_value, the single choke point every field's value already passes through, so the fix covers the project-name fallback and any other manifest-derived field, not just the version field used to demonstrate this.Testing
package.jsonwhoseversionfield contained a JSON-escaped OSC title-set escape sequence, confirmed via atmux pipe-panecapture (hex-dumped, not just visually inspected) that the decoded raw escape bytes reached the terminal adjacent to onefetch's own SGR color codes.