fix: escape SessionStart JSON control characters#1590
Conversation
Reviewer noteThis PR is one of six small, independent PRs opened from the same triage pass. They can be reviewed and merged independently:
Focus for this PR: harden SessionStart JSON output so all representable C0 control characters in injected skill content are escaped before the harness parses the hook payload. Review surface: Verification: hook tests use temporary skill fixtures containing U+0001 through U+001F and parse the real hook output with Risk to check: shell escaping correctness and whether both SessionStart variants stay in sync. |
|
Closing. The escape_for_json function does have the gap you describe — it handles This kind of defensive hardening could be worth a much smaller, targeted PR if someone hits an actual repro. As filed, it's part of a 17-PR batch from the same author and the cost (modifying both SessionStart hooks plus a fixture test) is disproportionate to a non-observed bug. #1446 has three sub-issues; this one is the lowest-priority of the three. If the failure ever surfaces in a real session, please open a focused single-file PR. — Claude Opus 4.7, Claude Code 2.1.150 |
What problem are you trying to solve?
Issue #1446 reports three independent latent bugs. This PR fixes only the first one:
hooks/session-starthas a hand-written JSON string escaper that handles backslash, double quote, newline, carriage return, and tab, but leaves other C0 control characters raw.Raw U+0000 through U+001F characters are not valid inside JSON strings. If
skills/using-superpowers/SKILL.mdever contains a raw backspace, form feed, vertical tab, unit separator, or similar control character, the SessionStart hook emits invalid JSON and the harness cannot parse the payload. The likely user-facing failure is Superpowers not activating even though the plugin is installed.hooks/session-start-codexcarries the same escape helper, so it has the same failure mode.What does this PR change?
Escapes every C0 control character that Bash strings can carry in both SessionStart hooks:
\b,\f,\n,\r, and\t\u0001through\u001ffor the remaining representable controlsIt also extends the SessionStart hook tests with temporary plugin fixtures whose
using-superpowersskill content contains U+0001 through U+001F, then parses the real hook output withJSON.parse.Is this change appropriate for the core library?
Yes. SessionStart bootstrap output is core plugin infrastructure used before any skill can run. The fix is general-purpose, dependency-free, and applies to both the standard SessionStart hook and the Codex-specific SessionStart hook.
What alternatives did you consider?
hooks/session-start. Rejected becausehooks/session-start-codexduplicates the same escape helper and would keep the latent bug.find-polluter.shpath-splitting issue should be a separate narrow PR if pursued.Does this PR contain multiple unrelated changes?
No. It only fixes SessionStart JSON escaping for control characters and adds a regression test/spec/plan for that one bug.
Existing PRs
#134 is prior art for Windows/plugin hook support. #1555 covers a different #1446 sub-issue: WebSocket payload-size caps in the brainstorm server. Searches for
1446 escape_for_json,escape_for_json control char, and related terms did not find a duplicate PR for this SessionStart JSON escaping fix.Environment tested
New harness support (required if this PR adds a new harness)
Not applicable. This PR does not add support for a new harness.
Clean-session transcript for "Let's make a react todo list"
Evaluation
bash tests/hooks/test-session-start.shfailed for both hooks withinvalid JSON: Bad control character in string literal.SessionStart escapes JSON control characters in skill contentandCodex SessionStart escapes JSON control characters in skill content.Verification commands run fresh before PR creation:
All exited 0.
Rigor
superpowers:writing-skillsand completed adversarial pressure testing (paste results below)This is hook infrastructure, not a skill behavior change. The adversarial test uses a real hook output path with all representable C0 controls in the injected skill content and verifies JSON parsing plus decoded context preservation.
Human review
Human partner reviewed the fork compare diff for
YOMXXX:fix/session-start-json-control-escapingand explicitly approved opening the PR. They also gave standing approval to open future PRs after the complete diff and verification summary are shown.