Ten of eleven open-source AI coding agents — with roughly 548,000 combined GitHub stars — check a shell command's raw text for danger before running it, then hand that same text to bash, which rewrites it through quote handling, variable expansion, command substitution, and encoded pipelines before actually executing anything. r''m looks nothing like rm to a regex. Bash deletes the empty quotes and runs it anyway.
That gap has a name now: GuardFall, disclosed by Adversa AI on June 30, 2026, after live penetration testing against eleven popular agents — Hermes, opencode, Goose, Cline, Roo-Code, Aider, Plandex, Open Interpreter, OpenHands, SWE-agent, and Continue — ranked by GitHub stars. Ten failed. One didn't. The difference between them is the entire lesson here, and it applies directly to any platform, including a self-hosted PaaS, that lets an agent run a shell command as part of a build, deploy, or rollback step.
The Filter Reads Text. Bash Reads Meaning.
Every vulnerable agent in the study made the same architectural choice: inspect the command string an LLM generated, decide whether it looks safe, then pass that string to a shell. The problem is that "looks safe" and "is safe" are answered by two different parsers reading two different things. A regex-based guard sees the command as literal characters. Bash sees the command as a grammar — one with quote removal, parameter expansion, and substitution rules that rewrite the literal text into something else entirely before a single byte reaches the kernel.
This isn't a new class of bug. Every technique GuardFall catalogs has existed in shell-scripting literature for decades; sysadmins have been warning about $IFS tricks and quote-splitting since long before LLMs existed. What's new is the blast radius: an autonomous agent that generates its own commands, often from untrusted input like a README, a Makefile target, or an MCP tool response, and then executes what it generated with the user's full account permissions — SSH keys, cloud credentials, and all.
Five Ways Bash Disagrees With a Regex
Adversa AI's researchers grouped the working bypasses into five classes, each defeating a different assumption a naive text filter makes:
| Class | Technique | Example | What the filter sees vs. what bash runs |
|---|---|---|---|
| A — Quote removal | Bash strips empty quote pairs before execution | r''m -rf / | Filter sees a string unlike rm; bash deletes '' and runs rm -rf / |
B — $IFS expansion | The internal field separator variable splits one "word" into multiple argv tokens | rm$IFS-rf$IFS/ | Filter sees one unbroken token with no spaces; bash expands it into three arguments: rm, -rf, / |
| C — Command substitution | $(...) runs an inner command and substitutes its output | $(echo rm) -rf / | Filter sees no literal rm; bash resolves the subshell first and executes rm -rf / |
| D — Base64-to-shell | Each pipeline stage is benign alone; the payload only exists after composition | echo <base64> | base64 -d | sh | Filter sees an echo and two pipe stages, none individually dangerous; bash runs the decoded script |
| E — Alternative destructive argv shapes | Denylists built around rm miss every other binary that can destroy data | find /x -delete, dd of=/dev/sda, tar -C / -x, install -m 4755 payload /usr/bin/backdoor | Filter has no rm to match on; each tool does real damage through its own flags |
None of these require exotic tooling — every example runs on stock bash. That's the point: a filter built to pattern-match "does this look like a dangerous command" is fighting a shell grammar that has forty years of expansion rules built specifically to rewrite text before execution.
Ten Agents, Four Ways to Fail
GuardFall's per-agent results split into four distinct failure modes, not one uniform bug:
| Failure mode | Agents | What's actually broken |
|---|---|---|
| Regex on raw string | Hermes, opencode, Goose | Pattern matching runs on the verbatim LLM output before bash ever touches it; all five classes bypass cleanly (opencode leaked 16/16 probes, Goose 22/23) |
| Tokenized but still matches raw text | Cline, Roo-Code | Some tokenization exists, but the matcher still inspects text, not post-expansion structure; classes C, D, and E leak through (Roo-Code leaked 4/18 probes; Cline 2–8/13, mode-dependent) |
| No static guard, relies on auto-yes | Aider, Plandex, Open Interpreter | Human approval is the only defense, and it disappears the moment an auto-execute flag is set — including via a repository's own config file, like .aider.conf.yml, silently flipping auto-test on |
| Sandbox by default, unprotected opt-out | OpenHands, SWE-agent | Containerized execution is genuinely sound, but a documented "not recommended" local mode disables all of it, and teams reach for local mode for CI speed |
Continue was the sole pass — 0 of 21 probes leaked — and it didn't get there by writing a better regex. It runs commands through a five-stage evaluator: tokenize with a real shell-quote parser (closes Class A), detect variable expansion like $IFS and escalate rather than ignore it (closes Class B), recursively evaluate command substitution outside of quotes (closes Class C), block pipes that terminate in sh, bash, python, or node (closes Class D), and finish with an explicit disabled list for canonical destructive shapes like rm -rf /(usr|etc|home|var|opt) and mkfs.* (addresses Class E). Each stage hands the next one a structurally correct input — the whole point being that you can't detect $IFS abuse by regex if you haven't already parsed the quoting correctly, and you can't catch command substitution if variable expansion hasn't already been resolved.
That's the actual finding: the difference between "10 vulnerable" and "1 safe" isn't more rules, it's parsing the command the same way the shell that will run it does, in the same order.
Why There's No CVE to Patch
Adversa AI didn't file a CVE against any of the ten failing agents, and that's a deliberate choice, not an oversight. A CVE identifies a specific, patchable defect in a specific version of a specific component. GuardFall isn't that — it's a convention repeated independently across ten unrelated codebases: an agent proposes command text, a permission gate inspects that text, and a shell interprets something structurally different from what the gate saw. Patching one regex closes one bypass and leaves the other four classes untouched, because the regex was never the actual point of failure. The researchers frame it explicitly as "not a bug, but a dangerous convention and a class of problems" — which is also why the fix that worked wasn't a better denylist, it was Continue rebuilding the evaluation pipeline around the shell's own grammar.
Exploiting any of this also needs only two conditions to line up, and both are already common in how these agents get used. First, the agent has to generate or relay a malicious command — which doesn't require a jailbroken model, just a booby-trapped input it's already trusted to read: an injected README, a Makefile target, a malicious MCP server's tool response, or a repository config file that flips an auto-test flag the moment the agent checks it out. Second, the agent has to actually run what it generated without a human catching it first, which is precisely the mode CI pipelines and "hands-off" agent workflows are built to enable. Neither condition is exotic on its own; autonomous execution against untrusted repository content is close to the default configuration for a coding agent wired into a CI job.
What This Means for an Agent-Operated Deploy Pipeline
A self-hosted, git-push PaaS built around agents as first-class operators — the entire premise Bex.co is built on — runs exactly the kind of tool GuardFall is warning about: an MCP tool that lets an agent trigger a build, run a rollback, or execute a one-off command against a deployed service. If that tool's permission gate checks the pre-expansion text an agent proposes and then hands the post-expansion command to a real shell, it inherits the identical structural flaw, regardless of how carefully the denylist is written.
The fix isn't a smarter regex; GuardFall demonstrates that road doesn't end. It's structural, and it's directly portable from Continue's own approach:
- Tokenize with an actual shell-aware parser before any safety decision, not string matching on what the model wrote.
- Escalate on expansion syntax (
$IFS,${VAR}, command substitution) instead of trying to predict what it resolves to — if a permission gate can't determine the final argv with certainty, it should ask a human, not guess. - Evaluate the post-expansion command, not the pre-expansion one — the security decision has to happen on the same representation bash is about to execute, which usually means resolving substitutions in a sandboxed evaluator first.
- Separate operational filters from security filters. A check that exists to stop an agent from hanging on a long-running process is not the same control as one meant to stop it from running
dd of=/dev/sda, and treating them as interchangeable is how "we already have a filter" becomes false confidence. - Distrust repository-supplied configuration. A Makefile target, a
package.jsonscript, or an agent config file living inside the repo an agent is operating on is attacker-controlled input the moment that repo can come from a fork, a webhook, or an untrusted contributor — the same class of risk as an MCP server returning a malicious tool response.
The immediate, no-code-change mitigations Adversa AI recommends apply just as directly to a deploy pipeline: scope $HOME to a sandboxed directory before an agent's shell step runs so a compromised command can't reach real SSH keys or cloud credentials, disable auto-execute flags in CI unless a human genuinely cannot be in the loop, and build a small regression harness seeded with GuardFall's five bypass classes that runs against your own agent-callable tools on every release — because, as the researchers put it, this isn't a single patchable bug. It's a convention — agent proposes text, a gate inspects that text, a shell interprets something else — and the convention itself is what fails.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with AI agents as first-class operators. Star the repo on GitHub or deploy your first app today.
Sources
- AI coding agents vulnerability: GuardFall shell injection | Adversa AI
- GuardFall Exposes Open-Source AI Coding Agents to Decades-Old Shell Injection Risks | The Hacker News
- Shell injection flaw found in 10 of 11 open-source AI agents | SC Media
- GuardFall Flaw Hits 10 of 11 Popular Open-Source AI Agents | Security Affairs
- Decades-Old Bash Tricks Expose AI Coding Agents to Supply Chain Attacks | SecurityWeek
- GuardFall Shell Injection Bypass Affects Most Open-Source AI Coding Agents | Mallory
All figures and the per-agent results cited above are drawn directly from the linked sources.



