hooks: strip heredoc bodies before dangerous-command scan#101
Open
truffle-dev wants to merge 1 commit intoghostwright:mainfrom
Open
hooks: strip heredoc bodies before dangerous-command scan#101truffle-dev wants to merge 1 commit intoghostwright:mainfrom
truffle-dev wants to merge 1 commit intoghostwright:mainfrom
Conversation
Closes ghostwright#100. The dangerous-command blocker regex-matches against the raw `command` string. Bodies of bash heredocs (cat > note.md <<EOF ... EOF) are data, not commands, so a journal entry or repro that quotes a forbidden phrase like "git push --force" or the docker-compose teardown invocation was tripping the blocker and refusing benign Bash invocations. Strip heredoc bodies from the scannable text before the pattern loop: /<<-?\s*['"]?(\w+)['"]?\n[\s\S]*?\n[ \t]*\1\s*$/gm Handles `<<DELIM`, `<<-DELIM`, `<<"DELIM"`, `<<'DELIM'`. The `[ \t]*` before the closing delimiter covers `<<-` heredocs where bash strips leading tabs from the terminator line. Real destructive commands outside the heredoc still match (verified by test). Tests added (hooks.test.ts): - allows heredoc body that names a forbidden phrase as data - allows heredoc with quoted delimiter and dangerous-looking body - blocks real dangerous command outside the heredoc - blocks dash-stripped heredoc opener with real dangerous trailing command Stash-bisect: 13/2 fail without the fix, 15/0 pass with the fix. This is option 2 from ghostwright#100 (heredoc-strip, no new dep). Echo/printf false-positives still exist; the long-term option 1 (shell-token-aware scan) is left for a future, larger PR. This narrow patch addresses the highest-frequency case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #100.
Problem
The
createDangerousCommandBlockerhook regex-matches against theraw
commandstring. Bodies of bash heredocs are data, not commands,so a journal entry, repro, or doc snippet that quotes a forbidden
phrase like
git push --forceordocker compose downwas trippingthe blocker and refusing benign Bash invocations:
The agent had no way to write the prose without the blocker firing.
Fix
This is option 2 from #100: strip heredoc bodies before the
pattern loop. No new dependency, no shell parser.
Handles
<<DELIM,<<-DELIM,<<"DELIM",<<'DELIM'. The[ \t]*before the closing delimiter covers
<<-heredocs where bash stripsleading tabs from the terminator line. A real destructive command
outside the heredoc still matches against the surrounding command
text that the regex leaves intact.
Tests
Four new cases in
src/agent/__tests__/hooks.test.ts:git push --force is forbidden<<'NODEEOF'body that says the docker-compose teardown phrasegit push --force origin main<<-EOF\n\tbody\n\tEOF\nrm -rf /Stash-bisect (stashing only
src/agent/hooks.ts, leaving the newtests in place) shows 13/2 fail without the fix, 15/0 pass with it.
What this leaves on the table
Echo/printf false positives still exist, e.g.
echo 'git push --force is bad'would still trip the blocker. Thatneeds option 1 from #100 (shell-token-aware scan with
shell-quoteor similar), which is a larger PR. This narrow patchaddresses the highest-frequency case the agent actually hits.
Verification
bun test src/agent/__tests__/hooks.test.ts— 15/15 passbun run typecheck— cleanbun run lint— clean (formatter normalized the new strings to one line each)origin/main(Resend domain, env-pollution between provider tests); none touched by this PR