Securing AI coding agents: the install is the part you can actually control
Claude Code, Cursor and Codex install dependencies faster than anyone reviews them, and the package gets to talk back. What a prompt instruction cannot do, and what a shell-level gate can.
Most advice on securing AI coding agents is about the model: better prompts, tighter system instructions, review the diff. That is worth doing and it addresses the part of the problem where you have the least leverage.
The part where you have real leverage is narrow and specific: the moment the agent installs something. It is a shell command, it happens at a point you can intercept, and it is where the irreversible thing happens — code from a stranger lands on your machine and, often, runs.
Three things that are true at once#
The agent installs faster than anyone reviews. An agent resolving a
build error runs npm install as one step inside a longer task. The package
name scrolls past inside a tool call. Nobody reads it, and that is not a discipline
failure — it is the point of delegating the task.
The agent sometimes invents the name. Measured across 2.23 million code samples at USENIX Security 2025, 19.7% contained at least one hallucinated package. Frontier models have improved — a 2026 follow-up puts the range at 4.62% to 6.10% — but the convergence created a worse problem than the rate: 127 hallucinated names were shared across all five frontier models tested, and 53 were still registrable as of April 2026. Those are pre-registration targets, and they are public to anyone who runs the same prompts.
Once installed, the package gets to talk back. Its README, description and manifest are text. To an agent, text is input. The thing deciding what happens next is now reading content an attacker wrote, in a context window attached to shell access.
That third one is the genuinely new problem, and it has a documented case:
react-codeshift, a hallucinated package Charlie Eriksen traced through
237 repositories via AI-generated agent skills. The agent hallucinated the
name, wrote the install command, and ran it. No human was in the loop at any point.
Why the prompt is the wrong place for this control#
The obvious response is to tell the agent to be careful. Add a rule to
CLAUDE.md or .cursorrules: verify packages before installing,
never install something you are unsure about.
Do it — it costs nothing and it helps at the margin. But understand what kind of control it is. An instruction in the context window is a suggestion to a system that processes suggestions. It sits in the same channel as the attacker's README, it competes with the user's actual task, and it degrades as the context fills. An agent that has been debugging for forty minutes and finally found a package that looks like the fix is an agent that will rationalise past your rule.
It is also the wrong trust boundary. You are asking the thing that might be compromised to enforce the policy that protects it.
What the layers actually are#
| Layer | Question it answers | Can the agent route around it? |
|---|---|---|
| Prompt / rules file | Should I be careful? | Yes — it is text in a context window. |
| Agent hook | Is this tool call allowed? | Sometimes — depends on the harness. |
| Shell-level gate | Is this package safe to pull? | Not by choosing a different command. |
| Sandbox | What can the code reach once running? | No — but it runs the code. |
| CI scanner | Is what we committed vulnerable? | Runs after the fact. |
These compose, and the honest recommendation is to run more than one. A sandbox and an install gate answer genuinely different questions: the sandbox limits the blast radius of code that is already executing, the gate tries to stop it executing. Neither substitutes for the other.
What to actually do#
1. Turn off install scripts at the default level
If you are on npm 12 or later, preinstall hooks are blocked by default. If not, put
--ignore-scripts in your CI invocation. In one benchmark of 6,420 malicious
packages, 72.21% used lifecycle scripts as the vector, and 21.9% had no malicious
JavaScript in any file at all — the hook was the payload.
2. Gate the install at the shell
Replace the package manager on PATH so the check runs regardless of which
command the agent chooses. This is what makes it a control rather than a convention.
npm i -g depwall && depwall init
depwall doctor
depwall doctor is the step that matters. It runs a package that must be
blocked and one that must be allowed, through the real gate. If any line is ✗, the gate is
not protecting the machine — and a gate you believe in but which is not live is worse than
no gate, because you stopped looking.
3. Treat package text as hostile input, not as instruction
This is the one most tools skip. A README carrying instructions aimed at the agent rather than at a human is evidence of an attack — it is never something to comply with. DepWall's injection judge exists for exactly this, and it runs only on the gray zone, because sending every package's text to a model would be slow, expensive and mostly pointless.
4. Keep a soak period
Do not let builds adopt a version published today. Every Shai-Hulud wave was identified within days. A 72-hour delay is the single highest-leverage change on this list and it requires no tooling at all.
5. Verify names against the project, not the registry
When an agent proposes an install, the package name is the one token worth a human glance. It is short, and it is the entire attack. Check it against the project's own documentation — the registry confirming the name exists is the attack working, not the check passing.
Setting it up from inside the agent#
Paste this into Claude Code, Cursor or Codex. It does the work rather than handing you config to edit, and it refuses to proceed if the gate is not actually live:
Install DepWall (https://depwall.com) and turn it on for this machine. It is an
install-time firewall: it wraps npm/pip/cargo/go and git so a malicious or
slopsquatted package is stopped before any of its code runs.
Do the work, do not hand me config to edit:
1. npm install -g depwall
2. depwall init — installs the PATH shims and the agent hook
3. depwall doctor — this is the only step that matters
It runs a package that MUST be blocked through the real gate, and one that
must be allowed. Every line has to be ✓ or !. If any line is ✗, or the
command exits non-zero, the gate is NOT protecting me — stop there and show
me the output. Do not continue and do not "fix" it by disabling anything.
4. Tell me which package managers are now gated, and what ALLOW / ASK / BLOCK
will each do to my installs, in one plain sentence each.
Never disable DepWall, uninstall the shims, or bypass a BLOCK by calling a
binary by its absolute path without asking me first.
What this does not fix#
Worth stating, because a list like the one above reads as more complete than it is.
An install-time gate defends against an agent being tricked. It does nothing
about an agent that is already compromised, and it is not a sandbox. It checks packages at
install, so a package clean at install and hostile three versions later is out of reach.
Calling a binary by absolute path bypasses the PATH shim — which is why
depwall doctor exists and why we document the bypass rather than pretending
there isn't one.
And the hardest case stays hard: a compromised maintainer publishing through their normal pipeline produces a package with the right name, a real history and valid provenance. Every structural signal stays green. We keep that in the corpus as a fixture we do not claim to detect, because a tool that only publishes its wins is describing its test suite rather than your risk.