Dependency Provenance: The Seventh Property, and the Only One Nobody Ships
19.7% of packages recommended by code-generation models do not exist. That figure comes from a USENIX Security 2025 study of 16 models across 576,000 Python and JavaScript samples, and the detail that makes it an attack surface is repeatability: 43% of hallucinated names reappeared on every single re-run of the same prompt. An attacker can prompt a model, observe which fake names it reliably invents, and pre-register them as malware. Researcher Bar Lanyado proved the consumption side by registering huggingface-cli, a name LLMs frequently hallucinated, on PyPI: 30,000 downloads in three months.
The seventh of the seven properties is different from the other six. The first six describe what the published record and the platforms already do, so their evidence falls out of mechanisms documented elsewhere in this handbook. This one is a prescription: the incident record demands it, and no vendor ships it today, including Wallfacer (disclosure: the sponsor of this guide). It is a control nobody sells, which is why it lives here as a build item or a contract clause rather than as a box you check by buying a platform this quarter. The Manage the Work chapter argues the same control as the last of the decision gates.
Two attack chains, and they need different controls
The incident record gives the property its spec. There are two distinct chains, detailed in the slopsquatting incident page and the Nx s1ngularity page.
Wrong identity. Slopsquatting is an identity problem. The model invents a plausible package name, the attacker has pre-registered it, the agent edits the manifest and runs install, and the postinstall script executes in the agent's environment. The package is not the one you meant.
Wrong version. Nx s1ngularity is a version problem. In August 2025, poisoned versions of the legitimate Nx package shipped via a stolen publish token. Anything installing @latest in the roughly 4-hour window ran a postinstall that harvested credentials, in part by driving locally installed AI CLIs with auto-approve flags. Coverage reported 400+ users and organizations and 5,500+ repositories affected. The package is exactly the one you meant, freshly poisoned.
Controls that fix one chain often do nothing for the other. Producer-side provenance (SLSA attestations, npm trusted publishing) breaks the Nx publish link but is useless against slopsquatting, because the attacker is the legitimate publisher of their own malicious package. Valid provenance proves origin, not intent.
Every platform gates the host; none gates the package
The major agent platforms all answer "which hosts can the agent reach?" None answers "is this the package the team meant, from the publisher they meant, old enough to trust?"
| Platform | Documented control | Gates package identity? |
|---|---|---|
| OpenAI Codex cloud | Domain allowlist with a "Common dependencies" registry preset | No |
| GitHub Copilot coding agent | Default-on firewall; new dependencies checked against the GitHub Advisory Database | Known-bad only |
| Claude Code | Proxy plus domain allowlist, confirmation for new domains | No |
| Cursor cloud agents | Three egress modes up to allowlist-only | No |
The registry host allowlist is precisely the control slopsquatting walks through, because the malicious package is served by the allowlisted host. Allowing registry.npmjs.org allows all ~3 million packages on it. Copilot's advisory-database check is the only agent-specific dependency gate any vendor documents, and it is detection of known-bads: a freshly registered slopsquat has no advisory yet. No vendor documentation we reviewed mentions slopsquatting, package-name verification, or in-sandbox cooldown enforcement at all.
The property, drafted as control text
If you are building (Path 2) or writing procurement requirements (Path 3), this is the text:
Dependency provenance. Nothing installs on the model's say-so. An LLM's output is untrusted input to the build system. Every dependency an agent introduces is verified against a trusted source before it can execute, at install time in the sandbox, not only at merge:
- Gating registry path. Installs resolve only through a curated internal registry or checking proxy, deny-by-default for package identities not already in the lockfile. A hallucinated name fails closed before any install script runs.
- A cooldown applies: no version installable until a minimum age after publication, so short-lived poisoned releases expire before they are eligible.
- New dependencies are a gated change: the review gate surfaces a dependency diff with name, age, publisher, advisory status, and provenance attestation where the ecosystem provides one. A new package is never merged solely because the model named it.
- Lockfile-only installs. Everywhere downstream of the agent, so the only path for a new package is the gated one above.
Install-time matters more than merge-time here. A dependency-review check at the PR gate protects the codebase, but in an agent workflow the postinstall already ran in the sandbox during iteration, before any PR existed. Only install gates protect the environment.
The pieces exist; the assembly doesn't
None of this requires invention. By mid-2026 every major package manager gates on release age: npm shipped minimumReleaseAge in 11.10.0, pnpm and yarn have equivalents, and Andrew Nesbitt's Package Managers Need to Cool Down catalogs the same idea under at least ten configuration names. Cooldowns alone would have made the Nx versions, live for about 4 hours, never installable. Gating proxies exist commercially: Socket Firewall, JFrog Curation, Sonatype Firewall, and Chainguard Libraries, which blocked 98% of a 3,025-sample known-malware corpus in testing. A curated registry is the one clean slopsquatting kill: the hallucinated name simply does not exist there, so the install fails closed.
What no one has done is wire these into the agent's environment as a default. The environment already mediates the agent's network egress, its credentials, and its code review. The package registry is the one unmediated channel left, and closing it is the same move that produced the evidence for the other six properties: make the boundary the environment, not the prompt. Limits worth stating: a cooldown does not stop a patient attacker whose slopsquat ages past the window (Lanyado's package sat for three months), and the field has published no data on how often agent tasks are blocked or slowed by these gates. Until a vendor ships it, this property is a build item or a contract clause, and it belongs on the checklist either way.