Slopsquatting:AI 助手虛構套件名稱如何帶來供應鏈攻擊
Slopsquatting: when your AI assistant invents a package
Slopsquatting 指攻擊者把 AI 工具虛構、原本不存在的套件名稱註冊到 npm 或 PyPI,再等開發者或 AI 智能體安裝含惡意程式碼的套件。安裝程序可能執行套件的安裝指令碼或建置程式碼,套件也可能在匯入時執行程式碼,並接觸用戶或 CI 可存取的憑證。
Key takeaways
- Attackers register package names that AI tools invent, then wait for installs.
- An install can run code on your machine, so a bad package is more than a bad import.
- Verify that a package exists and is what you expect before installing it.
- Commit lockfiles, install from them, and review dependency changes like code.
- Limit what a malicious install could reach, such as secrets and credentials.
You ask your AI assistant for a quick way to sanitize some JSON. It writes a tidy snippet, adds import { sanitize } from "fast-json-sanitize" at the top, and tells you to run npm install fast-json-sanitize. The code looks right. The name sounds right. There's just one problem: nobody ever published that package.
Language models predict plausible text, and a plausible package name is just text. Sometimes the name they produce belongs to a real, well-known library. Sometimes it's a convincing invention. This post is about what happens next, and how to make sure it doesn't happen to you.
A note on examples: fast-json-sanitize and every other package name in this post is made up for illustration. If you ever see it on a registry, treat that as exactly the situation this post describes.
How the attack works
The pattern, often called slopsquatting, goes like this:
- An AI tool suggests a package name that doesn't exist on the registry.
- Someone notices the name (in a chat log, a tutorial, a public repo, a forum answer) and registers it on npm or PyPI with malicious code inside.
- The next developer, or the next AI agent, who follows the same suggestion runs the install and gets the attacker's code instead of an error.
(Diagram: see the original post.)
It's a cousin of typosquatting, where an attacker registers a misspelling of a popular package's name and waits for a typo. The difference is where the wrong name comes from. With typosquatting the human mistypes. With slopsquatting the tool invents a name, and then confidently repeats it to many people. A model can suggest the same invented name more than once, which gives an attacker something worth registering.
Before the registration, a made-up name fails loudly: npm install returns a 404 and you notice. After it, the install succeeds and everything looks fine.
Why an install is more dangerous than it looks
Installing a package is not just downloading files. It can execute code:
-
npm lifecycle scripts. A package can declare
preinstall,installorpostinstallscripts in itspackage.json. They run automatically duringnpm install, as you, with your permissions. -
Python builds from source. Installing a prebuilt wheel doesn't run the package's code. But if pip has to install from a source distribution (sdist), it builds it first, and the build (for example a
setup.py) runs the package author's code on your machine. - Import-time code. Even with install scripts disabled, a package's top-level code runs the first time your app or test suite imports it. That's true for npm and Python packages alike.
- Your environment. On a laptop that means your shell environment, your SSH keys and your cloud credentials. In CI it means whatever secrets the job can see: deploy tokens, registry credentials, cloud keys.
{
"name": "fast-json-sanitize",
"version": "1.0.0",
"scripts": {
"postinstall": "node ./setup.js"
}
}
That's an ordinary-looking manifest. Whatever setup.js does, it does during your install. Nothing here is a bug in npm; running install scripts is a documented feature that legitimate packages use for native builds. The danger is that you ran the install without knowing whose code it was.
Why AI tools make this more likely
AI assistants don't check a registry while they write. They produce a name that fits the context, the same way they produce a function name. The result reads exactly like a real recommendation, so it gets the same trust as the rest of the answer.
Agentic tools raise the stakes. A chat assistant hands you a command to run. A coding agent that can execute shell commands may run npm install itself, mid-task, with nobody watching. Now the unverified name goes straight from suggestion to execution. This is a place where least privilege for AI agents applies directly: package installs should need your approval.
This is one more case of the pattern from vibe-coded security flaws: the tool optimizes for code that works, and nobody asked it to check where a dependency comes from.
Defenses that work
1. Verify before you install
When an AI suggests a package you don't already use, take 60 seconds before running the install:
-
Does it exist at all?
npm view <name>or the package's page on pypi.org will tell you. - Is it the one the official docs point to? Find the library from the project's own documentation or official repository, then copy the install command from there, not from the chat.
- Look at the signals. Registry age, version history, maintainers, a repository link that goes to a real project, and download history. A package that was registered last week, has one version and no linked source is a warning.
These are signals, not proofs. A healthy-looking package can still be compromised, and a new one can be legitimate. They're cheap filters that catch the obvious cases, including a freshly registered squat.
npm view fast-json-sanitize time.created maintainers repository.url
If a package your AI named is brand new, has no source link, or does something different from what you asked for, don't install it. Ask the AI for a different approach, or use the standard library or a package you already trust.
2. Commit lockfiles and install from them
A lockfile records exactly which versions (and integrity hashes) you resolved, so every later install gets the same bits.
# npm: installs exactly what package-lock.json says, fails if it disagrees
npm ci
# pip: pinned versions with hashes
pip install --require-hashes -r requirements.txt
Use npm ci in CI and in Docker builds, not npm install. With pip, pin versions in requirements.txt, and add hashes so a swapped file is rejected. Lockfiles don't make a bad package safe, but they stop a package from changing under you after you've reviewed it. (The same reasoning applies in Dockerfiles.)
3. Review dependency changes like code
A new line in package.json or requirements.txt is executable trust. Treat it as seriously as a new function. In pull requests:
- Make dependency changes visible: a changed manifest or lockfile should be called out in the PR description.
- Require a human to look at every new dependency an AI agent adds: what is it, why is it needed, can existing code or the standard library do the job?
- Be suspicious of tiny packages that do one small thing the AI could have written inline.
4. Vet with scripts disabled
When you want to look at an unfamiliar package, install it without running its lifecycle scripts:
npm install --ignore-scripts <name>
# Python: refuse source builds, so no build code runs (fails if there's no wheel)
pip install --only-binary :all: <name>
The npm flag blocks preinstall/postinstall code, but it's a vetting aid, not a safe mode. Some legitimate packages need their install step to compile native code, and they'll break without it. And the package's code still runs when you import it, so don't import something you haven't looked at.
5. Limit what a malicious install could reach
Assume that one day something bad will run during an install, and make that survivable:
- Give CI jobs that install dependencies only the secrets they need. A build and test job shouldn't see production deploy credentials.
- Prefer short-lived, narrowly scoped tokens over long-lived keys.
- Run installs for unvetted code in a throwaway container or VM, not on a machine that holds your SSH and cloud credentials.
This is the blast radius idea: you can't always prevent a bad install, but you can control what it can reach.
6. For larger teams, put a gate in front of the registry
A private registry or proxy with an allowlist means developers and CI can only install packages someone has approved. New names are blocked until reviewed, which stops a freshly squatted package from ever reaching a build. It's more process, so it fits teams with enough developers that ad-hoc review stops scaling.
7. Tell your AI tool the rules
You can cut the problem off at the source. Put this in your project's instructions file (CLAUDE.md, .cursorrules, or whatever your tool reads):
Dependencies:
- Use only packages already in package.json / requirements.txt, or the standard library.
- If a new dependency is needed, stop and ask me first. Give the exact package
name, what it does, and a link to its official docs or repository.
- Never run npm install, pip install or similar without my approval.
An instruction isn't a guarantee, so keep the tool's approval setting for shell commands turned on. The two together make a new dependency something you decide, not something that happens.
A quick checklist
- Every new package name was checked on the registry and traced to official docs or a real repository
- Lockfiles are committed; CI uses
npm ciorpip install --require-hashes -r - Dependency changes are reviewed in PRs, especially ones an AI agent added
- Installs of unfamiliar packages use
--ignore-scriptswhile you look them over - CI jobs that install packages can't see production credentials
- The AI tool is told to ask before adding a dependency, and installs need your approval
- Larger teams: a private registry or proxy with an allowlist
How OpenRouting helps
OpenRouting's supply-chain agent reviews what's in your repository: whether dependencies are pinned, whether lockfiles are committed, which registries your configuration points at, and where your build pulls remote code. Those are the settings that decide how much damage a bad package can do. Pull-request review runs the same checks on a change's files and posts a single summary comment, and every finding gets a plain-English explanation and a suggested fix.
To be clear about the boundary: OpenRouting does not look package names up in npm or PyPI, and it does not check packages for known CVEs. It can't tell you whether a given name is a hallucination or a squat. That check is yours to make, using the steps above.
Questions
What is slopsquatting?
Slopsquatting is when an attacker registers a package name that AI tools invent, on npm or PyPI, with malicious code inside. The next developer or AI agent who follows the same suggestion runs the install and gets the attacker's code instead of an error.
What is the difference between slopsquatting and typosquatting?
With typosquatting an attacker registers a misspelling of a popular package and waits for a human typo. With slopsquatting the AI tool invents the name and confidently repeats it to many people, which gives an attacker something worth registering.
How do I check if a package suggested by AI is real?
Run npm view or check its page on pypi.org, and copy the install command from the library's official docs or repository rather than the chat. Look at registry age, version history, maintainers and a real source link; a package registered last week with one version and no source is a warning.
Does npm install --ignore-scripts make installing an unknown package safe?
No. It blocks preinstall and postinstall scripts, so it's a vetting aid, not a safe mode. The package's code still runs when you import it, so don't import something you haven't looked at.
Originally published on openrouting.si. I'm building OpenRouting, security scanning with AI review of every finding, for teams shipping AI-written code.
來源:DEV Community · dev.to