✍️ Signing, Attestation, and Verification — Legacy vs Current
Intro: The underlying problem stayed the same: prove what artifact was built, by whom, from what source, and whether policy should allow it to run. The ecosystem changed a lot. This page translates older signing guidance into a 2026-friendly model.
The problem this page solves
A modern supply-chain control stack should answer five questions:
- What artifact is this?
- Which source and pipeline produced it?
- Was it signed by an expected identity?
- Do we have useful metadata, such as SBOM or provenance?
- Is the consumer actually verifying anything, or only storing metadata?
Legacy versus current reality
| Topic | Older model | Practical current model |
|---|---|---|
| image signing | Docker Content Trust / Notary v1 | Cosign is the default open-source mental model for new builds; Notation is a valid OCI-oriented alternative |
| vulnerability evidence | scanner output only | signed SBOMs, attestations, and policy-aware verification |
| “trust” decision | trust the registry or repo tag | verify signature, identity, provenance, and policy at admission or deploy time |
| evidence handoff | CI logs and screenshots | machine-readable SBOM, attestations, and release evidence stored with the artifact |
Minimal modern pattern
For most teams, the practical minimum is:
- generate an SBOM;
- sign the image or artifact;
- optionally attest provenance or scan results;
- verify signatures where the artifact is pulled, promoted, or admitted.
Practical snippet — legacy DCT example you may still encounter
export DOCKER_CONTENT_TRUST=1
docker trust sign registry.example.com/team/app:1.2.3
docker pull registry.example.com/team/app:1.2.3
Keep this in the KB because older runbooks and older training still refer to it. Do not choose it as the default for new platform design.
Practical snippet — current Syft + Cosign flow
syft registry.example.com/team/app:1.2.3 -o spdx-json=sbom.spdx.json
cosign sign --yes registry.example.com/team/app:1.2.3
cosign attest --yes --predicate sbom.spdx.json --type spdx registry.example.com/team/app:1.2.3
This is a good “small but real” pattern for teams that want evidence without building a large platform first.
Practical snippet — keyless sign and verify
cosign sign registry.example.com/team/app:1.2.3
cosign verify registry.example.com/team/app:1.2.3
Use workload identity or OIDC-backed CI where possible so signatures can be tied to the build identity rather than to a long-lived shared key.
Practical snippet — verify an attestation
cosign verify-attestation registry.example.com/team/app:1.2.3
Use this when your deploy or admission control wants more than “the image is signed.”
Practical snippet — SBOM generation and vulnerability scan
syft dir:. -o cyclonedx-json=sbom-source.cdx.json
trivy sbom sbom-source.cdx.json
Or with Grype:
grype sbom:sbom-source.cdx.json --fail-on high
Practical snippet — GitHub Actions example
name: build-sign-attest
on:
push:
branches: [ main ]
jobs:
release:
permissions:
id-token: write
contents: read
packages: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t ghcr.io/org/app:${{ github.sha }} .
- name: Push image
run: docker push ghcr.io/org/app:${{ github.sha }}
- name: Generate SBOM
run: syft ghcr.io/org/app:${{ github.sha }} -o spdx-json=sbom.spdx.json
- name: Sign image
run: cosign sign --yes ghcr.io/org/app:${{ github.sha }}
- name: Attach SBOM attestation
run: cosign attest --yes --predicate sbom.spdx.json --type spdx ghcr.io/org/app:${{ github.sha }}
Practical snippet — admission-friendly verification gate
cosign verify \
--certificate-identity "https://github.com/org/repo/.github/workflows/release.yml@refs/heads/main" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
registry.example.com/team/app:1.2.3
This makes the policy more specific than “any valid signature”.
Practical snippet — Notation-style mental model
If your environment standardizes on OCI-native signature tooling through the Notary Project ecosystem, keep the model the same:
- sign artifact;
- push artifact and signature;
- verify by policy before promotion or deployment.
Use Notation when your registry and platform standardize there. Use Cosign when you want the most common open-source path with broad examples and OIDC-first workflows.
Recommended evidence bundle per release
Store or publish, per release:
- artifact digest;
- commit SHA;
- pipeline run URL or immutable run identifier;
- SBOM in SPDX or CycloneDX;
- vulnerability summary or policy result;
- signature verification result;
- provenance or attestation where available.
Common mistakes
- signing by tag instead of reasoning from immutable digests;
- generating SBOMs but never tying them to a release artifact;
- storing signatures but not verifying them in deployment paths;
- using one shared signing key for too many repos or teams;
- treating “artifact is signed” as equivalent to “artifact is safe”.
What to keep from older books
Older material is still valuable for:
- explaining why provenance matters;
- showing repository keys, offline roots, and freshness concepts;
- teaching that artifact trust is different from transport security;
- reminding teams that image sources must be curated.
What changed:
- long-lived signing keys are less appealing than OIDC-backed identity flows;
- SBOM and attestation workflows are much more common;
- verification must happen in consumers, not only in producers.
Related pages
- 🧪 SCA, SBOM, and Supply Chain Tooling — Legacy to Current
- 📦 Software Supply Chain Foundations
- 🛡️ Trusted Images, Harbor, and Signing
- Security Quality Gates and Release Blocking
---Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.