Development record
Sibling of GHSA-fh9j-8xmg-m33f (CWE-59, CWE-400), found on the sweep and not fixed there: checkReceiptGate (internal/core/lint/lint.go) reads each review receipt under .abcd/work/reviews/<sha>/<gate>.json and the release-gate manifest through a bare os.ReadFile — no O_NOFOLLOW, no O_NONBLOCK, no regular-file check, no byte cap. The reviews store is committed and travels with a clone, so a committed FIFO at a receipt path hangs abcd lint (and make preflight through it), and a committed symlink is judged as if it were a receipt. The fix is the routing through fsutil.ReadGuarded that lint's readingoutstanding.go already uses for the reading family, with a cap for the receipt shape, and a test with a FIFO and a symlinked receipt. Distinct from iss-2609011423385217 (the manifest's stale pinned inputs) and from the record-store sweep records iss-2608301203521317 and iss-2608211914592726, which do not name the reviews store.
Sibling of GHSA-fh9j-8xmg-m33f (CWE-59, CWE-400), found on the sweep and not fixed there: checkReceiptGate (internal/core/lint/lint.go) reads each review receipt under .abcd/work/reviews/<sha>/<gate>.json and the release-gate manifest through a bare os.ReadFile — no O_NOFOLLOW, no O_NONBLOCK, no regular-file check, no byte cap. The reviews store is committed and travels with a clone, so a committed FIFO at a receipt path hangs abcd lint (and make preflight through it), and a committed symlink is judged as if it were a receipt. The fix is the routing through fsutil.ReadGuarded that lint's readingoutstanding.go already uses for the reading family, with a cap for the receipt shape, and a test with a FIFO and a symlinked receipt. Distinct from iss-2609011423385217 (the manifest's stale pinned inputs) and from the record-store sweep records iss-2608301203521317 and iss-2608211914592726, which do not name the reviews store.
Grounds
- pursued: an armed receipt gate never hangs and is never satisfied by a receipt reached through a link; a symlinked PROMOTE receipt yielding zero receipt_gate findings would show it wrong
Frontmatter
| id | iss-2609012037127981 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-2609012037127981-sibling-of-ghsa-fh9j-8xmg-m33f-cwe-59.md
open on GitHub ↗ · commit history ↗
mentions4
- iss-2608211914592726residual config-derived os.ReadFile sites in internal/core/lint read cloned-repo-controlled paths without the containment/guarded-read stack the roots and glossary walks now use: persona.go registry, lint.go spec-doc and record-store reads, speclinks.go, contextcurrency.go, deliverystate.go changelog, indexdrift.go, subverbs.go snapshots. Triage each by attacker-controllability under a cloned repo and guard those in scope
- iss-2608301203521317record_schema's store walk reads every record with os.ReadDir and os.ReadFile, with no symlink refusal and no size cap, while the sibling reading walk in readingoutstanding.go reads the same trees through fsutil.ReadGuarded — so a symlinked or oversized record is followed by the gate and declined by the report, and a symlink's target frontmatter can surface in lint output. Pre-existing across all four original stores; noted during the itd-189 security review and left out of that branch's scope. Read the store walk through the same guarded read the report uses.
- iss-2609011423385217The release-gate manifest's pinned inputs are stale and under-scope the record
- iss-2609261016494611The armed receipt gate is satisfied by a forged PROMOTE reached through a symlinked commit directory. checkReceiptGate (internal/core/lint/lint.go) reads each receipt with fsutil.ReadGuarded on the unresolved path `.abcd/work/reviews/<sha>/<gate>.json`, and holds only receipts_dir inside the repository once links are followed. O_NOFOLLOW refuses a symlinked leaf, but the kernel follows every ancestor, so a committed `.abcd/work/reviews/<sha>` that is a link to a directory outside the tree, holding a well-formed PROMOTE receipt, yields zero receipt_gate findings: the release gate passes on a receipt the tree does not hold. The release-gate manifest read has the same shape: a symlinked `.abcd/development/release-gate` directory hands the gate an out-of-tree manifest whose hash a forged receipt can echo. iss-2609012037127981 was resolved with grounds that the gate is never satisfied by a receipt reached through a link, so that resolution over-claims.