Development record
The lifeboat coverage renderer prints untrusted cross-repo status and tiers_present fields to the terminal without termsafe, so a crafted probe report injects raw ESC/OSC-8/C1/bidi sequences; only the repo name is sanitised
The lifeboat coverage renderer prints untrusted cross-repo status and tiers_present fields to the terminal without termsafe, so a crafted probe report injects raw ESC/OSC-8/C1/bidi sequences; only the repo name is sanitised
Evidence
internal/core/lifeboat/coverage.go:212sanitises onlyc.Repo.Name;:224copiesTiersPresentverbatim;:258-265statusOfreturnsStatusverbatim.internal/core/lifeboat/mapping.go:30,50—Tier/Statusare barestring;Status.Valid()(:77) is called only in tests, never on the decode/render path.internal/surface/cli/cli.go:532-535documents the operand as untrusted cross-repo;:553-565validates onlyschema_version;:574-575renders viaagg.Render()to stdout.- Aggregate render sinks:
coverage.go:273-276(tiers line) and:301-305(row.Cells); sibling per-repo render shares the gap at:98,:104,:106.
Reproduced: a crafted status/tiers_present injects raw ESC[31m (SGR) and OSC-8 hyperlink to the terminal; repo name correctly defanged in the same run.
Adversarial verdict
CONFIRMED (substantive). Refuter reproduced raw ESC/OSC-8 reaching the terminal. Distinct site from iss-259/iss-264/iss-340. Fix: route the tier/status/section strings through the existing sanitize at both the aggregate and per-repo render, with a pinning test.
Frontmatter
| id | iss-361 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-361-the-lifeboat-coverage-renderer-prints.md
open on GitHub ↗ · commit history ↗
mentions4
- dcn-26082000000000052026-08-20 — bughunt round 3 (branch bughunt-a/round-3): captured twelve findings (iss-360..iss-369, plus two renumbered to iss-373/iss-374 after round 2's own collision re-mint landed inside this round's block — the week's fourth collision,
- iss-259intent-store paths render to the terminal unsanitised in several intent verbs: intent plan prints res.Intent.Path and intent create prints the minted path without termsafe.Sanitize, and a hostile clone can commit a drafts/itd-N-<slug>.md whose filename tail carries control bytes (intentFileRe admits anything but a newline after the id), reaching the owner's terminal as escape sequences. The promote render sanitises its two paths as of spc-24; close the class once by sweeping the sibling intent renders through termsafe.Sanitize.
- iss-264cmd/record-lint prints Finding.File and Finding.Message raw — no termsafe.Sanitize and no path scrub on the findings path (its scrubPaths covers only the two error exits), so any rule echoing repo content lets a hostile clone inject terminal escapes into CI logs, and any finding message embedding an os error can leak absolute paths. The abcd CLI surface sanitizes at its findings renderer; the standalone binary does not. Found by the spc-27 security review, which also caught (and the change fixed) the one in-diff instance.
- iss-340abcd history show writes the stored transcript body to the terminal with no termsafe sanitisation (cli.go human render branch) — a transcript that ingested hostile content (fetched pages, target-repo files) replays ESC/CSI/C1/bidi sequences raw; the termsafe sweep missed the history surface