Problem
hooks/lib/read-session.sh's parse_session_fields serialises 8 session fields as tab-separated values from python3, then splits them back via IFS=\$'\t' read -r. A session.json containing embedded \t or \n characters in workflow, current_step, or other string fields would corrupt the field boundaries, shifting values into the wrong variables.
Today this is low-risk because session.json is written exclusively by the devkit engine (not user input), and the engine doesn't currently put tabs or newlines in those fields. But it's a latent footgun: any future change that lets workflow names or step IDs contain whitespace (or any operator manually editing session.json to recover a stuck workflow) could silently corrupt guard enforcement.
Proposal
Replace the tab-delimited output format with null-byte delimiters, which cannot appear in Python strings and survive all bash string handling cleanly:
sys.stdout.write("\0".join([...]))
On the bash side, read with read -rd '' or mapfile -d '' to split on null bytes.
Alternative: emit the 8 fields as lines of key=value pairs and parse with a loop. More verbose but more robust against schema additions.
Acceptance criteria
hooks/lib/read-session.sh parses correctly even when workflow/current_step contain tabs, newlines, or shell metacharacters.
- New fixture in
hooks/devkit-guard_test.sh seeds a session.json with embedded \t and \n and asserts the guard still enforces correctly.
- No performance regression (the python3 subprocess already dominates latency).
Out of scope
Context
Flagged by Codex during the PR #64 mega-review as a silent-failure vector. Deferred from PR #64 to keep that PR focused. Low urgency because the production writer is the engine itself, which doesn't produce these characters today.
Problem
hooks/lib/read-session.sh'sparse_session_fieldsserialises 8 session fields as tab-separated values from python3, then splits them back viaIFS=\$'\t' read -r. Asession.jsoncontaining embedded\tor\ncharacters inworkflow,current_step, or other string fields would corrupt the field boundaries, shifting values into the wrong variables.Today this is low-risk because
session.jsonis written exclusively by the devkit engine (not user input), and the engine doesn't currently put tabs or newlines in those fields. But it's a latent footgun: any future change that lets workflow names or step IDs contain whitespace (or any operator manually editingsession.jsonto recover a stuck workflow) could silently corrupt guard enforcement.Proposal
Replace the tab-delimited output format with null-byte delimiters, which cannot appear in Python strings and survive all bash string handling cleanly:
On the bash side, read with
read -rd ''ormapfile -d ''to split on null bytes.Alternative: emit the 8 fields as lines of key=value pairs and parse with a loop. More verbose but more robust against schema additions.
Acceptance criteria
hooks/lib/read-session.shparses correctly even whenworkflow/current_stepcontain tabs, newlines, or shell metacharacters.hooks/devkit-guard_test.shseeds asession.jsonwith embedded\tand\nand asserts the guard still enforces correctly.Out of scope
Context
Flagged by Codex during the PR #64 mega-review as a silent-failure vector. Deferred from PR #64 to keep that PR focused. Low urgency because the production writer is the engine itself, which doesn't produce these characters today.