Skip to content
The Cyber Security Place

Governance

Supply chain security in 2026: twelve decisions, fifteen hundred dependencies

Somebody on your team evaluated a dozen libraries. What shipped was a graph of several hundred more, maintained by people whose names nobody in the building has read — and every one of them can publish a new version tonight.

Last reviewed August 25, 2026

A mid-sized web application contains between 500 and 2,000 components once transitive dependencies are counted, against roughly a dozen anybody chose. Open-source malware on public registries grew about 73% in a year, with one ecosystem accounting for over 99% of it. Around 77% of organisations reported a supply chain incident in a twelve-month window and roughly 1 in 10 are running a package already known to be malicious. One actor published more than 150,000 malicious packages in days. The Cyber Resilience Act makes component inventories and 24-hour reporting mandatory from September 2026, with penalties reaching €15m or a share of worldwide turnover. Most malicious packages carry under 10,000 weekly downloads, which is the signature of typosquatting rather than of compromising something popular. Third-party involvement in breaches roughly doubled in a single year. The cheapest effective control is a lockfile that fails the build when it changes without review.

What is actually in your build?

Start with the dozen dependencies somebody evaluated and expand one level at a time. The counters are the argument.

Worked exampleTwelve dependencies, expanded

1,506packages in the build
612people who can publish to it
12anybody actually chose
  1. What you chose

    +12 packages

    The dependencies somebody on your team decided to add, evaluated at the time, and listed in the manifest. This is the only level anyone has ever looked at.

  2. What they chose

    +64 packages

    The direct dependencies of your direct dependencies. Already past the point where a review happened, and already including projects whose names nobody on the team would recognise.

  3. Two removes

    +210 packages

    The count is now larger than any team could read, and the maintainers are individuals rather than organisations. Several of these packages exist to do one thing in four lines.

  4. Three removes

    +480 packages

    Somewhere in here is a package that has not been updated in six years, is depended on by something popular, and whose maintainer stopped reading their email in 2021.

  5. The tail

    +740 packages

    The full graph for a mid-sized application. Every one of these executes with the same permissions as your own code, and any of their maintainers can publish a new version tonight.

Figures describe a mid-sized JavaScript application rather than a measurement of one. The order of magnitude is what matters: published surveys put a typical web application's component count somewhere between five hundred and two thousand, and the number anybody evaluated stays at twelve.

Two numbers on that panel do the work. The first is the gap between what was chosen and what shipped, which is roughly two orders of magnitude and is a property of the ecosystem rather than of anyone's diligence. The second is the maintainer count, because that is the actual attack surface: every one of those people holds a publishing credential, and compromising any of them puts code into your build.

The uncomfortable part is that none of this is a mistake anybody made. Small, focused packages that each do one thing are good engineering by every standard the industry has taught for fifteen years. The security consequence of that design is a graph with hundreds of independent points of trust, and both things are true at once.

Who can publish into your build

One square per maintainer with publishing rights over something that ends up compiled into that application. Twelve are the ones somebody chose.

12 chosen600 arrived transitivelyevery square has the same power to publish a version tonight
Maintainer count for the same example application, deduplicated. Real graphs vary enormously; the shape of the picture does not.

How does anyone actually exploit that?

Four routes, and they differ enormously in how much work they require. Ordering them by effort explains why the volume sits where it does.

Typosquatting requires no compromise at all. Publish a package whose name differs from a popular one by a character, a hyphen or a plural, and wait. It preys on human typing and on scripts somebody wrote from memory. Most malicious packages found on registries have almost no downloads, which is precisely the signature of this technique operating at volume — one actor published over a hundred and fifty thousand of them in a matter of days, overwhelming the moderation capacity of the registry as much as targeting any particular victim.

Dependency confusion exploits resolution order rather than names. Register a public package with the same name as one of a company's internal ones, and any build tool configured to check the public registry first will fetch yours. The remedy is configuration, which makes this the cheapest of the four to close and the most embarrassing to leave open.

Publisher takeover is the expensive, effective variant. Phish or buy the credentials of somebody who maintains a genuinely popular package, publish a release, and reach everybody who updates. It requires targeting and it produces reach that typosquatting never does.

Build system compromise is the rarest and the worst. Instead of the source, the attacker seizes the pipeline that turns source into artefacts, so the published code and the shipped binary differ. Reviewing the repository shows nothing wrong, because nothing in the repository is wrong.

Which controls survive the arithmetic?

Any remedy that requires reviewing fifteen hundred packages is not a remedy. Four things work at this scale, and all of them accept that you will never know what most of your dependencies do.

Pin everything and gate the lockfile. A compilation that resolves versions at install time swallows whatever the registry happens to offer that morning. A lockfile fixes the exact versions, and a rule that fails the build when the lockfile changes without review turns a silent update into a pull request somebody has to approve. This single change removes most of the value of a maintainer takeover.

Generate the inventory automatically, every build. The document itself is beside the point. It is being able to answer "are we affected" in the hour a vulnerability is published rather than in the week it takes to ask around. A list produced once and filed describes a graph that changed the next afternoon.

Reduce what you depend on. The least fashionable measure, and the only one that shrinks the problem instead of administering it. Every dependency removed is a maintainer removed, and a surprising number of small packages exist to do something the standard library now does.

Limit what the build can reach. A toolchain with unrestricted network access and long-lived cloud credentials converts any tainted library into a foothold inside your infrastructure. One with neither turns the same compromise into a broken build, which is a considerably better Tuesday.

The four sit in a deliberate order. Pinning is free and immediate. Inventory generation is a flag in a pipeline. Reducing dependencies is genuine engineering work with a payoff that arrives slowly. Restricting the build touches the platform team and takes a quarter. Attempting them in the reverse order is how this subject becomes a programme that stalls, and doing the first two costs a week and removes the failures that arrive without warning.

Can you tell a healthy dependency from a doomed one?

Partly, and the signals that matter are not the ones most teams check. Download counts and star ratings gauge popularity, which correlates with being worth attacking, not with being maintained. Four questions get further, and all four are answerable in a couple of minutes from the project's own pages.

How many people can publish it? A package maintained by one person is one phished account away from a bad release, and it is also one bereavement or one career change away from being unmaintained. Neither of those is a criticism of the maintainer; both are properties of the arrangement.

When did the last release happen, and what was in it? A gap of three years can mean the package is finished, which is a legitimate state that the industry is oddly reluctant to accept. It can also mean nobody is home. The difference usually shows in whether the open issues have replies.

Does the published artefact come from the published source? For most ecosystems this is not verifiable without effort, which is precisely why build system compromise is attractive. Where a project publishes provenance attestations, that is worth more than any other signal on this list.

What does it need at install time? A package that runs a script during installation is executing code on a developer machine and in the build, before anybody has reviewed anything. Most packages do not need to, and the ones that do should be able to explain why.

Applying that to fifteen hundred packages is impossible and applying it to the twelve direct ones is an afternoon. That asymmetry is worth accepting rather than fighting: the direct dependencies are the ones you can still decide about, and every one you decline never brings its own graph with it.

The other supply chain: people with your passwords

Software dependencies get the attention because they are countable. The larger practical exposure for most organisations is the set of companies holding privileged access to their systems: managed service providers, remote monitoring tools, backup platforms, payroll processors, the agency with an administrator account in the marketing platform.

The trade press filed this under operational risk, not supply chain risk, when it began covering it seriously, in pieces like this one from May 2015. The framing was right and the scale has changed: third-party involvement in breaches roughly doubled in a single recent year, from about one incident in seven to nearly one in three.

Questionnaires are the standard response and they measure the wrong thing. A supplier's certification tells you they had a process at audit time. What decides your outcome is what their software can do on your systems today, and that is answerable by inspection, not by interview. Three questions get further than forty: what can their software do here without asking us, how would we know if it did something unexpected, and how long would their access persist if we terminated the contract this afternoon.

The third question produces uncomfortable answers reliably. Agent software installed years ago on every endpoint, service accounts created during an implementation and never reviewed, VPN credentials shared across a support team whose membership has turned over twice. None of that appears on a questionnaire and all of it is visible in an afternoon of looking.

Why inventories stopped being optional

Component inventories spent years as a good idea that nobody funded, for the ordinary reason that they produce no visible benefit until the morning something goes wrong. Two regulatory movements have changed the calculation, and neither is about security teams.

Public procurement moved first. Software sold to government buyers in several jurisdictions now has to arrive with a component list, which promoted the manifest from an internal hygiene project to a condition of sale. Vendors who resisted for a decade produced one within a quarter of it appearing in a contract.

The European Cyber Resilience Act generalises that to anything with a digital element placed on the market. Manufacturers must maintain the inventory, handle vulnerabilities across a defined support period, and report actively exploited flaws within twenty-four hours, with those duties beginning in September 2026. Penalties reach fifteen million euros or a percentage of worldwide turnover.

For a buyer the practical shift arrives earlier than enforcement does. Asking a supplier for a component inventory has been a request that could be politely declined; it is becoming a thing they are obliged to have. That shifts the exchange from persuasion to procurement, which is a considerably shorter one.

The morning a component you use turns out to be malicious

This arrives as a headline rather than an alert, usually before anybody has told you whether you are affected. The organisations that handle it well are not the ones with better tooling. They are the ones that had already answered three questions and could reach the answers quickly.

Are we using it at all, and where? This is the inventory question, and it is the reason inventory generation is worth automating. An organisation that can query a component name across every build knows within minutes. One that cannot spends the first day asking teams to check, receiving inconsistent answers, and treating silence as a no.

Which versions, and when did they enter? Malicious releases are usually specific versions published in a window. Knowing you use the package is half an answer; knowing you pinned to a version from before the window is the other half, and it converts an emergency into a note in the log.

What could it have reached? A compromised build-time dependency had access to whatever the pipeline had access to. If that pipeline held long-lived cloud credentials, the incident is not about the package any more — it is about what those credentials could do, and the investigation belongs in your infrastructure rather than in your dependency graph.

Rehearsing this once is cheap and clarifying. Take a package you genuinely depend on, pretend the announcement landed this morning, and time how long the three answers take. Most teams discover that the first question — do we use it — is the one that costs them the day, and that it is also the one that a flag in a pipeline would have removed entirely.

One further thing worth deciding in advance: who is allowed to say «stop shipping». A compromised dependency discovered mid-afternoon puts a release train and a security judgement in direct conflict, and the argument goes better when the authority was settled while nobody was under pressure. It is usually the same person who can authorise taking production offline, and writing both down together costs one line.

None of the three questions is answerable by buying something, which is why this preparation tends to lose to work that comes with a demonstration. It is also why the organisations that have it are the ones that lived through a morning like this once already, and decided afterwards that they would rather not repeat the experience of finding out by asking around.

A decade of being right and unfunded

Supply chain risk has an unusual history for a security subject: it was identified early, described accurately, and ignored for years — and the reason was neither ignorance nor dispute: the remedies cost money and the casualties were somebody else.

It appears in this archive as a named risk from January 2015, sitting in lists of things organisations ought to worry about, alongside items that received far more attention and budget. Coverage climbed through the second half of the decade and peaked in 2019, largely on the strength of third-party breach reporting rather than software dependencies.

SolarWinds, from early 2021 ended the argument about whether this was theoretical. What made it decisive was never novelty, since the technique had been described for years, but that the victims were the kind of organisations that get legislators' attention, and that the compromise arrived through an update those organisations had been told to install.

The lesson worth carrying is about how this class of risk gets funded. Nothing about the analysis improved between 2015 and 2021; what changed was that the consequence became legible to people outside security. Anyone trying to fund preventive work on a quiet subject is fighting that same pattern, and the argument that works is rarely the technical one.

What changes when code is suggested rather than chosen?

A dependency used to enter a codebase because somebody searched for a library, compared a few, and made a decision they could later explain. Increasingly it enters because an assistant suggested an import and the suggestion was accepted, in the same motion as accepting a variable name.

That removes the one step where evaluation happened. The twelve reviewed choices at the top of this page were reviewed because adding a dependency used to cost enough attention to prompt a decision. When the cost drops to a keystroke, the count rises and the review does not.

There is a second-order problem that is harder to characterise. A suggested import can be a package that does not exist, and an attacker who watches which names get suggested can register them. The failure mode is a developer installing something that was recommended to them, from a registry, under a plausible name — with every step of the process behaving exactly as designed.

None of that argues against the tooling, which is genuinely useful. It argues for moving the gate to where the decision now happens: a check at install time that the package exists, is not brand new, and has more than a handful of users costs seconds and catches the entire class.

There is a related shift on the reviewing side that cuts the other way and is worth noting, because this subject attracts more pessimism than it deserves. Reading the source of an unfamiliar package used to be a specialist task nobody had time for. Summarising what a small package actually does is now cheap, which makes spot checks on the direct dependencies practical for teams that would never have attempted them. The tooling that lowered the cost of adding a dependency also lowered the cost of looking at one, and only the first of those has been widely adopted.

Where to start on a Monday

The subject is large enough to be paralysing and the first three steps are small enough to finish this week. None of them requires a purchase or a programme.

Check that your lockfiles are committed and enforced. Every repository, not the flagship one. A surprising number of build pipelines resolve versions fresh because somebody removed a lockfile to fix an install error in 2023 and nobody put it back.

Turn on inventory generation in the pipeline. Most build tooling can emit a component list with a flag. Store it somewhere queryable rather than as a build artefact nobody can find, and the next published vulnerability becomes a query instead of an investigation.

List who has privileged access from outside. Not the supplier list from procurement — the accounts and agents actually present in your systems. Compare the two, and treat the difference as the finding.

After those three, the remaining work is genuinely harder and genuinely prioritisable: restricting what the build can reach, reducing the dependency count, renegotiating notification terms. But an organisation that has done the first three can answer the question that arrives at nine in the morning when a widely used component turns out to be compromised, and that is the difference the whole subject comes down to.

Common questions

What counts as a supply chain attack?

Any compromise that reaches you through something you did not build: a dependency, a build tool, an update channel, a managed service provider, a contractor's laptop. The defining property is that your own defences were never defeated — they were sidestepped through trust you had already granted.

How many components does a typical application contain?

Published surveys put a mid-sized web application somewhere between five hundred and two thousand, counting transitive dependencies. The number a team actually chose and evaluated is usually one or two dozen.

How much malicious activity is on the package registries?

Open-source malware on registries grew by roughly three-quarters in a year, and one ecosystem accounts for the overwhelming majority of it. Most malicious packages have very low download counts, which is the signature of typosquatting, not of compromising something widely used.

What is typosquatting in this context?

Publishing a package whose name differs from a popular one by a character or a hyphen, and waiting for somebody to mistype it or for a script to install it. It requires no compromise of anything, and the registry cannot easily tell it apart from any other new upload.

What is dependency confusion?

Publishing a public package with the same name as one of your internal private packages. If a build tool resolves the public registry first, it fetches the attacker's version. The fix is configuration, not detection: pin the source for internal names.

Does an SBOM actually help?

It helps with the question it answers, which is what you contain. When a vulnerability is published against a component, an organisation with a current inventory knows in minutes whether it is affected. Without one that takes days, and days is the whole exposure.

Is an SBOM enough on its own?

No. A list generated once and filed is a snapshot of a graph that changes every build. The value lies in regenerating it automatically and being able to query it, not in owning the document.

What is the fastest thing to fix?

Pin your dependencies to specific versions with a lockfile, and make the build fail if the lockfile changes without a review. It costs nothing and removes the entire class of attack that relies on a new version arriving silently.

How do managed service providers fit in?

They hold privileged access to many customers at once, which makes a single compromise reach hundreds of organisations. The controls that work are the ones you apply to their access, not the ones you ask them to apply to themselves.

What does the Cyber Resilience Act require here?

Manufacturers placing products on the European market must maintain a component inventory and report actively exploited vulnerabilities within 24 hours, with reporting duties starting September 2026. For buyers it converts a polite request into an entitlement.

Can we audit our way out of this?

Not at this scale. Reviewing fifteen hundred packages is not a task anyone completes, and the maintainer who matters may change next week. The realistic posture is to reduce what you depend on, know what you have, and limit what any single component can do.

What should a supplier questionnaire actually ask?

Fewer questions with harder answers. How would we learn you had been breached, on what timescale, and through what channel. What access does your tooling hold on our systems. And how long would that access persist if we terminated tomorrow.

Supply chain coverage

184 reports on third-party and open source risk, newest first.