Slopsquatting is a supply chain attack where an attacker registers a package name that AI coding assistants hallucinate, then waits for an agent to install it. Because the agent invents the dependency and runs the install unattended, malicious code executes with CI credentials. Blocking it takes registry-aware egress control, not code review.
What slopsquatting actually is
Typosquatting relies on a human fat-fingering reqeusts instead of requests. Slopsquatting relies on a model confidently producing a package that does not exist: a plausible-sounding helper library, a wrapper SDK for an API that never shipped one, a submodule that was renamed two major versions ago. The name is stable enough across prompts that an attacker can harvest hallucinated names, publish them to PyPI or npm with a functional-looking README, and let coding agents do the distribution.
The attack is attractive because the delivery mechanism is automated. Nobody reads the install line. A coding agent working through a task writes pip install langchain-openai-tools, the shell succeeds, the setup.py or npm postinstall script runs, and the payload has access to whatever the agent's environment holds: repository tokens, cloud role credentials, an SSH agent socket, a package registry publish key.
Why package hallucination in AI coding agents creates a new install path
Traditional dependency risk assumes a human commits a manifest change that a reviewer sees in a diff. Agentic development breaks three assumptions at once.
- The dependency decision is generative. The agent is not selecting from a curated list. It is emitting a token sequence that looks like a package name.
- Install and execution are the same step. Package managers run arbitrary code at install time. There is no gap between resolve and execute where a human can intervene.
- The loop retries. When an import fails, agents commonly try a near-miss name, a different registry, or
--index-urlpointing somewhere new. Failure pressure pushes the agent toward unapproved sources.
The hallucinated package install agent loop
A typical sequence inside a CI-run coding agent looks like this:
- The model writes code that imports a module it believes exists.
- The test run fails with
ModuleNotFoundError. - The agent decides to install the missing module, without verifying it against a lockfile or approved manifest.
- The package manager resolves the name against the public index and finds a match, because an attacker published one.
- Install scripts execute. Credentials in the environment are now readable by attacker code.
- The payload calls out to collect them.
Steps one through four are model behavior you cannot fully prevent. Steps four through six happen on the network, which is exactly where they can be stopped.
What a slopsquatting install looks like on the wire
Strip away the terminal output and a fake install is a short, very recognizable sequence of outbound calls:
- A metadata resolve:
GET https://pypi.org/simple/langchain-openai-tools/orGET https://registry.npmjs.org/@acme%2fai-sdk-helpers. - An artifact fetch from the CDN:
files.pythonhosted.orgorregistry.npmjs.org/.../-/pkg-0.0.1.tgz. - Then, seconds later, a call that has nothing to do with building software: a POST to an unfamiliar host, a DNS query with base64 in the label, a fetch of
169.254.169.254/latest/meta-data/iam/security-credentials/.
That third pattern is the tell. A legitimate dependency install talks to a registry and a CDN. It does not open a webhook to a domain registered last week. An egress proxy that inspects the request, not just the connection, sees both halves: the unapproved package name going out and the credential material trying to come back.
How to block malicious package registry calls from agents
Seven controls, ordered by how much risk they remove per unit of engineering effort.
- Default-deny egress from every agent runtime. Nothing leaves the sandbox unless a policy allows the destination. Allow your registry hosts and CDNs explicitly (
pypi.org,files.pythonhosted.org,registry.npmjs.org, your internal Artifactory) and deny the rest. This is the single control that turns a working payload into a failed connection. See the implementation detail in default-deny egress allowlists for AI agents. - Force resolution through one private registry. Point
PIP_INDEX_URLandnpm config set registryat an internal proxy with upstream caching, then block the public indexes at egress so an agent cannot bypass config by passing--index-url. A private registry with a curated allowlist simply has no entry for the hallucinated name. - Require lockfiles and fail on drift. Run installs with
pip install --require-hashes -r requirements.txt,npm ci,uv sync --frozen. Agents may edit manifests, but a lockfile plus hash verification means an unpinned invented name cannot resolve silently. - Inspect package names at egress, not only hosts. A host allowlist permits
pypi.orgin general. Argument-level inspection reads the path and asks whether this specific package appears in the repository lockfile or the approved manifest. If not, the request is denied or escalated. Host-level rules cannot make that distinction. - Gate first-seen packages with human approval. Any package name not previously observed for this repository becomes an approval event: name, version, registry, requesting agent identity, and the surrounding task. Approving a real new dependency takes seconds. Declining a hallucinated one takes less.
- Disable install scripts where you can.
npm ci --ignore-scriptsand building wheels in a separate, network-isolated stage remove the execution primitive most payloads rely on. Treat any package that genuinely requires install scripts as a reviewed exception. - Kill the post-install callback. Even if a bad package lands, the value only leaves your perimeter over the network. Egress inspection that scans outbound bodies for credential shapes catches the second half of the attack. That is the same mechanism described in catching leaked API keys and tokens on the way out.
Which control catches what
| Control | Where it acts | Catches | Misses |
|---|---|---|---|
| Prompt or system-prompt instruction (do not install unlisted packages) | Model input | Casual drift | Any injected instruction or retry loop that overrides it |
| Static dependency scanner in CI | Post-merge diff | Bad packages already committed | Installs that ran during the agent session, before the diff existed |
| Lockfile plus hash pinning | Package manager | Unpinned invented names | Agents that edit the lockfile or pass override flags |
| Private registry with curated index | Resolution | Names absent from your index | Direct calls to public registries if egress is open |
| Host-level egress allowlist | Network | Payload callbacks to unknown domains | Fake packages served from an allowed registry host |
| Package-name inspection plus approval at egress | Network, request-aware | Hallucinated installs from allowed hosts, plus exfil attempts | Nothing in this chain, which is why it belongs in front of the others |
Detection heuristics worth wiring into policy
When an unknown package request reaches the proxy, cheap signals separate a real new dependency from an attacker-registered slop name:
- Registry age. First release published very recently, with a single version.
- Single maintainer, no repository link. No source URL, or a source URL that does not resolve.
- Edit distance to a popular package. Within one or two characters of a top package, or a plausible compound of two real ones.
- No prior appearance in your organization. Never resolved by any repository or agent before this request.
- Install-time scripts present. A build backend or
postinstallhook in a package that should be pure Python or pure JS.
Any two of those signals is a reasonable threshold for escalate-to-human rather than auto-allow.
Where Agent G fits
Agent G sits inline as an egress proxy in front of coding agent runtimes, so every registry resolve, artifact fetch, and post-install callback crosses a policy decision point outside the agent's own trust boundary. Policy is expressed against the actual request: destination host, package path and version, requesting agent identity, and outbound body content. Unapproved package names are denied or held for human-in-the-loop approval, credential-shaped payloads leaving in a request body are blocked, and every decision is written to an out-of-band log you can hand to an auditor or replay during incident response.
That pairs naturally with the broader hardening described in securing AI coding agents at egress. For agents reaching tools through Model Context Protocol servers, the same argument-level enforcement applies through the Agent G MCP gateway. If you are comparing approaches, the alternatives overview lays out what prompt-layer and posture tools do and do not cover here.
Frequently Asked Questions
Is slopsquatting different from typosquatting?
Yes. Typosquatting targets human typing errors on real package names. Slopsquatting targets names that no legitimate project ever used, because a language model invented them. The attacker harvests hallucinated names from model output and publishes them, so the bait matches what agents ask for.
Can I stop package hallucination in AI coding agents at the prompt layer?
You can reduce it with retrieval of approved manifests and stricter instructions, but not eliminate it. Generation is probabilistic and retry loops push agents toward new names. Treat prompt-layer measures as noise reduction and enforce the actual install decision at the network boundary.
Does a private registry alone solve this?
Only if agents cannot reach public indexes directly. A curated internal index removes the hallucinated name from resolution, but an agent with open egress can pass an override flag and fetch from PyPI or npm anyway. Pair the registry with default-deny egress so the bypass fails.
How do I block malicious package registry access without breaking builds?
Start in log-only mode, record every registry request for a week, and generate the allowlist from observed legitimate traffic. Then flip to enforce with first-seen packages routed to approval rather than hard-denied. Real dependencies get approved in seconds and cached; invented ones never resolve.
Close the install path before it runs
Slopsquatting works because an autonomous agent will happily install a package that does not deserve to exist, and package managers execute code at install time. The durable fix is not better model behavior; it is a policy enforcement point on the wire that reads package names, gates unknowns, and blocks the callback. Agent G provides that layer as a drop-in egress proxy. Request access to the Agent G private beta to run it in front of your coding agents.