Ravindra BagaleCourses & study guides मराठी

Chapter 52: Dockerfile Instructions Explained: FROM, RUN, CMD vs ENTRYPOINT, COPY vs ADD, Multi-Stage and BuildKit

52.11 SBOM and provenance attestations with buildx

Friends, when a new security bug like Log4Shell comes out, the first question from the boss is: which of our images contain this library? If your images carry an SBOM, you answer in minutes. Today we learn SBOM, the list of everything inside an image, and provenance, the record of how and where it was built.

1. Start from a story

In December 2021 Log4Shell hit. Ankit's team at PhonePe had about 300 images in their registry. Nobody knew which ones had log4j-core inside.

They pulled every image and scanned each one by hand for two days. Some images were built from laptops and nobody knew which commit they came from.

After that, Ankit changed the pipeline. Every build now adds --sbom=true and --provenance=mode=max. The registry stores both next to the image.

Next time a library bug came out, one script read the SBOMs of all images and listed the affected ones in eight minutes. Provenance showed the exact commit and pipeline for each. Today we build that habit.

Image layersthe appSBOM attestationlist of packages and versionsProvenance attestationsource, commit, builder, stepsRegistrystores all three under one tag
Picture 1: what travels with the image

2. What SBOM and provenance are

Step 1: SBOM in one line

Why: Software Bill of Materials.

What: A list of every package in the image: name, version, licence. Formats are SPDX and CycloneDX.

Example 1: Without an SBOM

Type this:

docker run --rm payapi sh -c 'ls /app/lib | head -3'

You will see:

jackson-core-2.17.1.jar
log4j-core-2.17.2.jar
slf4j-api-2.0.13.jar

What it means: You must look inside by hand.

Example 2: Quick SBOM with docker scout

Type this:

docker scout sbom --format list payapi:1.0 | head -4

You will see:

Name          Version   Type
log4j-core    2.17.2    maven
jackson-core  2.17.1    maven
openssl       3.0.13    deb

What it means: A readable package list.

Example 3: Search it

Type this:

docker scout sbom --format list payapi:1.0 | grep log4j

You will see:

log4j-core    2.17.2    maven

What it means: One command answers the boss.

Step 2: Provenance in one line

Why: Where did this image come from?

What: Provenance is a signed-style record in SLSA format: source repo, commit, builder, build arguments and timing.

Example 4: Build with it

Type this:

docker buildx build --provenance=mode=max -t registry.example.com/payapi:1.0 --push .

You will see:

=> exporting attestation manifest sha256:9f2a...

What it means: Provenance attached.

Example 5: Read it

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.0 --format '{{json .Provenance.SLSA.invocation.configSource}}'

You will see:

{"entryPoint":"Dockerfile"}

What it means: The Dockerfile used.

Example 6: Source commit

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.0 --format '{{json .Provenance.SLSA.metadata}}' | grep -o 'vcs:revision[^,]*'

You will see:

vcs:revision":"4e7b1c2

What it means: The commit is recorded.

Step 3: Why both

Why: SBOM answers what, provenance answers how.

What: Security teams and auditors, including banks under RBI rules, ask for both.

Example 7: What

Type this:

printf 'SBOM: what is inside\n'

You will see:

SBOM: what is inside

What it means: Packages and versions.

Example 8: How

Type this:

printf 'Provenance: how and where it was built\n'

You will see:

Provenance: how and where it was built

What it means: Commit, builder, args.

Example 9: Policy check

Type this:

docker scout policy registry.example.com/payapi:1.0 | grep -i 'supply chain'

You will see:

Supply chain attestations   compliant

What it means: Both present, policy passes.

3. Create attestations with buildx

Step 4: --sbom=true

Why: BuildKit scans the image and attaches an SPDX SBOM.

What: It needs a docker-container builder and --push or an OCI output.

Example 10: Builder

Type this:

docker buildx create --name att --driver docker-container --use --bootstrap | tail -1

You will see:

att

What it means: Builder ready.

Example 11: Build

Type this:

docker buildx build --sbom=true -t registry.example.com/payapi:1.1 --push . 2>&1 | grep -i sbom

You will see:

=> [linux/amd64] generating sbom using docker.io/docker/buildkit-syft-scanner:stable-1

What it means: Scanner ran inside the build.

Example 12: Read

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.1 --format '{{json .SBOM.SPDX.packages}}' | grep -o '"name":"log4j-core"'

You will see:

"name":"log4j-core"

What it means: The SBOM lists the jar.

Step 5: Scan build stages too

Why: Stages that are thrown away still matter.

What: Add ARG BUILDKIT_SBOM_SCAN_STAGE=true in a stage to include it, and BUILDKIT_SBOM_SCAN_CONTEXT=true for the context.

Example 13: Mark stage

Type this:

printf 'FROM maven:3.9-eclipse-temurin-21 AS build\nARG BUILDKIT_SBOM_SCAN_STAGE=true\nCOPY . .\nRUN mvn -q package\nFROM eclipse-temurin:21-jre-jammy\nCOPY --from=build /target/app.jar /app.jar\n' > Dockerfile && grep SBOM Dockerfile

You will see:

ARG BUILDKIT_SBOM_SCAN_STAGE=true

What it means: Build stage will be scanned.

Example 14: Build

Type this:

docker buildx build --sbom=true -t registry.example.com/payapi:1.2 --push . 2>&1 | grep -c 'generating sbom'

You will see:

2

What it means: Two SBOM passes.

Example 15: Maven appears

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.2 --format '{{json .SBOM}}' | grep -o 'maven-core' | head -1

You will see:

maven-core

What it means: Build tools are recorded.

Step 6: --provenance modes

Why: min is the default, max adds more detail.

What: min records basics; max adds build arguments and full step data. Do not pass secrets as args, max would record them.

Example 16: Default

Type this:

docker buildx build -t registry.example.com/web:1.0 --push . 2>&1 | grep attestation

You will see:

=> exporting attestation manifest

What it means: min provenance by default.

Example 17: Max

Type this:

docker buildx build --provenance=mode=max -t registry.example.com/web:1.1 --push . >/dev/null && docker buildx imagetools inspect registry.example.com/web:1.1 --format '{{json .Provenance.SLSA.invocation.parameters.args}}'

You will see:

{"build-arg:APP_ENV":"prod"}

What it means: Build args recorded.

Example 18: Turn off

Type this:

docker buildx build --provenance=false -t registry.example.com/web:dev --push . 2>&1 | grep -c attestation

You will see:

0

What it means: Sometimes needed for old registries.

Step 7: Attestation manifests

Why: How the registry stores them.

What: Attestations are stored in the image index as extra manifests with platform unknown/unknown.

Example 19: Raw index

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.1 --raw | grep -c 'attestation-manifest'

You will see:

1

What it means: One attestation manifest.

Example 20: Platforms

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.1 | grep Platform

You will see:

Platform:    linux/amd64
Platform:    unknown/unknown

What it means: unknown/unknown holds the attestations.

Example 21: Old tools

Type this:

docker pull registry.example.com/payapi:1.1 | tail -1

You will see:

registry.example.com/payapi:1.1

What it means: docker pull ignores attestations and just works.

4. Use the SBOM

New CVE announcedfor one libraryRead SBOM of every imagescript loops over tagsList images with that versionin minutesRebuild and redeploy those onlyfixed
Picture 2: from new bug to answer

Step 8: Export to a file

Why: Keep SBOMs for audits.

What: Write the SBOM with an output, or with docker scout or syft.

Example 22: Local output

Type this:

docker buildx build --sbom=true --output type=local,dest=out . && ls out | grep sbom

You will see:

sbom.spdx.json

What it means: SBOM saved as a file.

Example 23: Count packages

Type this:

jq '.packages | length' out/sbom.spdx.json

You will see:

187

What it means: 187 packages in this image.

Example 24: CycloneDX

Type this:

docker scout sbom --format cyclonedx --output payapi.cdx.json payapi:1.0 && head -c 40 payapi.cdx.json

You will see:

