Skip to content

guard-main-checkout-bash.sh: a backslash-escaped \" ends the double-quoted word — blocking pure reads with a confidently-wrong target AND missing real sed -i writes (arrow diagnosis disproven; was: unicode-arrow-as-redirect) #10247

Description

@os-elon

Found while running the 17.1.0 QA sweep (#10224 family). Filing because the failure mode pushes an agent toward OS_ALLOW_MAIN_EDITS=1, which is the one outcome a write guard must never encourage.

What happened

This command is pure read — one node -e that requires a JSON file and prints to stdout. It was blocked:

node -e "const j=require('./qa/platform-smoke.test.json'); …
  console.log('  roundtrip steps:', (sc.steps||[]).map(st=>st.action||st.type).join(' → '));
  console.log('  teardown:', …);"

The hook reported:

⛔ Blocked: this Bash command WRITES into the shared PRIMARY checkout, not a worktree.
   target:  st.action||st.type).join( → ));
            console.log(  teardown:,
   repo:    /home/user/objectstack

The target it extracted is a fragment of my JavaScript string, split at the (U+2192) inside .join(' → '). Nothing is redirected and nothing is written; the arrow is a display separator in a log line.

Re-running with .join(' then ') — same command, same file, same read — passed immediately. That is the isolating experiment: the arrow character alone decides it.

Why this is worth fixing rather than working around

The guard's own header says anything it cannot parse with confidence is allowed through. Here it parsed with false confidence: it produced a concrete target from a character that is not a shell operator in any position. A guard that names a specific target is much more convincing than one that says "unsure", so the failure is more likely to be trusted and worked around.

And the documented way around it is OS_ALLOW_MAIN_EDITS=1 — the switch that disables the guard for that call. An agent that hits this on a read-only command has every reason to reach for it, and the next command it runs under that flag may not be read-only. False positives on safe commands are how a write guard gets trained out of the workflow.

Suggested direction

Match redirection on the ASCII operators only (>, >>, 2>, &>, <>), and do not treat any non-ASCII codepoint as one. all plausibly appear in log strings, and in particular is already in this repo's own CLI banner output (➜ API:, ➜ Console:), so a command that echoes or greps a boot banner can hit the same shape.

A regression probe worth adding to guard-main-checkout-bash.selftest.sh: a node -e/echo whose string literal contains , asserted to be allowed.

Scope note

Only the Bash-side guard is affected — guard-main-checkout.sh (Edit/Write/NotebookEdit) does not parse shell text. Verified on 19f98fa1.

Filed unassigned; the file lives under .claude/hooks/, so routing is the skills lane's call.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions