Attackers increasingly skip your application and go after the things that build it: a compromised dependency, a hijacked CI action, a poisoned base image. The new A03 category in the OWASP Top 10:2025, Software Supply Chain Failures, reflects this shift, and in the EU the Cyber Resilience Act turns parts of supply chain hygiene into law, with vulnerability reporting duties since September 11, 2026. This guide covers a practical baseline for teams shipping containers: minimal images, scanning, SBOMs, signatures, provenance and policies that verify them before deployment.

Why supply chain security matters now

A typical service image contains your code plus hundreds of open-source packages and an operating system layer. Every one of them, and every tool in the pipeline that assembles them, is part of your attack surface. Two lessons from recent incidents:

  • CI is a production system. The March 2025 compromise of the tj-actions/changed-files GitHub Action leaked secrets from workflow logs across thousands of repositories (CISA, 2025).
  • You can't fix what you can't see. When a critical vulnerability hits a widely used library, teams with an inventory of their components know within minutes which services are affected; others spend days grepping.

The regulatory push: the Cyber Resilience Act

The EU Cyber Resilience Act, Regulation (EU) 2024/2847, sets cybersecurity requirements for products with digital elements placed on the EU market, including software. Two dates matter (European Commission: CRA):

  • September 11, 2026: manufacturers must report actively exploited vulnerabilities and severe incidents — an early warning within 24 hours, a notification within 72 hours and a final report later (CRA reporting obligations).
  • December 11, 2027: the main obligations apply, including secure-by-design requirements, vulnerability handling and documenting components, among other things through a software bill of materials.

Even if your product is out of scope, your enterprise customers will increasingly ask for SBOMs and evidence of secure build practices.

Layer 1: minimal, pinned base images

Fewer packages mean fewer vulnerabilities and less to patch.

  • Use minimal base images: distroless images contain only the runtime your application needs, without a shell or package manager (Distroless).
  • Use multi-stage builds so compilers and build tools never reach the runtime image.
  • Pin base images by digest, not by mutable tag, and let a bot propose updates.
  • Run as a non-root user and enforce it in Kubernetes with Pod Security Standards (Kubernetes: Pod Security Standards).
FROM eclipse-temurin:25-jdk@sha256:<digest> AS build
WORKDIR /src
COPY . .
RUN ./gradlew bootJar --no-daemon

FROM gcr.io/distroless/java25-debian13@sha256:<digest>
COPY --from=build /src/build/libs/app.jar /app/app.jar
USER nonroot
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Layer 2: scan dependencies and images

  • Dependencies in pull requests: dependency review and automated updates, as in our CI/CD template.
  • Images in CI and registries: scanners such as Trivy or Grype find known vulnerabilities in OS packages and language dependencies.
  • Triage, don't drown. Fail builds on critical vulnerabilities with a fix available; track the rest with owners and deadlines. A scanner that produces 400 findings nobody reads is worse than one with a clear policy.

Layer 3: generate SBOMs

A software bill of materials lists the components in your artifact — names, versions, licenses, hashes. The two established formats are SPDX (an ISO/IEC standard) and CycloneDX (ECMA-424) (SPDX; CycloneDX; ECMA-424). CISA maintains guidance on SBOM minimum elements and practices (CISA: SBOM).

Generate SBOMs at build time, attach them to the image and store them so you can query "which images contain library X version Y?":

# BuildKit can attach an SBOM and provenance attestation to the image
docker buildx build --sbom=true --provenance=mode=max \
  -t registry.example.com/orders:1.4.2 --push .

# Or generate an SBOM separately with Syft
syft registry.example.com/orders:1.4.2 -o cyclonedx-json > orders-1.4.2.cdx.json

See Docker's documentation on build attestations and Syft for details (Docker: build attestations).

Layer 4: sign artifacts

Signatures prove that an image came from your pipeline and wasn't altered. Sigstore's cosign supports keyless signing: in CI, the workflow's OIDC identity obtains a short-lived certificate, and the signature is recorded in a public transparency log, so there are no long-lived signing keys to leak (Sigstore; cosign signing).

# GitHub Actions job excerpt
permissions:
  id-token: write      # OIDC token for keyless signing
  packages: write
  attestations: write
steps:
  - uses: sigstore/cosign-installer@<pinned-sha>
  - run: cosign sign --yes registry.example.com/orders@${{ steps.build.outputs.digest }}
  - uses: actions/attest-build-provenance@<pinned-sha>
    with:
      subject-name: registry.example.com/orders
      subject-digest: ${{ steps.build.outputs.digest }}
      push-to-registry: true

GitHub's artifact attestations generate signed build provenance for your artifacts (GitHub: artifact attestations).

Layer 5: provenance and SLSA

SLSA (Supply-chain Levels for Software Artifacts) is a framework describing increasingly strong guarantees about how an artifact was built (SLSA; SLSA v1.0 levels):

Build level Requirement In practice
L1 Provenance exists The build produces a record of how the artifact was built
L2 Hosted build platform, signed provenance Builds run on a managed CI service that signs provenance
L3 Hardened build platform Builds are isolated from each other; signing secrets are out of reach of build steps

Most teams can reach L2 quickly with a hosted CI and artifact attestations; L3 requires stricter isolation of the build platform.

Layer 6: verify before deploy

Signatures are worthless if nobody checks them. Enforce policies at the cluster: only images signed by your CI identity, from your registry, with no critical vulnerabilities, may run. Kubernetes admission controllers such as Sigstore's policy-controller or Kyverno can verify signatures and attestations at deploy time.

A practical roadmap

  1. Week 1–2: pin actions and base images, minimize CI token permissions, enable dependency review.
  2. Week 3–4: switch to minimal base images and non-root containers; add image scanning with a clear failure policy.
  3. Month 2: generate and store SBOMs for every release; set up a way to query them.
  4. Month 3: sign images and add build provenance; verify signatures at admission in staging, then production.
  5. Ongoing: vulnerability response process with owners and SLAs — a requirement under the CRA for products in scope.

Infrastructure code belongs in the same chain: pin provider versions and review plans, as described in Terraform vs OpenTofu. For the application-level risks, see OWASP Top 10:2025 for web developers.

FAQ

Do we need an SBOM if we don't sell to the EU? Increasingly yes: enterprise customers and US public sector buyers ask for them, and they make vulnerability response much faster.

SPDX or CycloneDX? Both are widely supported. Pick the one your tools and customers use; many tools can produce both.

Is image scanning enough? No. Scanning finds known vulnerabilities in components; signing and provenance prove the artifact wasn't tampered with. You need both.

Does keyless signing mean anyone can sign? No. The signature binds to a specific identity — for example your repository's CI workflow — and verification policies check that identity.

Sources

  1. European Union. Regulation (EU) 2024/2847 (Cyber Resilience Act); European Commission: CRA, reporting obligations.
  2. CISA. Software Bill of Materials and tj-actions/changed-files compromise.
  3. SLSA and SLSA v1.0 levels.
  4. Sigstore and cosign signing overview.
  5. SPDX, CycloneDX, ECMA-424.
  6. Docker. Build attestations; GitHub. Artifact attestations.
  7. Distroless images, Syft, Trivy.