Development record
ahoy.Detect reads CLAUDE.md/AGENTS.md/config via plain os.ReadFile with no size cap or O_NONBLOCK, unlike the hardened session-end transcript read; a FIFO or multi-GB file at cwd could hang or slurp any hook that calls Detect (session-start, session-end, ahoy verbs). Harden Detect's marker/config reads to match maxTranscriptBytes plus a non-blocking open.
issueresolvedminoriss-97
ahoy.Detect reads CLAUDE.md/AGENTS.md/config via plain os.ReadFile with no size cap or O_NONBLOCK, unlike the hardened session-end transcript read; a FIFO or multi-GB file at cwd could hang or slurp any hook that calls Detect (session-start, session-end, ahoy verbs). Harden Detect's marker/config reads to match maxTranscriptBytes plus a non-blocking open.
Frontmatter
| id | iss-97 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-97-detect-unbounded-marker-reads.md
open on GitHub ↗ · commit history ↗
mentions4
- dcn-26080800000000022026-08-08 — bug-hunt loop round 9 (state issue #197): a multi-angle sweep (5
- iss-109ahoy manual-guard reads carry a residual Lstat->ReadFile TOCTOU: verifyHookManifest (store.go), and gitignore.go read sites (~72, ~181) each do Lstat+IsRegular+size-cap then a separate os.ReadFile, so a type/symlink swap between check and read is not refused on the same fd. iss-97 converged the six bare-unguarded ahoy reads onto fsutil.ReadGuarded (single-fd O_NOFOLLOW|O_NONBLOCK+cap); these three were left because their structured signals (verifyHookManifest reason strings; gitignore bool flags + the write-path oversize refusal) need preserving, so the convergence is not mechanical. Route them through ReadGuarded too, preserving those signals, to close the TOCTOU and reach one guarded-read mechanism. Sibling of iss-97.
- iss-202scanner.New reads the per-repo .abcd/config/pii.json override with a bare os.ReadFile — no O_NOFOLLOW, no size cap, no regular-file check — unlike every sibling trust-boundary config reader in this codebase (guard.Load, rules.Load, banlist private store) which goes through fsutil.ReadGuarded; a FIFO planted at that path hangs the read forever and a symlink to a device file (git-committable, mode 120000, no local write access needed) grows the read unbounded toward OOM; reachable automatically via the SessionEnd hook's history capture, which also holds an unbounded history.repoLock flock across the hang, permanently wedging transcript capture for that repo; this is the same bug class already fixed once for ahoy.Detect under iss-97. Independently verified: FIFO hangs past 3s deadline (control: no-config-file case returns in 0.01s), /dev/zero symlink accumulates ~137 MiB/s, causal fix test (swap to fsutil.ReadGuarded) confirmed both cases resolve
- iss-2608241347321757`abcd capture resolve` exists and works. Nothing anywhere can fail when it is