Development record
readTranscript opens the hook-supplied transcript path with O_RDONLY|O_NONBLOCK but no O_NOFOLLOW, the last bespoke external-input read in the CLI not routed through fsutil.ReadGuarded; defence-in-depth consolidation (no reachable exploit: the path is harness-supplied and no path policy exists)
readTranscript opens the hook-supplied transcript path with O_RDONLY|O_NONBLOCK but no O_NOFOLLOW, the last bespoke external-input read in the CLI not routed through fsutil.ReadGuarded; defence-in-depth consolidation (no reachable exploit: the path is harness-supplied and no path policy exists)
Evidence
internal/surface/cli/cli.go:1211—os.OpenFile(path, os.O_RDONLY|syscall.O_NONBLOCK, 0), noO_NOFOLLOW, unlikefsutil.ReadGuarded(fsutil/fsutil.go:48) andreadGuardedOperand(cli.go:917-918).- The regular-file check and cap are on the returned fd (
:1217-1226) — no leaf TOCTOU, but a followed symlink's fstat reports the target, so a symlink-to-regular-file is not refused. transcript_pathis harness-supplied (cli.go:943-945), outside the target repo; content lands in~/.abcd/historyand is shown byabcd history show(sanitised, iss-340).
Adversarial verdict
CONFIRMED (nitpick / defence-in-depth). The exfiltration framing is REFUTED: the path is attacker-chosen by design with no path policy, so a direct path already reads any file — O_NOFOLLOW closes nothing reachable. It is the last bespoke external-input read not routed through the shared primitive. RECORDED, not fixed this round (touches the SessionEnd hook error path; pure defence-in-depth, no reachable exploit). Fix (future): route through fsutil.ReadGuarded.
Frontmatter
| id | iss-369 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | nitpick |
.abcd/work/issues/resolved/iss-369-readtranscript-opens-the-hook-supplied.md
open on GitHub ↗ · commit history ↗
mentions2
- 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-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