Your Coding Agent's Allowlist Is Not a Sandbox
If you run a coding agent unattended, there is one setting you almost certainly trust more than it deserves: the command allowlist. You give the agent a short list of commands it may run without stopping to ask you, flip on auto-run, and let it work through a task queue while you do something else. The allowlist is the thing that makes that feel safe.
In August 2026 that trust took a concrete, vendor-acknowledged hit. Cursor published a security advisory for a flaw that let an agent execute commands the operator never approved, even with allowlist mode switched on. The interesting part is not that one product had a bug. It is the reason the bug worked, because that reason applies to every permission allowlist in every coding agent on the market, including the one this site runs in production.
The real bottleneck: you approved throughput, not safety
Teams reach for auto-run because human approval is the slowest part of an agentic workflow. A senior engineer clicking "allow" on every git status and npm test is expensive, and after the fortieth prompt they stop reading and start clicking. So the allowlist exists to buy back that time: pre-approve the boring, safe commands once, and let the agent run them freely.
That trade is reasonable. The problem is what the operator believes they bought. Most people read an allowlist as a safety boundary, a sandbox wall that says "the agent can do these things and nothing else." It is not that. An allowlist is a list of command names. It says nothing about what those names will actually do when they run, and that gap is where the money and the risk both live.
Why the naive allowlist fails
Here is the mechanism, in plain terms. A command like git branch or python3 script.py looks harmless, so it ends up on the allowlist. But what that command does depends on more than its name. It depends on the environment it runs in: the PATH that decides which binary python3 resolves to, the variables a program reads to change its own behavior, aliases and shell settings that rewrite a command before it executes.
If an attacker can change that environment, they do not need to run a forbidden command. They re-point an allowed one.
Cursor's own advisory (GHSA-82wg-qcm4-fp2w, tracked as CVE-2026-22708) describes the entry point without naming the exact mechanism. It states that when the agent runs in Auto-Run Mode with Allowlist mode enabled, "certain shell built-ins can still be executed without appearing in the allowlist and without requiring user approval." The advisory carries a "High" severity label and no CVSS score, and it credits Dan Lisichkin of Pillar Security. It affects versions up to and including 2.2, and is fixed in 2.3.
The advisory deliberately stops there. The specific built-ins and the working technique come from the researchers who found it, and they should be attributed as such rather than read as vendor-confirmed detail. Pillar Security and the independent writeup by danusminimus describe shell built-ins such as export, typeset, and declare being treated as implicitly trusted and executed without approval. Because those built-ins set environment variables, an agent that was tricked by a poisoned instruction, an indirect prompt injection buried in a file it reads, could quietly change the environment. After that, the next "approved" command runs inside an environment the attacker controls. No forbidden command ever appears in the log. That is the whole trick: the allowlist checked the name and the name was fine.
None of this requires a weaponized payload to understand, and we are not publishing one. The lesson is structural. An allowlist enforces identity. Security wants to enforce behavior. Those are not the same guarantee, and the distance between them is exactly one environment variable wide.
This is not a Cursor problem
It is tempting to file this under "a bug in one editor, now patched." That reading misses the point. Any agent that gates execution on a list of command names inherits the same weakness, because the weakness is in the model of control, not in Cursor's code. Claude Code, which Effloow uses daily, works from an allow-rules list in .claude/settings.json. The same question applies to it and to every competitor: when a user approves a command, what can actually run under that approval once the environment around it is no longer trusted?
We have not reproduced an exploit against Claude Code, and we are not claiming one exists. The point is narrower and more useful: the class of question is portable even when the specific vulnerability is not.
Production architecture: audit the config, then contain the blast radius
You cannot fix this by reading your allowlist more carefully, because the danger is invisible at the name level. You need two things: a static check that flags the risky patterns before they ship, and an execution model that limits what a bypass can reach.
A config auditor you can run today
The tractable, credential-free move is a static scan over your agent's configuration. It looks for two classes of finding: allowlisted commands whose real behavior depends on environment variables an attacker could set, and configuration that executes on folder-trust before a human reviews anything. Here is the core of that check as a worked blueprint.
# agent_config_auditor.py — static triage over agent config files.
# Flags allow-rules whose behavior is environment-dependent, and
# auto-execution that fires before human review. Triage aid, not proof.
ENV_SENSITIVE = {
"python", "python3", "node", "npm", "npx", "pip", "git",
"make", "bash", "sh", "env", "docker",
}
# Shell built-ins that mutate the environment other commands read.
ENV_MUTATORS = {"export", "set", "declare", "typeset", "alias", "source", "."}
def audit_allow_rule(cmd: str) -> str | None:
head = cmd.strip().split()[0] if cmd.strip() else ""
if head in ENV_MUTATORS:
return f"CRITICAL: '{head}' can re-point later trusted commands"
if head in ENV_SENSITIVE:
return f"REVIEW: '{head}' resolves via PATH / env-controlled config"
return None
def audit_autoexec(entry: dict) -> str | None:
if entry.get("runs_on_trust") and not entry.get("user_reviewed"):
return "CRITICAL: executes on folder-trust before any human review"
return None
Point it at a synthetic fixture, a settings file with an allowlisted python3 build.py next to an allowed export, plus a folder-trust hook that runs on open, and it prints a per-entry risk table:
| Config entry | Class | Verdict |
|---|---|---|
export (allowlisted) |
env mutator | CRITICAL: can re-point later trusted commands |
python3 build.py (allowlisted) |
env-sensitive | REVIEW: resolves via PATH / env-controlled config |
git branch (allowlisted) |
env-sensitive | REVIEW: behavior depends on git config in env |
| folder-trust auto-hook | auto-exec | CRITICAL: runs before human review |
ls -la (allowlisted) |
inert | pass |
The value is not the code, which is deliberately simple. It is the reframing it forces: you stop asking "is this command safe?" and start asking "can anything on this list change the environment that the rest of the list runs in?" Any entry that can is a lever, not a leaf.
Contain what the audit cannot catch
Static analysis has a hard ceiling, and honesty about it is the whole credibility of the exercise. A scan sees names and config shapes. It cannot see intent that only emerges when a command runs against a poisoned environment at runtime. So the auditor is a triage aid, not a guarantee, and the real boundary has to be enforced by the execution model:
- Keep the agent off the host. Run unattended agents in a disposable container or VM with no standing credentials and no reach into production. A bypass then executes inside a box you can throw away.
- Treat environment mutators as high-risk, not routine.
export,alias,sourceand their kin should never sit silently on an auto-run allowlist. If the agent needs them, that is a per-use approval, not a blanket one. - Scope credentials to the task, not the session. The damage from any bypass is bounded by what the environment can reach. Short-lived, least-privilege tokens turn a critical finding into a contained one.
- Patch the known holes. For the specific CVE, the fix is Cursor 2.3. That closes this instance; it does not close the category.
What this is worth to a founder
The ROI here is not a number we can invent, and we will not pretend to one. It is a shift in where you spend attention. Enabling auto-run to save engineer time is a real, defensible efficiency. But the saving is only real if the boundary you are trusting is the boundary you think it is. An allowlist that approves names while an attacker controls behaviors is not a saving, it is deferred risk with your production credentials attached.
The decision is small and cheap to make well:
- When auto-run with an allowlist is fine: the agent runs in a throwaway sandbox, holds no production secrets, and the allowlist contains no environment mutators. Here the convenience is close to free.
- When to skip it: the agent runs on a developer laptop or CI host with live credentials, reads untrusted content (issues, PRs, web pages, dependency files), and the allowlist was written by asking "is this command safe" instead of "what can this command become." Here auto-run is a standing liability, and human-in-the-loop approval is the cheaper option once you price in a single bad night.
Running the audit costs an afternoon. Not running it costs you the assumption that your logs tell the truth about what your agent did.
For your engineers
The generalizable check is: enumerate every command your agent can run without approval, then for each one ask whether its resolved behavior is a function of the environment (PATH resolution, config files read from env, interpreter selection) or whether it can mutate that environment for later commands. The second set is your real attack surface. Wire the auditor above into CI so a new allow-rule that introduces an environment mutator fails the build, the same way you would gate a new outbound network permission. Pair it with runtime isolation, because config auditing and sandboxing catch different halves of the problem and neither is sufficient alone.
What Effloow added
We did not discover this vulnerability and we do not restate the researchers' work as our own. Pillar Security and danusminimus did the exploit research; Cursor published the advisory. What we added is the operator-facing translation: the reframe from "allowlist of names" to "allowlist of behaviors," a static auditor blueprint you can run against your own config without installing anything vulnerable, and the honest limit that static analysis is triage, not proof, so isolation has to carry the rest. The exploit specifics beyond the advisory's own wording are attributed to their researchers throughout, and no working bypass is published here.
For related reading on the same threat surface, see our guides on red-teaming LLM agents against OWASP failure modes and the agent spend cap that documents it can be exceeded — both cases where a control means less than its name implies.
Talk to Effloow
"What can actually run when a user approves this?" is the question an agent vendor pays to have answered about their own product, and it is precisely the work our Proof Studio does: claim-bound evidence about how a system behaves at its trust boundary, not a marketing recap. If you ship a coding agent, an MCP integration, or any tool that executes on a user's behalf, we can audit the boundary and produce the evidence your buyers ask for.
See what we build at /services, or tell us what you are shipping at /contact.
Primary sources
- Cursor security advisory GHSA-82wg-qcm4-fp2w — affected versions ≤ 2.2, fixed in 2.3, precondition Auto-Run + Allowlist mode, "High" severity, no CVSS score.
- CVE-2026-22708 record (cvefeed.io / NVD).
- Pillar Security, "The Agent Security Paradox: When Trusted Commands in Cursor Become Attack Vectors."
- danusminimus, "Cursor Allowlist Bypass (CVE-2026-22708)."
- Claude Code settings and permission allow-rules documentation (
.claude/settings.json).
Get the next one
in your inbox.
One short weekly dispatch with new guides, tools, and what we tested. No spam, unsubscribe anytime.
Get weekly AI tool reviews & automation tips
Join our newsletter. No spam, unsubscribe anytime.
More in Articles
Compare 2026 AI DevOps tools — Harness AIDA, Amazon Q, Datadog Bits AI, GitLab Duo, Copilot — on CI/CD, incidents, and IaC, with a source-checked cost table
Source-verified guide to Claude Code, Codex CLI, Gemini CLI, and Aider for terminal-based AI coding workflows in June 2026.
How to use Promptfoo 0.121 to red-team LLM apps against the OWASP LLM Top 10 2025. YAML config, CI/CD integration, and plugin mapping explained.
Complete guide to GitHub Copilot agent mode in JetBrains IDEs in 2026: inline agents, CLI agent, worktree isolation, MCP support, and Claude Opus 4.7.