Skip to main content
Whitepapers
Best Practices

Securing the Software Supply Chain: A 2026 Defender's Playbook

A practical playbook for defending the software supply chain in 2026: the attack patterns behind the year's biggest incidents, and the controls that stop them.

May 27, 2026 13 min 2,479 words 13 sections Breachline Labs

The defining security story of 2026 is not a single breach. It is the realization that the software supply chain, the chain of registries, build systems, and automation that turns source code into running software, is itself the target. Attackers stopped trying to find a bug in your code and started trying to own the pipeline that ships it.

This playbook lays out the attack patterns behind the year's biggest incidents, the frameworks that exist to counter them, and a concrete, prioritized set of controls. It is written for engineering leaders and security teams who need to move from "we have an SBOM somewhere" to a supply chain that resists real attacks.

Why the supply chain is the target

The economics are simple. Compromising one widely used package, action, or build system gives an attacker reach into every organization downstream, all of it backed by trust the victims already extended. Three incidents from 2026 make the pattern concrete.

  • TeamPCP (CVE-2026-33634). A threat actor rewrote the mutable Git tags of the Trivy and Checkmarx GitHub Actions, so every pipeline that ran those scanners executed a credential stealer. The harvested tokens were then used to poison LiteLLM and Telnyx on PyPI and dozens of npm packages. One stolen service-account token cascaded across five ecosystems.
  • The LiteLLM PyPI compromise. Malicious versions 1.82.7 and 1.82.8 shipped a .pth file that ran on every Python interpreter startup and passed pip's hash verification, because the file matched what the registry advertised. Hash checks confirm integrity, not intent.
  • The Axios npm compromise. A maintainer account takeover let attackers publish a backdoored release of one of the most widely used HTTP clients in the npm ecosystem, delivered through a postinstall hook with no source change to the library itself.

Across all three, the same weaknesses recur: mutable references, long-lived publishing credentials, install-time script execution, and verification that checks integrity but not provenance.

The anatomy of a supply chain attack

Rendering diagram

Every link in this chain is a place to intervene. The rest of this playbook works through the controls link by link, then maps them to a maturity model you can adopt incrementally.

The blast radius problem

A direct dependency is a decision you made. The packages it pulls in are not. A typical application has a handful of direct dependencies and hundreds to thousands of transitive ones, and every one of them runs with the same trust as code you wrote yourself. That is the leverage an attacker buys by compromising a single popular package: reach into everything downstream, with none of the friction of breaking in directly.

The TeamPCP campaign is the clearest illustration. One stolen service-account token did not compromise one project. It rewrote shared GitHub Actions, which ran in every pipeline that used them, which harvested more tokens, which poisoned packages across five separate ecosystems. The initial foothold was small. The blast radius was the entire dependency graph that trusted it.

This is why integrity checks are necessary but not sufficient. A hash proves a package is the one the registry advertised. It says nothing about whether that package, the account that published it, or the build that produced it should be trusted at all. Defending the supply chain means shrinking the blast radius (least privilege, scoped tokens, isolated builds) and verifying provenance, not just integrity, at every link.

The defender's frameworks

You do not have to invent the defenses. Two open frameworks, used together, address most of the chain.

SLSA: provenance and build integrity

SLSA (Supply-chain Levels for Software Artifacts) defines escalating levels of build integrity. The core idea is provenance: a signed, verifiable statement of how an artifact was built, by which builder, from which source.

LevelWhat it adds
L0No guarantees. Local or ad-hoc builds.
L1The build platform generates provenance describing how the artifact was built.
L2Provenance is signed by a hosted build service, and build logs are tamper-evident.
L3Hardened, isolated builds with non-falsifiable provenance, resistant to a compromised build step.

For most teams, SLSA Level 2 is the right near-term target. It is achievable on GitHub Actions or GitLab CI in a day or two and defeats the most common attack patterns. Level 3 is the goal for critical or regulated components. SLSA v1.1 is the current stable release.

Sigstore: keyless signing tied to identity

Sigstore (a Linux Foundation project backed by Google, Red Hat, and others) provides free, keyless artifact signing. Instead of managing long-lived signing keys, you sign with a short-lived certificate tied to your build's OIDC identity, and anyone can verify that an artifact was produced by a specific workflow in a specific repository. This directly counters the stolen-publishing-token pattern: there is no durable key to steal, and the signature proves origin, not just integrity.

