Guide
How do I stop AI coding agents from installing malicious or typosquatted packages?
Updated
Short answer
Lockfiles, pinning and a private registry limit what an agent can install. They only help, though, if the agent's install command stays inside them, and the agent writes that command itself. Check each npm, pip or curl-pipe-to-shell call at the agent's pre-execution hook, outside the agent, against what the session is supposed to be doing. Start in watch-only mode so you can see which installs agents actually attempt before you block anything.
Nobody has to trick your agent into running npm install. It runs it all day. What matters is whether this install, in this session, is one you'd approve.
How an agent ends up installing the wrong package#
There are two routes, and they need different defenses.
The first is a planted instruction. Help Net Security reported on coding agents following malicious instructions planted in the Downloads folder. The package in the case was function-color, part of a malicious campaign on npm.
It works through trust settings. Codex follows an AGENTS.md "only in a folder it trusts, and Downloads qualifies once the user has worked there." In the researchers' own testing, Codex ran the malware in more than 90% of attempts and Claude followed through about 50% of the time.
The second route is a made-up name. A study of 576,000 code samples found the average share of hallucinated packages was at least 5.2% for commercial models and 21.7% for open-source models. It recorded 205,474 unique invented names. An attacker only has to register one of them and wait.
What the standard controls do and don't stop#
To be fair to them, you should turn every one of these on.
- Lockfiles and pinning. They stop silent version drift in installs that follow the lockfile. They don't stop the agent running
npm install some-new-thing, which rewrites the lockfile to include whatever it fetched. - Private registry or allow-list. This is the strongest control over what can be fetched. It does nothing about
curl | sh, apip installfrom a raw Git URL, or an agent that edits.npmrcto point at a different registry. - Release-age gates. npm has a
min-release-agesetting. Per the npm docs it defaults tonull, so it's off until you set it. It targets freshly published versions and won't help against a package that was malicious from its first release. - Disabling install scripts.
ignore-scriptsdefaults tofalse, per the same docs. Set it totrueand npm stops running scripts from package.json files. The package's code still runs when your project imports it. - Permission rules and approval prompts. These help, but in Anthropic's study of 1,053 testers, humans caught only 13.6% of dangerous commands. Anthropic also reports that users approve 93% of permission prompts.
- Sandboxes. They limit what a bad package can reach. A package installed inside the sandbox is still in your project.
Why deny-lists miss it#
A deny-list matches names, and attackers rename.
A blocked package can come back under a new name, as an alias (npm install left-pad@npm:some-bad-pkg), from a Git URL or as a tarball. A hallucinated name was never on any list. There are far more ways to say "fetch and run this" than there are package names you've heard of.
What a useful check looks at#
The install command is half of what you need to judge. The session is the other half.
- What is the agent working on? A session fixing a Python test has no reason to pull in an npm package it has never touched.
- Where did the instruction come from? A package named in a file the agent just read from Downloads carries different risk from one the developer asked for.
- What else does the command do? A plain install is a different class of action from one that also changes the registry, edits config or pipes output to a shell.
Where the check has to run#
The check belongs at the agent's pre-execution hook. Claude Code's hooks documentation says its PreToolUse hook fires "before a tool call executes" and "can block it." Other agents expose similar hooks.
A control there sees the command before the shell does. Because it sits outside the agent's context, the agent can't argue its way past the decision.
Where Harden fits#
Harden Agentic Integrity Foundation (AIF) runs on the developer laptop, outside the agent, at that pre-execution hook. It parses each command, decodes encoded payloads and checks the action against the session's intent before it runs. Decisions take about 28 ms (P99 about 70 ms), are made locally and send nothing off the machine.
When an npm install, pip install or curl-pipe-to-shell doesn't fit the session, Harden stops it and gives the agent the reason so it can retry a safe way. If the check itself can't run, the action doesn't run either. Every decision is recorded and can be exported to your SIEM.
AIF starts in watch-only mode and is pushed by the MDM you already run, with one policy across every agent. It's a layer, not a perimeter. It doesn't replace a private registry, pinned dependencies, scoped credentials or least privilege, and a determined attacker who controls the code can defeat static analysis.
The same approach applies to deletes (stopping destructive commands) and to the broader laptop picture (securing coding agents on developer laptops).
A checklist for this week#
- Set a release-age gate and turn on
ignore-scriptsin the package manager configs you standardize on. - Route installs through a private registry and pin with lockfiles.
- Tell developers not to start agents in Downloads, and scan machines for stray AGENTS.md and CLAUDE.md files.
- Roll out a pre-execution check in watch-only mode and read what agents try to install until you know what normal looks like.
- Turn on enforcement for three cases: installs that don't match the session, registry changes and pipe-to-shell.
FAQ
Related questions
Do lockfiles stop an AI agent from installing a malicious package?
Only for installs that follow the lockfile. If the agent runs a new install command, the lockfile gets updated with whatever the agent fetched. You need pinning, but it doesn't stop this on its own.
What is slopsquatting?
An attacker registers a package name that AI models tend to make up, so an agent that trusts its own suggestion installs the attacker's package. One study of 576,000 code samples found at least 5.2% of packages were hallucinated for commercial models and 21.7% for open-source ones.
Should I start with watch-only mode or enforce right away?
Start watch-only. You'll see which installs agents attempt and which ones are legitimate. Then enforce on installs that don't match the session, registry changes and pipe-to-shell.
Does a sandbox solve this?
It limits what a bad package can reach, but the package still sits in your project and runs when it's imported. Keep sandboxes on and add a check before the install command runs.