DepWall

Home / Blog

  • ai-agents
  • claude-code
  • cursor
  • prompt injection

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#

LayerQuestion it answersCan the agent route around it?
Prompt / rules fileShould I be careful?Yes — it is text in a context window.
Agent hookIs this tool call allowed?Sometimes — depends on the harness.
Shell-level gateIs this package safe to pull?Not by choosing a different command.
SandboxWhat can the code reach once running?No — but it runs the code.
CI scannerIs 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.