Used together, SLSA answers "how was this built and can I trust the builder," and Sigstore answers "who built it and can I prove it." Hash verification alone, as the LiteLLM incident showed, answers neither.

The controls, prioritized

Not every control is equal. This is the order we recommend, by leverage against the 2026 attack patterns.

Tier 1: stop the common attacks (do these first)

  1. Pin to immutable references. Reference dependencies and GitHub Actions by full commit SHA or content digest, never by a movable tag like @v1 or @latest. A pinned digest cannot be silently repointed, which is exactly what defeated the TeamPCP tag-rewrite.
  2. Commit lockfiles and install from them. Use npm ci, pip install --require-hashes, or the equivalent, so builds resolve from a reviewed lockfile rather than from open version ranges that auto-pull a poisoned release.
  3. Disable install scripts in CI. Run npm ci --ignore-scripts. This blocks the postinstall hook that the Axios compromise relied on. Audit which packages genuinely need scripts and handle them explicitly.
  4. Eliminate long-lived publishing credentials. Replace static npm, PyPI, and registry tokens, and personal access tokens, with short-lived OIDC token exchange. There is then no durable secret for a stealer to harvest.
  5. Audit pull_request_target and similar triggers. These run with write access and were the original entry point in the TeamPCP campaign. Treat any workflow that runs untrusted code with elevated permissions as a critical review item.

Tier 2: raise the floor

  1. Adopt SLSA Level 2 provenance for your own published artifacts, so downstream consumers can verify how you built them.
  2. Sign artifacts with Sigstore and verify signatures on the consume side, not just the produce side.
  3. Generate and actually use an SBOM. A Software Bill of Materials is only useful if you query it against known-malicious package and version lists and act on hits. An unread SBOM is paperwork.
  4. Scope CI permissions to least privilege. A build job should not hold credentials it does not need. Separate the right to build from the right to publish.

Tier 3: detect what slips through

  1. Monitor build-time behavior, not just manifests. The malicious LiteLLM content was advertised honestly, so manifest checks passed. Detection has to include behavior: unexpected outbound connections during a build, secret access from unusual user agents, new .pth files, new systemd units, and pod creation in sensitive namespaces.
  2. Watch for anomalous publish events. A release published outside your normal CI path, like the direct-to-PyPI uploads in the LiteLLM and Axios incidents, should raise an alert.
  3. Continuously test, do not rely on a quarterly snapshot. Supply chain risk changes every time a dependency updates. Point-in-time assurance misses everything that happens between tests.

A maturity model you can adopt incrementally

StageYou haveYou are protected against
ReactiveLockfiles, occasional scansKnown-bad versions you happen to scan for
HardenedPinned digests, --ignore-scripts, OIDC publishingTag rewriting, postinstall hooks, token theft
VerifiableSLSA L2 provenance, Sigstore signing and verificationBuilder compromise, forged or repackaged artifacts
ContinuousBehavioral build monitoring, continuous testingNovel attacks and the gaps between releases

Most teams that suffered in 2026 were stuck at "reactive." The jump to "hardened" is cheap and stops the majority of real attacks. "Verifiable" and "continuous" are where mature programs are heading.

Hardening GitHub Actions: a worked example

Most of the Tier 1 controls fit in a single release workflow. The example below is the shape to aim for: a read-only default token, OIDC instead of a stored publishing secret, every action pinned to a full commit SHA, and an install step that refuses to run package scripts.

# .github/workflows/release.yml
permissions:
  contents: read          # least privilege by default
  id-token: write         # OIDC for keyless publish, no stored secret

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      # Pin every action to a full 40-char commit SHA, never @v4 or @latest.
      # The trailing comment records the human-readable version.
      - uses: actions/checkout@<full-commit-sha>      # v4.x
      - uses: actions/setup-node@<full-commit-sha>    # v4.x
        with:
          node-version: 20
          registry-url: https://registry.npmjs.org

      # Resolve from the committed lockfile and run no install-time scripts.
      - run: npm ci --ignore-scripts
      - run: npm run build

      # Publish with a short-lived OIDC token and attach build provenance.
      # There is no long-lived npm token in this workflow to steal.
      - run: npm publish --provenance --access public