{"bomFormat":"CycloneDX","specVersion":

What it means: The other common format.

Step 9: Find a library across images

Why: The Log4Shell question.

What: Loop over images and grep the SBOM.

Example 25: Loop

Type this:

for i in payapi:1.0 web:1.0 partner:1.0; do docker scout sbom --format list $i | grep -q log4j-core && echo $i; done

You will see:

payapi:1.0

What it means: Only one image is affected.

Example 26: Version

Type this:

docker scout sbom --format list payapi:1.0 | grep log4j-core | awk '{print $2}'

You will see:

2.17.2

What it means: Is it a safe version?

Example 27: CVEs

Type this:

docker scout cves --only-package log4j-core payapi:1.0 | tail -2

You will see:

0C  0H  0M  0L
No vulnerable packages detected

What it means: Safe version confirmed.

Step 10: Scan for vulnerabilities

Why: SBOM plus a CVE database gives a risk list.

What: Docker Scout, Trivy and Grype can read an image or its SBOM.

Example 28: Scout

Type this:

docker scout cves payapi:1.0 | grep -E '^ +[0-9]+C'

You will see:

0C     2H     5M     9L

What it means: Counts by severity.

Example 29: Trivy

Type this:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:0.56.2 image --severity HIGH,CRITICAL -q payapi:1.0 | tail -1

You will see:

Total: 2 (HIGH: 2, CRITICAL: 0)

What it means: Same image, second tool.

Example 30: Gate in CI

Type this:

docker scout cves --exit-code --only-severity critical payapi:1.0; echo exit=$?

You will see:

exit=0

What it means: Pipeline fails only on critical.

Step 11: Sign the image

Why: Proof that your pipeline built it.

What: Cosign signs an image digest. Keys here are examples; keep real keys in a secrets manager.

Example 31: Keys

Type this:

cosign generate-key-pair

You will see:

Private key written to cosign.key
Public key written to cosign.pub

What it means: Example keys for practice.

Example 32: Sign

Type this:

cosign sign --key cosign.key registry.example.com/payapi@sha256:9f2a...

You will see:

Pushing signature to: registry.example.com/payapi

What it means: Signature stored next to the image.

Example 33: Verify

Type this:

cosign verify --key cosign.pub registry.example.com/payapi:1.1 | head -1

You will see:

Verification for registry.example.com/payapi:1.1 --

What it means: Servers can refuse unsigned images.

Step 12: Read provenance in an audit

Why: Answer who built what.

What: Look at the builder ID, the commit and the time.

Example 34: Builder

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.1 --format '{{json .Provenance.SLSA.builder}}'

You will see:

{"id":"https://ci.example.com/job/payapi/212"}

What it means: CI job 212.

Example 35: Time

Type this:

docker buildx imagetools inspect registry.example.com/payapi:1.1 --format '{{.Provenance.SLSA.metadata.buildFinishedOn}}'

You will see:

2026-10-24T09:12:44Z

What it means: Finished 2:42 PM IST.

Example 36: Mismatch alarm

Type this:

[ "$(git rev-parse --short HEAD)" = 4e7b1c2 ] && echo match || echo mismatch

You will see:

match

What it means: Image matches the code in the repo.

5. Common mistakes and how Ankit avoids them

Mistake one: building with the default docker driver and wondering where the SBOM went. Ankit uses a docker-container builder and --push.

Mistake two: passing tokens as build args with mode=max. They end up in provenance. Ankit uses --secret.

Mistake three: generating SBOMs but never reading them. Ankit has a weekly job that scans all SBOMs for new CVEs.

Mistake four: old registries that reject attestation manifests. Ankit tests the registry once and uses --provenance=false only where needed.

Mistake five: signing a tag instead of a digest. Ankit signs the digest so the signature cannot move.

Check yourself

Q1. What does an SBOM list?

Every package and version in the image.

Q2. What does provenance record?

Source, commit, builder and build steps.

Q3. Which flags add them?

--sbom=true and --provenance=mode=max.

Q4. Why sign the digest?

A tag can move; a digest cannot.

Friends, an image without an SBOM is a box without a label. Did you understand? Let us try it once more. Build one image with --sbom=true, export the SBOM and count its packages.

Ravindra Bagale's Tip

In interviews, when asked about supply chain security, say these four words in order: SBOM, provenance, scanning, signing. Then give one command for each.

Lab: try at home

  1. Create a docker-container builder.
  2. Build and push with --sbom=true.
  3. Add --provenance=mode=max and read the commit.
  4. Export the SBOM to a file and count packages.
  5. Search three images for one library.
  6. Sign an image digest with example cosign keys and verify.

Recap

  • SBOM is the list of contents.
  • Provenance is the build record.
  • buildx adds both with two flags.
  • Attestations live in the image index.
  • Scan SBOMs for CVEs on a schedule.
  • Sign digests and verify before deploy.

Ravi Sir's Cards for this lesson

मराठी cards