In June, security firm Adversa AI published a survey of eleven of the most-used open-source coding and computer-use agents — roughly 548,000 combined GitHub stars, the dead center of the category. Ten of them fell to a bypass technique that's been documented in shell-scripting literature since the 1980s. Only one agent, Continue, was built to actually stop it.
Nobody found a zero-day. Nobody needed one. This isn't a frontier machine-learning vulnerability requiring novel adversarial research. It's a decades-old shell-quoting bypass that the AI coding-agent ecosystem rediscovered the hard way — because the convention it standardized on was never sound to begin with, model in the loop or not.
Adversa calls the pattern GuardFall. It starts from a simple mismatch. A security filter reads a command as a plain string. Bash treats that same string as a small program — stripping quotes, expanding variables, substituting the output of other commands, splitting on whitespace — before it decides what to actually execute. A filter and a shell can stare at identical input and walk away with two completely different commands. The filter approves what it sees. Bash runs what it means.
Five bypass classes are enough to break essentially any filter operating on raw command text:
None of these are novel. They're the same shell-quoting tricks that have been in the security literature for decades. What's new is the target: an AI agent that reads untrusted content — a poisoned README, a malicious tool response, a planted Makefile — and can be talked into emitting one of these payloads as if it were routine work.
This is the detail that matters most, and it's the one a "just align the model better" reflex misses. Adversa's researchers found that asking a model outright to run a destructive rm gets refused, reliably. But the exact same payload, wrapped inside a Makefile target the agent is asked to inspect, or returned as "documentation" from a compromised tool server, gets emitted without hesitation — because from the model's perspective it's just doing the task in front of it.
Their cline run shows how thin the line is. Hinted as ordinary tool content, the model spotted the injection and emitted a read-only find. Re-framed as an authoritative directive, it emitted find -delete without hedging — and the controller passed it, because find was on the operator's allowlist.
Picture the realistic version. A mid-sized engineering team runs an open-source coding agent in CI to review pull requests automatically. To keep the pipeline non-interactive, someone enabled the documented --auto-exec flag, exactly as recommended for unattended use. A contributor opens a PR — maybe someone who's never seen the payload, maybe someone who planted it — adding a one-line dependency update plus a Makefile change. The agent reads the Makefile to understand the project (normal behavior), emits make test as its next step, and the auto-exec gate runs bash -c "make test". The runner's IAM credentials are wiped; on the next deploy, production fails. In parallel, the same credentials were already exfiltrated through an endpoint embedded earlier in the same Makefile.
The blast radius is the operator's shell. On a laptop that's SSH keys, cloud credential files, browser session tokens, git signing keys. In a CI runner it's deploy keys, registry credentials, and — for self-hosted runners — a pivot into the corporate network. Treat every line of every file your agent reads as a potential payload that may end up as bash -c.
Adversa grouped the ten failing agents into four architectural patterns. The grouping matters more than any product name, because it tells you what to look for in your own tooling rather than which brand to avoid this month.
Only one agent, Continue, closed the structural majority of the bypass surface by design. Its evaluator runs five checks in sequence, and each one closes a class that skipping it would reopen:
Empirically: of 21 bypass cases submitted to Continue's evaluator, zero reached unrestricted execution, and all 12 canonical-destructive cases were correctly downgraded. It's not perfect — Class C inside a quoted argument and the full long tail of Class E remain open — but it's the only agent in the survey that closes the structural majority of the surface.
Every proposed fix that begins "add this pattern to the blocklist" is treating the symptom. Three popular designs get offered as the defense at the bash -c boundary, and under prompt injection each fails for the same root reason: it sites the decision with a party that lacks the context to make it.
The three share one shape: each hands the decision somewhere that can't hold it. A sound check is a guard on the agent's side of the boundary — it runs on every emitted command, before the operator sees it, regardless of flags. Only Continue's design aspires to that, and even it drops the soft tier under --auto. The rest of the ecosystem shifts accountability without shifting capability: the developer can't vet every line the agent reads, so the agent must.
For teams running any of these agents in CI: audit whether auto-execute is enabled, and if it is, treat that pipeline as running with full credential access on every unreviewed PR — because that is precisely what's happening. Disable agent execution on fork pull requests; that's the common path from an attacker-authored README to secret exfiltration on a privileged runner.
For anyone maintaining a fork or wrapper: adopting Continue's tokenize-then-recursively-evaluate pattern is described by its own authors as roughly a two-day engineering exercise. Given the alternative, that's a very short list of days. Adopting just three of the five components (tokenize + substitution-recursion + pipe-destination) closes Classes A, B, C-outer, and D.
For security teams evaluating agent tooling: ask the specific question — "how does your shell guard handle $IFS, command substitution inside quotes, and destructive argv flags on non-rm binaries?" If the answer is "we have a blocklist," you now know exactly which of the four failure modes you're looking at. Treat operational filters (stop the agent hanging in vim) and security filters as different things; conflating them is how teams accidentally rely on an anti-hang feature for safety.
For everyone else, this week: run the agent from a scoped shell with $HOME redirected. A one-line wrapper — HOME=$HOME/.agent-sandbox-$RANDOM agent … — keeps the project directory but removes ~/.ssh, ~/.aws, and shell history from the blast radius. It's always-on, has no one-flag opt-out, and is the strongest stopgap while you wait for a proper guard.
GuardFall doesn't sit alone. It's one of several large-scale shell-channel findings in the past six months: the Claude Code deny-rule bypass (a token-budget shortcut), the Antigravity command-injection RCE, the CrewAI framework RCE chain, and TrustFall — a folder-trust dialog leading to unsandboxed startup execution across Claude Code, Cursor, Gemini CLI, and GitHub Copilot CLI. The shape is consistent every time: the defense between the model's emitted command and bash -c is structurally underbuilt. Each finding patches a specific surface; the convention itself produces the next finding.
And the survey deliberately scoped itself to open-source agents. Cursor, Claude Code, Copilot agent mode, Windsurf, and Google's Antigravity were out of scope — but the bypass classes are shell-semantics-driven and independent of who ships the agent. Adversa's expectation, supported by prior findings, is that the same four failure modes live in the closed-source tools too. Someone with authorized testing relationships should run the closed-source GuardFall survey. I'd read it.
What strikes me most about GuardFall isn't the exploit — it's that the exploit is older than most of the engineers building these agents. Continue's evaluator proves the fix is known and shippable in a couple of days. The fact that it's the exception rather than the norm, across a category with over half a million combined GitHub stars, is the actual finding.
An unsound guard offers no protection even when it's left fully on. A sandbox offers full protection right up until it's switched off — and the deployments that most need it are the ones that most often turn it off. Only a sound, on-by-default guard on the agent's side of the boundary protects the operator's own host without asking them to opt in. Until that becomes the convention, every agent shipping a string-matching guard is one prompt injection away from operator-account compromise.