How to deliver high-quality software with AI-native development / Checks that keep working at high speed
Dependency control when an agent picks the packages
Coding models suggest packages that do not exist, at rates above 10 percent for open-source models. Attackers register those names and wait for someone to install them. After a real supply chain incident in the npm registry and a new OWASP category for this risk, every new package should pass a required check before it is added. This page covers the policy, the checks, and who decides.
Published September 1, 2026. Editorial.
Key takeaways
- Research presented at USENIX Security 2025 found references to invented packages in at least 5.2 percent of commercial model output and 21.7 percent of open-source output across 576,000 samples [1].
- Invented names repeat, which is what makes them registrable by an attacker rather than a harmless typo.
- OWASP added Software Supply Chain Failures to its Top 10:2025 as A03, a category in its own right [2].
- Adding a dependency is a decision, so it should arrive as its own change with a named owner, never hidden inside a feature diff.
Most AI code-quality discussion is about the code. The most consequential new risk is about what the code imports.
The measured problem
Researchers from the University of Texas at San Antonio, the University of Oklahoma and Virginia Tech generated 576,000 code samples across 16 models and counted references to packages that do not exist. Commercial models produced references to invented packages in at least 5.2 percent of samples and open-source models in 21.7 percent, yielding 205,474 distinct fake package names [1].
The important part is the repetition. An invented name that appears once is a typo. An invented name that a model produces often for a common prompt is a name anyone can register and fill with their own code. The attack is straightforward: find the names models invent, register them, publish something that runs on install, and wait for an agent to add it to somebody's build.
This is already happening in the wider world of open-source packages. In September 2025 a self-replicating worm spread through npm using stolen maintainer credentials, and CISA published an alert on 23 September 2025 advising organisations to review dependencies, pin npm packages to releases produced before 16 September 2025, rotate developer credentials immediately, and mandate phishing-resistant multifactor authentication on developer accounts [3]. OWASP's Top 10:2025 lists Software Supply Chain Failures as A03 [2].
Why AI-native teams are more exposed
Three reasons, all structural rather than about any particular tool.
Volume. More changes means more opportunities to add a dependency, and each one is a small decision nobody flagged.
Plausibility. A suggested package name usually looks right. It follows the naming conventions of the package registry, it is descriptive, and it appears in code that otherwise works. Nothing about the diff signals that this line is different from the twenty around it.
Convenience bias. An agent solving a problem will use a library, because that is what the training data does. Left alone it will add three dependencies where a human would have written fifteen lines, and every one of them is a permanent obligation. Our post on the cost of a dependency you did not choose covers the long-run version of this cost.
The policy
Five rules, all enforceable.
A new dependency is its own change. Not part of a feature branch. Its own diff, its own review, one line explaining why it is needed and what was considered instead. This single rule catches most of the problem, because it makes the decision visible at the moment it is made.
The package must exist and be the one you think it is. Verify the registry entry, the repository behind it, the maintainer, and the download history. A package with a plausible name, no history, and a recent first publish is the exact profile of a slopsquat: a fake package registered under a name that models invent.
Lockfiles are authoritative and pinned. Builds resolve from the lockfile, not from a range. This is what makes a compromise investigable later, and it is the specific control CISA recommended during the npm incident [3].
Advisory checks block the merge. A known vulnerable version does not reach the main branch, and the check runs in the pipeline rather than as a report someone reads weekly.
Install-time scripts are treated as execution. Anything that runs during install is running on a developer machine and in continuous integration with whatever credentials are there. If your package manager allows it, disable install scripts by default and allow them per package.
Where the check has to live
In the pipeline, as a gate. Not in a linter that warns, not in a weekly report, and not in a policy document.
The reason is timing. A dependency added at ten in the morning is depended upon by three other changes by the afternoon, and the cost of removing it rises with every hour. The check that matters runs on the change that adds it, and it fails the build.
There is a second requirement that teams miss: the check must run on changes made by agents in exactly the same way as on changes made by people, with no fast path. If an automated pipeline can add a dependency without the gate, the gate does nothing.
Adding fewer packages instead of checking more of them
The cheapest dependency is the one you did not add. Two habits make a measurable difference.
First, tell the agent what it may use. A short list of approved libraries for common jobs, in the repository where the model reads it, stops most of the invented names. Agents follow explicit conventions well when the conventions are written down where they load them, which is the practical point of documentation an agent and a new hire can use.
Second, ask for the version without the library for small jobs. A date formatting helper, a debounce, an argument parser: these are often twenty lines, and twenty lines you own are cheaper over five years than a dependency with its own release cycle, its own maintainer risk, and its own chain of indirect dependencies.
Read the lockfile diff, not just the manifest
A change that adds one package usually adds more than one package. The manifest shows the decision; the lockfile shows the consequence, and the consequence is where the risk is.
Make the lockfile diff part of what a reviewer sees. The questions are simple: how many packages arrived, does any of them have a name that looks close to a well-known one, and is anything appearing here that is unrelated to the stated purpose of the change. A change described as adding a date library that pulls in thirty transitive packages including a network client is worth thirty seconds of attention.
This is also the practical answer to typo-style attacks, which are an older problem related to invented package names. A name one character away from a package with millions of downloads is hard to see in a manifest and obvious in a diff when you are looking for it.
Internal packages need the same rules
Teams often apply dependency policy to the public registry and skip it for their own internal packages, on the reasoning that internal code is trusted. That reasoning fails against this attack.
An internal registry is a smaller, more valuable target: it is the one place where a single compromised credential reaches every service in the company, and internal packages usually run install scripts that nobody has read in years. The controls that matter are the same ones, applied to internal packages. Publishing requires more than one credential. Package names are reserved so an internal name cannot be claimed on the public registry, which is what makes a dependency confusion attack possible in the first place. And the resolution order is explicit, so a public package can never replace an internal one of the same name.
None of this is new advice. What is new is the volume of dependency decisions being made per week, which is what turns a policy gap that used to be theoretical into one that attackers actually use.
What to do if you find one
Assume credentials were exposed. That is the standard assumption after any suspicious install-time execution, and it is what CISA recommended during the npm incident: rotate developer credentials immediately, and audit repository webhooks, secrets and installed applications [3].
Then find out how far it spread. The lockfile history tells you when it entered and which builds included it, which is the reason for the pinning rule above. Check the machines as well as the repositories: a package with an install script has run on every developer machine and every build agent that installed it, so the question is not only which services released it but which environments executed it.
Then remove it, rebuild, and write the postmortem in a way that names the missing control rather than the person who approved the change. Our post on how to handle a security finding in generated code covers the sequence.
Where this connects
This is one of the five gates in the quality gates that should block a merge, and it is an architectural decision in the sense used in the decisions that stay with your engineers, since a dependency is expensive to reverse once other code depends on it. The broader question of whether generated code is secure is covered in is AI-generated code secure. The main guide puts it in the context of the whole delivery model.
Best for
- Blocking a merge when a dependency is newly added, unknown, or matches a known advisory
- Pinning through a lockfile so a later investigation can say exactly what was installed and when
- Disabling install-time scripts by default and allowing them per package
Avoid if
- The rule only exists in a policy document rather than in the pipeline
- Automated or agent-driven merges can take a path that skips the check
- The check produces a weekly report instead of failing the change that introduced the problem
Check before you decide
- Open the registry entry, the source repository, the maintainer and the publish history before approving a new package
- Confirm builds resolve from the lockfile rather than from a version range
- Confirm the advisory check runs on agent-authored changes with no fast path
Common questions
Do AI coding tools really invent package names?
Yes, at measurable rates. Research presented at USENIX Security 2025 generated 576,000 code samples across 16 models and found references to invented packages in at least 5.2 percent of commercial model output and 21.7 percent of open-source output, producing 205,474 distinct fake package names.
What is slopsquatting?
It is registering a package name that a code-generating model reliably invents, then publishing something malicious under it and waiting for a developer or agent to install it. It works because invented names repeat rather than being random one-off typos, which turns a model's mistake into a predictable name an attacker can register.
How should a team review a new dependency added by an agent?
Make it its own change rather than part of a feature branch, with one line saying why it is needed and what was considered instead. Then check the registry entry, the source repository, the maintainer and the download history. A plausible name with no history and a recent first publish is the profile of a slopsquat.
Why does dependency risk get worse with AI-native development?
Volume, plausibility and convenience bias. More changes create more chances to add a package, a suggested name looks like every other line in the diff, and an agent solving a problem reaches for a library where a person might write fifteen lines. None of those signals appear in review unless the dependency is separated out.
Should lockfiles be pinned in an AI-native repository?
Yes, and builds should resolve from the lockfile rather than from a version range. Pinning is what makes an incident investigable later, since the lockfile history tells you when a package entered and which builds included it. CISA recommended pinning npm dependencies to known safe releases during the September 2025 registry compromise.
What should we do about install-time scripts?
Treat them as code execution, because that is what they are: they run on developer machines and in CI with whatever credentials are present. Where the package manager supports it, disable install scripts by default and allow them for specific packages, so a compromised dependency cannot act simply by being installed.
How do we stop agents adding unnecessary dependencies at all?
Write down the approved libraries for common jobs in the repository where the model reads them, and ask for the small version without a library where it fits. A date helper or a debounce is often twenty lines, and twenty lines you own cost less over five years than a package with its own release cycle and chain of indirect dependencies.
What should happen immediately after discovering a malicious package?
Assume credentials were exposed and rotate them, which is what CISA advised during the npm worm incident, along with auditing repository webhooks, secrets and installed applications. Then use lockfile history to find which builds included it, remove it, rebuild, and write the postmortem around the missing control rather than the person who approved the change.
Is dependency risk covered by OWASP guidance?
Yes. The OWASP Top 10:2025 lists A03:2025 Software Supply Chain Failures as a category of its own, alongside A01 Broken Access Control and A02 Security Misconfiguration. That elevation reflects how much of current real-world risk arrives through what an application depends on rather than through code the team wrote.
Can dependency checks run only on human-authored changes?
No, and a pipeline that lets automated changes take a faster path has no dependency control at all. The check must run identically whoever or whatever opened the change, because the volume of agent-authored changes is precisely where an unnoticed package addition is most likely to get through.
References
- [1] Spracklen, Wijewickrama, Sakib, Maiti, Viswanath and Jadliwala, We Have a Package for You! A Comprehensive Analysis of Package Hallucinations by Code Generating LLMs, USENIX Security Symposium 2025: 16 models, 576,000 samples, at least 5.2% hallucination rate for commercial models and 21.7% for open-source models, 205,474 unique hallucinated package names. Accessed 1 September 2026.
- [2] OWASP Top 10:2025: A03:2025 Software Supply Chain Failures, a new category in the current edition. Accessed 1 September 2026.
- [3] CISA alert, Widespread Supply Chain Compromise Impacting npm Ecosystem, 23 September 2025: recommends dependency review, pinning to releases produced before 16 September 2025, immediate rotation of developer credentials, phishing-resistant MFA on developer accounts, and auditing repository webhooks and secrets. Accessed 1 September 2026.
Related reading
The cost of a dependency you did not choose
A coding agent adds a package in four seconds and the decision is never discussed. Someone will be responsible for that package for the next five years, and it will not be the agent.
How to handle a security finding in generated code
A scanner reports a problem in code no human wrote. The first instinct is to fix that line, and that is the one response almost guaranteed to leave the same defect in nine other places.
A practical pre-launch security review for a small team
You do not need perfect security to launch. You need to check the few basics that find most real problems, and to know when the risk is big enough to bring in a specialist.
More in Checks that keep working at high speed
The quality gates that should block a merge
A gate is a check that stops a change reaching the main branch without a person deciding. Everything else is a suggestion. This page covers which checks deserve that power, why a short blocking list beats a long advisory one, how to keep the gates trustworthy, and what to do about the changes that still need a human.
Test strategy when the AI writes the tests too
When the same system writes the implementation and the tests, a passing suite can mean the code agrees with itself. That is not evidence. This page covers how to keep tests independent of the code they check, which tests are worth generating and which are not, and the three properties a suite needs before you can let a passing result decide a merge.