Development record
readSeries (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.
readSeries (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.
Security scope (abcd-fixes-what-it-adds): the route does not exist without abcd. The series and run state files, their readers and the --json streams that echo them are abcd's own, so abcd added it and fixes it; a fix refuses a malformed file abcd itself reads and changes nothing about how the repository works.
A third route, named by the security reviewer of fix/build-next-followups: continueSeries given a pace flag that differs from the stored pace calls resumeWithFlags (internal/core/implement/loop/loop.go), whose refusal reason includes res.Pace.String(); describeOrigin (pace.go) concatenates each setting's origin and layer raw, and loopFail sanitizes only the text line, so the JSON refusal carries them unmasked. The fix's test should cover that refusal reason too.
Frontmatter
| id | iss-2610121206163414 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-2610121206163414-readseries-internal-core-implement-loop.md
open on GitHub ↗ · commit history ↗
mentions2
- iss-2610120925598775readSeries (internal/core/implement/loop/nextseries.go) checks a series file's intent, run_id and outcome but not its stored pace flags (flags.pace, flags.sub_agents, flags.fix_rounds), so a hand-written or repository-shipped .abcd/.work.local/run/next.json can carry control or bidi runes (for example U+202E, U+009B) in them; on a series move that picks nothing (window or cap), those strings reach 'abcd build next --json' unvalidated and encoding/json leaves them raw. Low severity: display spoofing of the JSON text on a terminal, no read, write or exec. Found by the security reviewer, round 2 of run-2610110908001704 lane-1.
- iss-2610121505153157readDrain (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.