diff --git a/packages/mosaic/framework/tools/git/test-wrapper-guard.sh b/packages/mosaic/framework/tools/git/test-wrapper-guard.sh index 60f51241..97270be1 100755 --- a/packages/mosaic/framework/tools/git/test-wrapper-guard.sh +++ b/packages/mosaic/framework/tools/git/test-wrapper-guard.sh @@ -67,6 +67,13 @@ FIXTURES="$TMP/fixtures.tsv" printf '0\t{"tool_input":{"command":"python3 -c '"'"'print(\\"curl -d https://git.example.invalid/api/v1/repos/a/b/issues\\")'"'"'"}}\tprinting an example is not calling it\n' # Command position must still catch the real thing behind operators and env. printf '2\t{"tool_input":{"command":"cd /tmp && GITEA_TOKEN=$T curl -d@b https://git.example.invalid/api/v1/repos/a/b/pulls/1/merge"}}\ta real call behind && and an assignment is still a call\n' + # --- and the case the AUTHOR hit, one level in from the reported one: an + # operator INSIDE a quoted string is not an operator. This blocked a message + # that merely quoted the fixture above. Position is judged on the skeleton. + printf '0\t{"tool_input":{"command":"send.sh -m \\"repro was: cd /tmp && curl -d@b https://git.example.invalid/api/v1/repos/a/b/pulls/1/merge\\""}}\tan operator inside a quoted string is not an operator\n' + printf '0\t{"tool_input":{"command":"cat >> notes.md < "$FIXTURES" fail=0 n=0 diff --git a/packages/mosaic/framework/tools/git/wrapper-guard.sh b/packages/mosaic/framework/tools/git/wrapper-guard.sh index 35844b6d..ab26c75b 100755 --- a/packages/mosaic/framework/tools/git/wrapper-guard.sh +++ b/packages/mosaic/framework/tools/git/wrapper-guard.sh @@ -85,23 +85,46 @@ fi # and the host-anchored literal never appears, so the check read clean while the # write went through. The endpoint fragments below survive it, because the # fragment has to appear somewhere for the URL to be constructible at all. -# The client must be at COMMAND POSITION — start of the command, or directly -# after a shell operator, optionally behind VAR=value assignments. Substring -# presence is not enough, and this is the second thing review caught: with a -# bare substring test, +# The client must be at COMMAND POSITION, and that has to be judged against the +# CODE in the command, not against its text. Review caught the text version +# blocking ordinary work: # grep -R "curl -d https://host/api/v1/repos/a/b/issues" docs/ # echo "curl -d https://host/api/v1/repos/a/b/pulls" > note.txt -# were both BLOCKED. Talking about a call is not making one. Over-blocking is -# not the safe direction here — a guard that blocks ordinary work gets switched -# off, and a guard that is off permits everything. +# Talking about a call is not making one, and over-blocking is not the safe +# direction: a guard that blocks ordinary work gets switched off, and a guard +# that is off permits everything. # -# Quoting is what separates the two: in every false positive the client sits -# immediately after a quote character, never after an operator. Note the -# deliberate absence of quote-stripping: the URL is frequently quoted in REAL -# calls, so stripping quotes before matching would blind the endpoint check. +# A first fix required the client to follow a shell operator. That lasted until +# the author sent a message quoting one of these fixtures — the quoted text +# contained `... && GITEA_TOKEN=$T curl -d@b .../merge`, so an operator appeared +# INSIDE the quotes and the guard blocked the message. Same defect, one level +# in: an operator inside a string is not an operator. +# +# So the position test runs against a SKELETON — the command with its data spans +# (quoted strings, heredoc bodies) removed. Endpoint, URL and body detection all +# still run against the FULL text, because real calls quote their URLs and a +# skeleton would be blind to them. +# +# The exception is the reason quotes are data at all: if something is about to +# EXECUTE the quoted text (`bash -c`, `sh <