Three things make this resistant to the 2026 patterns. The SHA pins mean a rewritten tag cannot change what runs, which is exactly what defeated the TeamPCP campaign. The --ignore-scripts flag neutralizes postinstall hooks during the build. And id-token: write with npm publish --provenance replaces the durable publishing token, the thing a credential stealer is hunting for, with a credential that exists only for the life of the job and is bound to this repository and workflow.

Apply the same pattern in GitLab CI with ID tokens and protected jobs, and in any pipeline by separating the permission to build from the permission to publish.

Verifying artifacts on the way in

Producing provenance is half the job. The other half is refusing to install anything you cannot verify. Verification belongs on the consume side, in the build that pulls a dependency, not only on the side that publishes it.

# Confirm a Sigstore signature ties an artifact to the workflow that built it
cosign verify-blob \
  --certificate-identity-regexp 'https://github.com/org/repo/.github/workflows/.*' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  --signature artifact.sig --certificate artifact.pem \
  artifact.tar.gz

# Check SLSA provenance: built from the expected source, by the expected builder
slsa-verifier verify-artifact artifact.tar.gz \
  --provenance-path artifact.intoto.jsonl \
  --source-uri github.com/org/repo

# For npm packages, verify published provenance and signatures of the tree
npm audit signatures

The identity regex is the control that matters. A signature alone only proves something signed the artifact. Binding it to a specific repository and workflow is what proves the right thing signed it, and it is what a stolen token cannot forge. Fail the build when verification fails, rather than logging a warning and continuing.

Securing the maintainer account

Two of the three 2026 incidents started with a person, not a pipeline: a maintainer account was taken over, or a service account token was stolen and reused. Provenance does not help if the attacker is publishing as you.

  • Require phishing-resistant 2FA (passkeys or hardware keys) on every account with publish rights, across npm, PyPI, and your source host. SMS and TOTP are better than nothing but are phishable.
  • Remove human publish rights entirely where you can. If only the CI workflow can publish, through OIDC, there is no personal credential to phish and no direct-to-registry path to abuse.
  • Use granular, scoped, short-lived tokens for the cases that still need a token. A token that can publish one package for one hour is a far smaller prize than a classic token that can publish everything forever.
  • Protect the publish path. Require signed commits, protected branches, and required reviews on the workflows that hold id-token: write or publishing permission. The workflow that can publish is as sensitive as the code it ships.
  • Alert on out-of-band publishes. A release that did not come from the protected CI path, like the direct-to-PyPI uploads in the LiteLLM and Axios incidents, is an incident until proven otherwise.

Metrics: what good looks like

Supply chain security is measurable. These few indicators separate a program that would have survived 2026 from one that would not.

IndicatorTarget
Dependencies and actions pinned to a digest or SHA100% in CI
First-party artifacts published with SLSA L2+ provenance100%
Long-lived registry or publishing tokens in use0
Workflows running untrusted code with write permissions0
Builds that verify signatures and provenance before install100%
Mean time to detect an anomalous publish eventMinutes, not weeks

If you track nothing else, track the first three. They map directly to the root causes behind the year's incidents, and moving them to target is mostly configuration, not new tooling.

How Breachline fits

A playbook is only as good as its verification. Nebula's supply chain analysis cross-references your dependency tree against known malicious package and version lists, flags phantom dependencies that appear in a manifest but are never imported in source, and audits for unpinned references vulnerable to tag rewriting. Beyond the manifest, it tests the application and infrastructure around your pipeline for the SSRF, credential exposure, and injection flaws that let a single stolen token escalate into full compromise. The recurring lesson of 2026 is that trust is the attack surface, and trust has to be verified continuously, not signed off once a quarter.

Takeaways

  • The 2026 incidents share four root causes: mutable references, long-lived credentials, install-time scripts, and integrity-without-provenance verification.
  • Tier 1 controls (pin to digests, install from lockfiles, disable scripts, OIDC publishing, audit risky triggers) are low effort and stop the common attacks. Do them first.
  • Use SLSA for build provenance and Sigstore for identity-bound signing. Together they answer questions hash checks cannot.
  • Treat supply chain security as continuous. The risk changes with every dependency update.

Sources