fix(gate): classify the scripts an agent runs, not just the command line (v0.448.7) - #840
Merged
Merged
Conversation
…ine (v0.448.7) On globex a billing agent wrote a Stripe teardown (card detach, sub cancel, customer delete) into a .sh file and ran `bash <file>`; the gate saw a green shell call and two live accounts were changed with no human in the loop. A shell call that executes a file changed during the run or in the last 24h now has that body checked against the workspace's custom patterns (line by line) and the unambiguous destructive ops. Scoped from a week of replayed globex traffic: 1,754 decision flips for the broad version, 5 for this one. Linear-time: an unanchored lookahead pattern over a 30 KB blob cost 0.6s of blocked event loop per call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Problem
On globex, billing-ops wrote a Stripe teardown (card detach, subscription cancel, customer delete) into
fsNNNN-execute-stripe-teardown.shand ranCONFIRM=EXECUTE bash <file>. The gate classifies the command line only, sawbash <file>, and allowed it green. Two live customer accounts were changed with no human approval. The samephp sdel.php …typed directly would have matched the tenant's guardrail.Fix
src/governance/script-bodies.tsfinds the script operands a shell call executes (bash x.sh,./x.sh,php x.php,python3 x.py,source x,bash -c "…", trackingcd). It reads them server-side, bounded, and follows nested scripts.enrichArgstakes those bodies. It checks them against the workspace's custom patterns (line by line) and the unambiguous destructive ops (DROP/TRUNCATE TABLE, mkfs, dd, terraform destroy, kubectl delete, force-push). The audit row getsscriptsInspected.TerminalManager.gateandpolicyCheck, so the preview matches the gate.Scoping, measured on a week of real globex traffic (39.5k shell calls)
rm -rf "$tmp", generic "delete/prod" words)freescout-manager.php … replydenied FreeScout reads)Performance: an unanchored
(?=[\s\S]*…)operator pattern over a 30 KB blob cost ~0.6 s of blocked event loop per call. Script bodies are now pattern-matched line by line, so the same case takes 4 ms. A perf check in the test pins this.Limits (documented in the module)
This is text matching, not a sandbox. download-and-run, base64 and eval still hide intent. The hard stop for money is a read-only credential. For the incident tenant, that change is pending in Stripe.
Test
scripts/script-body-gate-test.cjs(added totest:governance): parser, bounded/fresh reading, enricher facts, noise regressions, a perf guard, and end to end throughTerminalManager.gate. The fulltest:governancesuite and the web build pass.🤖 Generated with Claude Code