Most supply chain attacks don't target your code — they target the dozens of transitive dependencies your code pulls in without anyone reviewing them. A compromised maintainer account, a typosquatted package name, a build step that fetches an unpinned script from the internet: any of these can smuggle malicious code into your production build without touching a single line you wrote. The response to this isn't "audit every dependency," which doesn't scale — it's building a chain of verifiable evidence from source to running artifact, so a compromise anywhere in that chain is detectable rather than invisible.
How dependency compromise actually happens
The realistic attack patterns are not exotic. A maintainer's npm token gets phished and a backdoored patch version gets published. A popular package gets abandoned and someone squats the name with a near-identical one (typosquatting: corss-env instead of cross-env). A CI pipeline pulls a build script over plain HTTP with no integrity check, and a man-in-the-middle swaps it. In every case, the code that runs in production was never reviewed by anyone on your team — it was trusted by default because it came through a package manager.
Lockfile integrity in CI
The cheapest defense against a compromised or accidentally-upgraded dependency is enforcing that CI installs exactly what the lockfile says, and fails loudly if `package.json` and the lockfile have drifted apart.
# npm: fails if package.json and package-lock.json are out of sync,
# and refuses to silently resolve a newer version of any dependency.
npm ci --ignore-scripts
# yarn (classic): same intent — install exactly what's locked.
yarn install --frozen-lockfile --ignore-scripts
# --ignore-scripts blocks postinstall scripts from running during CI
# install. Most supply-chain payloads execute via postinstall hooks,
# so this alone closes a large fraction of real-world attacks.
`npm audit` checks known CVEs against a database — it says nothing about whether the package you're about to install is the one the maintainer actually published, or whether it was tampered with in transit. Integrity comes from the lockfile's recorded hashes, not from vulnerability scanning.
SLSA: what provenance actually proves
SLSA (Supply-chain Levels for Software Artifacts) is a framework for grading how verifiable the path from source code to built artifact is. The core idea is provenance: a signed, tamper-evident statement saying "this exact artifact was built from this exact source commit, by this build system, using these exact steps" — generated automatically by the build platform, not by a human attesting after the fact. At SLSA's higher levels, the build has to run in an isolated, non-interactive environment so that no one — including someone with source repo access — can slip an unreviewed change into the artifact without it showing up in the provenance.
name: build-and-attest
on: push
permissions:
id-token: write # required to mint the signing identity
contents: read
attestations: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci --ignore-scripts && npm run build
# Generates and attaches SLSA provenance for the build artifact,
# signed via GitHub's OIDC-backed Sigstore integration.
- uses: actions/attest-build-provenance@v1
with:
subject-path: 'dist/**'
Signing artifacts with Sigstore and cosign
Sigstore solves the "who signed this and can I trust the key" problem without requiring you to manage long-lived signing keys yourself. Instead of a private key you store and rotate, Sigstore issues a short-lived certificate tied to an OIDC identity (your CI provider's token, or a GitHub Actions workflow identity) at signing time, and records the signature in a public transparency log. `cosign` is the CLI most teams use to sign and verify container images and other artifacts against Sigstore.
# Sign a container image keylessly, using the CI job's OIDC identity
cosign sign ghcr.io/acme/api:1.4.2
# Verify the image was signed by a specific identity (e.g. your CI
# workflow) before pulling it in a deploy pipeline
cosign verify ghcr.io/acme/api:1.4.2 \
--certificate-identity "https://github.com/acme/api/.github/workflows/release.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
Signing an image is only useful if something refuses to deploy an unsigned or wrongly-signed one. Add a cosign verify step (or a Kubernetes admission controller like Kyverno/Sigstore Policy Controller) at the point of deployment, not just as a CI checkbox nobody enforces downstream.
Wrapping up
None of these controls — lockfile pinning, SLSA provenance, cosign signatures — prevent a determined attacker on their own. What they do is convert an invisible compromise into a detectable one: a tampered dependency fails an integrity check, an unsigned artifact fails a deploy gate, a build missing provenance can't claim to be the one your CI actually produced. Supply chain security is less about any single tool and more about closing the gaps where trust was previously implicit — the postinstall script nobody read, the image nobody verified, the artifact that could have come from anywhere.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.