Skip to content

Mirror the guard-main-checkout-bash.sh quote-escape fix to objectui, whose copy is declared case-for-case identical #10408

Description

@qq9340100

Found while fixing #10247 (PR #10406); filed unassigned rather than fixed in that PR, whose declared file surface is this repo's two hook files only.

The drift

.claude/hooks/guard-main-checkout-bash.sh carries this in its own header:

Ported from objectui's hook of the same name (objectstack-ai/objectui#3452, filed there as objectui#3435) — the logic below is deliberately kept case-for-case identical to it so the two repos' guards cannot drift; only issue references, example paths and the package name in the self-test are localised.

PR #10406 changes the parsing logic in this repo's copy: a backslash-escaped \" inside a double-quoted word no longer ends the quote (POSIX — backslash keeps its meaning inside "…" only before ", \, $ and a backtick). objectui's copy is, by that header's own claim, still the pre-fix logic, so the two have now drifted in exactly the way the header says must not happen.

Why it matters beyond tidiness

The bug being fixed is not cosmetic. In objectui's copy, as in this one before the fix:

  • a pure-read node -e "…" whose program contains an escaped quote followed by a JS arrow function gets blocked with a confidently-wrong write "target" — the false positive that trains agents onto OS_ALLOW_MAIN_EDITS=1;
  • and, measured under ablation in fix(hooks): a backslash-escaped quote must not end a double-quoted word in the Bash write guard #10406, the same desync makes the guard miss real writes: sed -i "s/\"a\"/\"b\"/" pkg/x.ts was allowed through. That is precisely the reflexive sed -i the guard exists to catch, so objectui's shared checkout is currently unguarded against that shape.

Suggested shape

Port the two hunks and the self-test section from PR #10406 into objectui's .claude/hooks/guard-main-checkout-bash.sh and guard-main-checkout-bash.selftest.sh, localising issue references per the existing convention. The self-test port matters as much as the logic: the probes are what keep the two copies honest.

Worth deciding at triage whether "case-for-case identical" is worth a gate rather than a header comment — a check that diffs the two copies modulo the localised lines would have caught this drift at the moment it was introduced, instead of relying on the next reader of the header.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions