Development record
readDrain (internal/core/implement/loop/drain.go) accepts the free text a drain state stores in .abcd/.work.local/run/drain.json unchecked: each hand-back's reason, home, question, rule, draft and wrote fields and the judgements are copied into 'abcd drain --json' as stored (res.HandBacks = st.HandBacks), so a hand-written or repository-shipped drain.json can carry control or bidi runes (U+202E, U+009B) onto the JSON stream; the same display-spoofing class as iss-2610121206163414, which hardened the drain's stored pace. Found by the implementer of that fix.
readDrain (internal/core/implement/loop/drain.go) accepts the free text a drain state stores in .abcd/.work.local/run/drain.json unchecked: each hand-back's reason, home, question, rule, draft and wrote fields and the judgements are copied into 'abcd drain --json' as stored (res.HandBacks = st.HandBacks), so a hand-written or repository-shipped drain.json can carry control or bidi runes (U+202E, U+009B) onto the JSON stream; the same display-spoofing class as iss-2610121206163414, which hardened the drain's stored pace. Found by the implementer of that fix.
Security scope (abcd-fixes-what-it-adds): the route does not exist without abcd. The drain state file, its reader and the --json stream are abcd's own, so abcd added it and fixes it; a fix refuses or masks a malformed file abcd itself reads and changes nothing about how the repository works.
Frontmatter
| id | iss-2610121505153157 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-2610121505153157-readdrain-internal-core-implement-loop.md
open on GitHub ↗ · commit history ↗
mentions3
- iss-2610121206163414readSeries (internal/core/implement/loop/nextseries.go) still accepts the stored pace provenance strings in .abcd/.work.local/run/next.json unchecked: each pace setting's layer and origin (pace.*.layer, pace.*.origin) is free text that reaches 'abcd build next --json' raw, so a hand-written or repository-shipped series file can carry control or bidi runes there, the same display-spoofing class iss-2610120925598775 closed for the stored flags. The same Pace shape is read from a run's state.json and echoed by 'implement record --json'. Found by the implementer fixing iss-2610120925598775.
- iss-2610121516552317abcd drain --json echoes each issue's disposition reason straight from the ledger reader: that text includes the reader's error messages with record paths unquoted and a record's raw deferred_after value, so a repository whose ledger file name or deferred_after carries a control or bidi rune (U+202E, U+009B) puts it raw on the --json stream, and the drain copies the same text into a judgement's note in drain.json, where readDrain (since iss-2610121505153157) then refuses the whole file. Found by the implementer of iss-2610121505153157.
- iss-2610121516559163ReadState (internal/core/implement/loop/state.go) does not check a lane's stored hand-back text in a run's state.json, and on the call that routes a hand-back the drain echoes that text onto abcd drain --json before drain.json is ever re-read, so a hand-written or repository-shipped state.json whose hand-back reason, home or question carries a control or bidi rune (U+202E, U+009B) puts it raw on the stream. The receipt path sanitizes these fields when the loop takes them, so only a forged file carries them. Found by the implementer of iss-2610121505153157.