The 2026 OSSRA report audited 947 codebases across seventeen industries and left four numbers on the same page: open source components per application rose 30% in a year, files per codebase 74%, mean vulnerabilities per codebase 107%, and licence conflicts now appear in two thirds of audits, up from 56% the year before — the largest year-over-year jump since the report has existed.
None of the four is about the code your team writes. All four are about the code your team imports.
This piece is about that part. Not whether the assistant writes good code — that was the redesign of the review — but about the decisions it makes in addition to writing it: which library it uses, in which version, under which licence and with which chain of maintainers behind it. These are decisions with a lifespan of years, they are made in a second, and they reach the pull request disguised as one line.
The line nobody argues about
A diff is democratic in a way that hurts: every line takes up the same space. Renaming a variable takes one line. Adding a dependency takes one line. The first gets discussed in review; the second goes in without comments, and it is the one that brings with it a tree of code neither side has opened.
The proportions have been measured for years and almost nobody has them in mind when approving. In Endor Labs' dependency analysis, 95% of the vulnerabilities found live in transitive dependencies — the ones you did not choose, the ones your choice chose; in Java applications, 71% of the code that ends up in the application comes from open source components and, of all that imported code, around 12% is actually used.
With generated code, that line shows up many more times. Not because the model is reckless, but because its objective is to solve the problem in front of it, and pulling in a library is almost always the shortest way to do that. The result is not a spectacular failure: it is volume. And volume slips through wherever the process is not looking.
Three failure modes, ordered the opposite way to how they are told
They are worth separating before deciding where to invest, because their frequencies are very different and none of them is fixed by another one's control. I have ordered them from loudest to most frequent, which turns out to be the inverse of the order they occupy in the public conversation.
| Mode | What happens | How often |
|---|---|---|
| 1 · The package that does not exist | The model recommends an invented name. If someone registers it before you install it, they run code on your machine and in your pipeline | Between 4.6% and 6.1% of references in 2026 frontier models. No documented public malicious attack yet |
| 2 · The package that exists, in the wrong version | The library is real and the version it proposes drags in already-published vulnerabilities. The code works and the tests pass | Between 36.7% and 55.7% of tasks end with at least one known CVE in the specified version |
| 3 · The right package that should not be there | Incompatible licence, a duplicate of something you already had, or nobody in-house who answers for it a year from now | Two thirds of audited codebases have licence conflicts. The rest is almost never measured |
The first is the one that makes the press; the third is the one that will happen to you this week
1 · The package that does not exist
The reference work is by Joseph Spracklen and his team, presented at USENIX Security 2025. They generated 576,000 code samples with sixteen models and two prompt datasets, and checked every referenced package against the real PyPI and npm indexes: 440,445 references, 19.7%, pointed at packages that do not exist, spanning 205,474 distinct unique names. The rate ranged from 5.2% in commercial models to 21.7% in open models.
The rate is the headline. What turns this into a security problem rather than an annoyance are two other findings from the same study, cited far less often.
The first is repetition. 43% of the hallucinated names came back in all ten repeated queries; 39% never repeated once. That bimodality is the whole difference: a hallucination that does not repeat is noise, and one that always repeats is a postal address. The attacker does not need to guess what the model will invent for your teammate — asking ten times and keeping what is stable is enough.
The second is that this is not typosquatting. Only 13.4% of the invented names sit at an edit distance of 1 or 2 from a real package. They are not misspellings of a legitimate name: they are new, plausible names, the kind a developer in a hurry accepts because it sounds exactly like what they needed. Registry defences designed to catch names nearly identical to a popular one are looking at something else.
In 2026 the study was replicated on five frontier models released between October 2025 and March 2026, with 199,845 paired Python and JavaScript prompts. The good news is that the spread compresses by an order of magnitude: every model evaluated lands between 4.62% and 6.10%. The bad news comes after the rate: there are 127 package names that all five models invent identically and, following coordinated disclosure with PyPI Security and Socket, 53 were still available to register — 41 on PyPI and 12 on npm — despite the defences the registries already apply. A single malicious registration would reach users of five different providers at once.
It is a preprint by an independent researcher and has not been peer reviewed; I cite it because its methodology replicates the USENIX study's and because the part that carries the most weight — the 53 free names — was validated by Socket against the registry, discarding six false positives that were valid framework imports. And it is worth repeating what they themselves write, because almost no article does: this is attack surface, not an attack. There is no public evidence that any of those names has been registered maliciously.
The documented case of the chain actually closing is still an experiment. In December 2023, Bar Lanyado, a researcher at Lasso Security, registered a package on PyPI called huggingface-cli — harmless — after seeing models recommend it again and again, when the real tool is installed another way. In February 2024 the install instructions in the README of an Alibaba repository were pointing at his. In three months it collected more than 15,000 genuine downloads. Nobody attacked it: the whole mechanism simply worked.
2 · The package that exists, in the wrong version
This mode makes no headlines and is ten times more frequent. The library is real, well known and perfectly reasonable. What arrives wrong is the version.
Endor Labs measured it across more than 10,000 GitHub repositories and coding agents on PyPI, npm, Maven and NuGet: only one in five dependency versions recommended by an assistant was safe, safe meaning the package is not invented and the version does not drag in known vulnerabilities. Between 44% and 49% of the dependencies the agents imported carried already-published vulnerabilities.
The study that best explains why is from 2026, across ten models and a thousand real programming tasks: between 36.70% and 55.70% of tasks end with at least one known CVE in the library version the model specifies, and between 62.75% and 74.51% of those CVEs are critical or high severity. All the models also converge on the same problematic versions, which rules out accident and points at something structural.
The number that orders the conversation is this one: between 72.27% and 91.37% of those CVEs had been published before the model's own knowledge cutoff. It is not that the model could not have known. It is that nothing in the task you gave it asked it to look. The paper's title says it better than any paraphrase: correct code, vulnerable dependencies.
The inversion that catches teams out
This year's fashionable control is the cooldown: do not install a version until it has been published for a few days. There is a solid argument behind it. In November 2025, William Woodruff reviewed ten supply-chain attacks from 2024 and 2025 — from the xz-utils backdoor to the ultralytics, chalk, Nx and web3.js incidents — and measured the window between publishing the compromised package and detecting it: in eight of the ten it was under a week. A seven-day wait would have avoided almost all of them; fourteen days, all but one.
The whole ecosystem has implemented it in nine months. pnpm has had it since 10.16 in September 2025, Yarn since 4.10, Bun since 1.3 in October and npm since 11.10.0 in February 2026; in Python, uv since 0.9.17 and pip since 26.0; and Poetry, Bundler and Cargo's registry side too. It is probably the fastest hygiene change the ecosystem has adopted in a decade.
3 · The right package that should not be there
The third mode is not a security one, has no CVE, and is the one that will show up in your repository this week. These are real, maintained, vulnerability-free dependencies that nonetheless should not have come in.
Because of the licence. It is the most striking finding of the 2026 OSSRA and the least commented on: licence conflicts went from 56% to two thirds of audited codebases in a single year. The report's explanation has two halves — more components per application, and generated fragments derived from copyleft sources that arrive without carrying their licence along. The process mismatch is measured in the same survey: 76% of organisations review generated code for security risk, 54% look at intellectual property and licensing, and only 24% review all four dimensions — security, licence, intellectual property and quality. Intellectual property review was designed for a world where code arrived at human pace.
Because of duplication. A generator solves the problem in front of it; it does not know that three folders away there is already a library for that, approved two years ago. It is the same structural blindness that makes generated code duplicate instead of reuse, only applied to the supplier catalogue rather than to your own code. And where a duplicated function is debt, two libraries doing the same thing are two surfaces to patch and two update criteria.
Because of orphanhood. The question rarely asked in a pull request: a year from now, when this library ships a breaking change or stops being maintained, which of us answers? If the answer is "nobody", the dependency goes in anyway, but the team has taken on an obligation it has recorded nowhere.
Why the review will not catch it
It is worth saying why this is not fixed by asking for more rigour in review, which is the reflex answer. There are three reasons, and none of them depends on anyone's professionalism.
The cost of reading does not discriminate. The reviewer spends the same seconds on a trivial line and on a five-year decision, because in the diff they take up the same space and arrive mixed together. When the flow of changes multiplies, the first thing lost is the thing whose loss goes unnoticed.
What comes in is not in the pull request. 95% of vulnerabilities live in transitive dependencies, and not one line of those appears in the diff. An entry in the lock file is approved and a whole tree arrives.
There is no written criterion. When someone asks "do we really need this library?", they are applying personal taste, and that is why the question is rarely asked: it is uncomfortable and it has no backing. In almost no team is there a document saying what may be imported, under which licences, from which minimum version and through which approval process. Without that, dependency review is an opinion against a colleague in a hurry, and that argument is always won by the hurry.
Six controls, and what each one cuts
None of them is new or expensive. What usually fails is not the choice of tool but installing two of them and treating what they do not cover as covered. The column that matters is the second one.
| Control | Which mode it cuts | What it really costs |
|---|---|---|
| Registry mirror with an allow-list | Mode 1, at the root | Standing it up takes days. The cost is the approval queue: if it takes more than 48 hours, the team routes around it and the control stops existing |
| Lock file with hashes and reproducible installs | Later substitution | Almost nothing, and it is usually half done: the file exists, but the pipeline installs by resolving again instead of installing exactly what is locked |
| Installing without running scripts | Execution at install time | An afternoon fixing the three dependencies that genuinely need to compile, and documenting them as exceptions |
| Minimum release age (7-14 days) | Recent maintainer compromise | One configuration line, plus the exclusion list for urgent patches. It does not cover mode 2 |
| Minimum-version policy enforced at resolution | Mode 2 | The change with the most real friction: it breaks builds for the first month. In exchange, the vulnerable version stops being installed instead of being reported afterwards |
| Licence and owner required on approval | Mode 3 | Zero euros and all the cultural resistance: it forces someone to put their name next to every new dependency |
The first three are configuration; the last three are team decisions, which is why they are the ones missing
What does change what the assistant proposes
There is a figure in the Endor Labs report that reads like a technical footnote and is, in fact, the central argument: when the agent has security tooling connected that it can consult while deciding, the share of safe dependency recommendations goes from around 20% to 57%. Almost triple, without changing model and without asking anyone to try harder.
It is worth reading slowly, because it dismantles the usual reaction. The assistant is not breaking your dependency policy: it has never seen it. When it proposes a library and a version, it is reproducing what was reasonable in the corpus it was trained on, which is an average of the internet from two years ago. The list of what you already use, the acceptable minimum versions, the permitted licences and the "we already have something for this" are not discipline to be demanded: they are context to be given.
It is exactly the same move as in agent security: you stop arguing with the model and change what the model can see and do. In Spec-Driven Development that artefact has a name and a place — the project constitution, the document of immutable rules the agent reads before proposing anything. A dependency policy that lives in the tech lead's head is good for telling people off; written into the constitution, it changes the first proposal.
With a caveat that is also in the data: 57% is not 100%. Giving the assistant context reduces the volume you have to stop downstream, it does not replace the six controls. The sensible sequence is the reverse of the usual one: first the registry mirror and reproducible installs, which do not depend on anyone remembering; then the context, which reduces the flow; and only then the process conversations, which by now arrive with far fewer cases.
A Tuesday inventory
You do not need a programme to start, or to buy anything. You need the lock file, which you already have under version control, and forty minutes.
Pull the last ninety days of that file's history — package-lock.json, uv.lock, poetry.lock, pom.xml, whichever is yours — and list which new dependencies came in over that period. For each one, three questions: who asked for it, in which pull request it was discussed and whether it is used today.
The interesting part is almost never finding a dangerous dependency. It is seeing how many rows have all three boxes empty. That number — the share of suppliers that entered your product without anyone deciding anything — is what turns this from a tech lead's intuition into a figure you can bring down next quarter. And unlike almost everything else measured in a development team, you can get it this afternoon and it admits no argument about methodology.
Frequently asked questions
Is the hallucinated package a real risk, or security marketing?
It is a demonstrated attack surface and, to date, without a public malicious incident exploiting it. The order matters. Spracklen and his team measured 440,445 references to non-existent packages across 576,000 code samples, and the 2026 work on frontier models finds 127 names that all five evaluated models invent identically, of which 53 remained free to register after PyPI's and npm's defences. Socket, which took part in the disclosure, states plainly that there is no evidence any of them has been registered maliciously. The one documented case of this reaching the real world is still Bar Lanyado's experiment: he registered huggingface-cli in December 2023, by February 2024 the README of an Alibaba repository was telling people to install it, and it collected more than 15,000 genuine downloads in three months with a harmless package.
How do you cut off the package that does not exist without slowing the team down?
With a registry mirror and an allow-list of names. It is the only control that attacks this failure mode at the root, because an invented name is not in the mirror and the install fails on the first attempt, locally, before it reaches anyone. The real cost is not technical — standing up an artifact proxy takes days — it is process: someone has to approve additions, and if that queue takes a week the team routes around it. What holds the control together is a short turnaround and a named owner for each addition, not a long list.
If the AI proposes a version with a known CVE, won't our scanner catch it?
It catches it late and with noise, which in practice is not catching it. The scanner reports after the merge, across a whole repository, mixed in with findings from transitive dependencies nobody will touch this week. Wang and his team, across ten models and a thousand tasks, found that between 36.70% and 55.70% of tasks end up with at least one known CVE in the specified version, and that between 72.27% and 91.37% of those CVEs had been published before the model's own knowledge cutoff. The control that changes something is a minimum-version policy enforced at dependency resolution: the vulnerable version is never installed, instead of being installed and then reported.
Don't cooldowns delay security updates?
They do delay updates, which is why they are configured with exceptions. The case for them was made by William Woodruff in November 2025, reviewing ten supply-chain attacks from 2024 and 2025: in eight of the ten, the window between publishing the compromised package and detecting it was under a week; a seven-day wait avoids almost all of them and fourteen days avoids all but one. The trade-off is managed with an exclusion list for urgent patches, which pnpm has had from the start and npm is still debating. What you should not expect from a cooldown is coverage of the other failure mode: it protects against the package that is too new, not the one that is too old.
What about licensing for the code and the dependencies the AI brings in?
It is the least examined part and the one that ages worst. The 2026 OSSRA report, across 947 audited codebases, finds licence conflicts in two thirds of them, up from 56% the year before: the largest year-over-year jump in its history. It gives a two-part explanation: more components per application — 30% more in a year — and generated fragments derived from copyleft sources that arrive without their licence attached. The organisational mismatch shows up in the same survey: 76% of companies review generated code for security risk, only 54% look at intellectual property and licensing, and just 24% review all four dimensions.
Where do I start this week without launching a programme?
With a forty-minute inventory of your lock file, which you already have under version control. Pull the dependencies that came in over the last ninety days from that file's history, and ask each one three questions: who asked for it, in which pull request it was discussed, and whether it is used today. What usually shows up is not a dangerous dependency, but that most of them have no answer to any of the three. That list, with the empty boxes on display, is a different conversation from asking for budget for a tool: it turns an intuition into a number you can bring down next quarter.
Sources cited
- Spracklen, J., Wijewickrama, R., Sakib, A. H. M. N., Maiti, A., Viswanath, B. and Jadliwala, M. — We Have a Package for You! A Comprehensive Analysis of Package Hallucinations by Code Generating LLMs (USENIX Security 2025; 576,000 samples and 16 models; 19.7% hallucinated references, 205,474 unique names, 43% repeated in all ten queries, 13.4% at edit distance 1-2)
- Churilov, A. — The Range Shrinks, the Threat Remains: Re-evaluating LLM Package Hallucinations on the 2026 Frontier-Model Cohort (preprint, not peer reviewed; 199,845 prompts and five frontier models; 4.62%-6.10%, 127 shared names, 53 registrable)
- Socket — New Study Identifies 53 Slopsquatting Targets Across 5 Frontier LLMs (22 July 2026; validation of the names against the registry and the clarification that there is no evidence of malicious registration)
- Claburn, T. — AI bots hallucinate software packages and devs download them (The Register, 28 March 2024; Bar Lanyado's experiment with
huggingface-cli, the Alibaba README and the 15,000-plus downloads) - Endor Labs — 2025 State of Dependency Management (4 November 2025; more than 10,000 repositories; one in five recommended versions safe, 44-49% with known vulnerabilities, 20% to 57% with security tooling connected)
- Wang, C., Wu, J., Ling, X., Luo, T. and Zhao, C. — Correct Code, Vulnerable Dependencies: A Large Scale Measurement Study of LLM-Specified Library Versions (May 2026; 10 models and 1,000 tasks; 36.70%-55.70% of tasks with a known CVE and 72.27%-91.37% of those CVEs predating the knowledge cutoff)
- Black Duck — 2026 Open Source Security and Risk Analysis (OSSRA) (25 February 2026; 947 codebases and 17 industries; components +30%, files +74%, mean vulnerabilities +107%, licence conflicts in two thirds versus 56%)
- Woodruff, W. — We should all be using dependency cooldowns (21 November 2025; ten attacks from 2024-2025, eight with a window under one week)
- Nesbitt, A. — Package Managers Need to Cool Down (4 March 2026; the inventory of versions and wait options in npm, pnpm, Yarn, Bun, uv, pip, Poetry, Bundler and Cargo)
- Endor Labs — State of Dependency Management 2023 (95% of vulnerabilities in transitive dependencies; 71% of a Java application's code coming from open source, of which around 12% is used)

Jordi García is Tech Lead at onext. He works on bringing AI into governed production across development and product teams —with Spec-Driven Development, context engineering and human verification at every step— and authors onext's technical insights on the method, quality and cost of applied AI.
LinkedIn →