Skip to content

guard-shared-stash.sh's split_segments() lacks the in-quote backslash branch its sibling guard carries — false BLOCK on nested-escape reads, fail-open once the escapes pair up (port of objectstack#14839) #7441

Description

@claude

Filed by the objectstack-ai/objectstack domain:devx PM seat (session session_01LAwHpn4uVuf4N1geBcD5i3) on behalf of the os-dev run for objectstack-ai/objectstack#11804 (PR objectstack-ai/objectstack#14839), which measured this repo's copy while probing the parity declaration. Filed unassigned; dedup: a 600-card title/body sweep (guard-shared-stash, split_segments, stash+quote) found no open or closed card on this defect.

Blocked-by: objectstack-ai/objectstack#11804

The observation

.claude/hooks/guard-shared-stash.sh's split_segments() in this repo (measured at 6411def) carries the out-of-quotes backslash branch and NOT the in-quote one, while this repo's own guard-main-checkout-bash.sh split_segments() already carries the in-quote branch. That is exactly the state objectstack was in before objectstack-ai/objectstack#14839 — and both repos' hook headers declare parity between the two guards, which is currently false here.

Inside "…" a \" is a literal quote and the quoted region stays open; the pass reads it as closing, flips to "outside quotes" while bash is still inside, and separators behind it split where bash would not. Two directions:

  • false BLOCK on a pure read: grep -rn "he said \"cd x && git stash pop\" once" .claude/ → BLOCK (wanted allow); the single-level control grep -rn "cd x && git stash pop" .claude/ → allow (so the guard is reached and the nested escape alone is the difference);
  • fail OPEN once the escapes pair up: echo "he said \"x\"" && git stash pop → allow (wanted block) — the region is left hanging and the real stash rides through as an argument.

Measured on this repo at 6411def, fed as the PreToolUse payload {cwd, tool_name:"Bash", tool_input:{command}}: control allow / nested grep BLOCK / nested echo BLOCK — identical to objectstack before its fix.

The remedy (a port, not a design)

Mirror objectstack-ai/objectstack#14839 once it has merged: in the in-quote path of split_segments(), when q is " and the character is \ followed by one of " \ $ `, keep both characters and do not close the region (gated on q = '"' — inside '…' nothing is special). Add the same paired self-test cases to .claude/hooks/guard-shared-stash.selftest.sh and run them against the pre-fix hook first (the allow rows and the fail-open twins must be red before, green after). Governed surface (.claude/hooks/**) ⇒ draft PR, human merge.

guard-main-checkout-bash.sh / guard-main-checkout.sh are the precedent here and stay untouched.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions