loader
critical risk Build / Dependencies / Distribution current

Software Supply Chain Compromise

Attacking what you trust rather than what you expose — the build system, the dependency graph, or the update channel that delivers signed code to every customer.

Defender-oriented briefing. This page describes behavior, observable signals, prevention and response. Operational attack instructions are intentionally excluded.

How it works

Trusted automation holds broad access and can distribute a malicious change downstream. Naming, registry priority or spelling errors introduce hostile packages into the dependency graph. Compromise at a vendor, signer or build system makes malicious content arrive legitimately signed.

Attacking trust rather than exposure

Every other category in this wiki attacks something you expose. This one attacks something you trust, which is why it bypasses the controls built around the perimeter entirely.

Code arriving through the build pipeline is reviewed and signed. A dependency pulled from a registry is installed by an automated process nobody watches. A vendor update is signed by the vendor and installed by policy. In each case the delivery mechanism is the one designed to be trusted, and the malicious content inherits that trust completely.

The economics strongly favour the attacker: compromising one build system or one popular package reaches every downstream consumer at once, which is why this technique has moved from theoretical to routine.

The build pipeline is production

CI/CD systems are frequently secured as developer tooling despite holding deployment credentials, signing keys, cloud access and the ability to alter what ships. In terms of what it can reach, a build system is production infrastructure.

The recurring weaknesses follow from that mismatch: long-lived credentials in variables, runners shared between jobs so one build can observe another's secrets, workflow definitions editable by anyone who can open a pull request, and build steps that execute arbitrary code from a dependency during install.

That last point deserves emphasis. Installing dependencies commonly runs code — install scripts, build hooks — inside the pipeline, with the pipeline's credentials. A malicious package does not need to reach production to be damaging; it already ran somewhere privileged.

The countermeasures are ephemeral runners that hold no standing credentials, secrets scoped per job and short-lived, protected workflow definitions, and provenance so the artifact can be tied to the source that produced it.

Dependency confusion and typosquatting

These exploit resolution rather than code. Typosquatting registers a name close to a popular package and waits for a misspelling. Dependency confusion is more mechanical: if a build resolves from both a private and a public registry, and the resolver prefers the higher version or the public source, an attacker who publishes a high version of your internal package name captures the resolution.

The unsettling property is that nothing on your side changed. The build ran, the name matched, a package installed. Internal package names also leak readily — in logs, error messages, published artifacts and job postings.

Controls: register your internal namespaces publicly so the names cannot be claimed, configure resolution so private sources are authoritative rather than merely preferred, pin with lockfiles and hashes so a resolved artifact cannot silently change, and review dependency additions as code rather than as configuration.

When the vendor is the vector

The hardest case is a legitimate vendor shipping a compromised update. Signature verification passes because the vendor genuinely signed it. Reputation checks pass because it is genuinely their software. The update installs because updating promptly is correct advice.

There is no clean prevention here, and it is worth being honest about that rather than pretending otherwise. What exists is damage limitation: staged rollout so an update reaches a small population first, behavioural monitoring so a familiar application acting unfamiliarly is noticed, network restrictions so software cannot reach destinations unrelated to its function, and a rehearsed rollback.

An inventory of what you actually run — an SBOM, or simply an accurate asset list — is what converts a vendor advisory from a research project into a query. Organisations that could not answer "do we run this, and where" spent the first days of past incidents finding out.

Also known as

dependency confusion typosquatting compromised update supply-chain backdoor build system compromise

What defenders may observe

  • Build steps, runners or workflow files changing unexpectedly
  • Artifacts that differ from the reviewed source
  • Pipeline secrets accessed by an unusual job
  • A dependency resolving to an unexpected registry or maintainer
  • Lockfiles or resolved sources changing without an intended edit
  • A signed update behaving anomalously, or many customers reporting one new indicator

Prevention and mitigation

  • Use ephemeral, isolated build runners with no standing credentials
  • Generate and verify build provenance; prefer reproducible builds
  • Protect branches, require review, and issue short-lived deployment credentials
  • Pin dependencies with lockfiles and hashes; control private namespaces and registry priority
  • Verify signatures and provenance rather than trusting the channel
  • Deploy vendor updates in stages with behavioural monitoring and a tested rollback

Initial response priorities

  • Freeze unauthorized control-plane changes and rotate credentials.
  • Trace the affected artifact, pipeline or trust relationship.
  • Rebuild from verified sources and review downstream exposure.

Use your approved incident-response plan and adapt decisions to your environment. This is educational guidance, not a substitute for live incident leadership.

Authoritative references