Supply Chain Security — Signing, SBOMs & OIDC Federation
OIDC federation, Sigstore/cosign, SBOMs, admit-time policy, and CI permissions hygiene for supply-chain defense.
- 1Gist
- 2Maps
- 3Q&A
- 4Sandbox
Voice readout needs Web Speech Synthesis in this browser.
A deploy job needs to push to the registry and assume a cloud role
Prefer
OIDC, short-lived credentials
The job requests an ID token. The cloud role trusts the issuer and a subject pinned to this repo, this ref, and the production environment.
- Nothing long-lived sits in repository secrets for that role.
- A fork pull request does not match the subject.
- Rotation is the token lifetime.
Alternative
A static cloud key in Actions secrets
AWS_SECRET_ACCESS_KEY lives in the repo settings. Any job that can print the environment can take it.
- Forks, logs, and poisoned workflow steps all become exfiltration paths.
- Rotation is a ticket nobody files.
- You cannot tell which ref minted the credential.
Fail closed before the process starts
Build-time signing without an admit check is theater. The deploy path repeats the checks.
- 1
Digest only
Reject a tag, including latest. The reference is sha256. - 2
Signature and identity
The signature verifies, and the signer is an allowlisted repo and workflow. - 3
Provenance
If provenance is required, the builder identity matches the expected workflow. - 4
SBOM policy
Severity policy passes, or an exception with an expiry is on file. - 5
OIDC environment
The deploy role was assumed with the production environment claim.
Overview
If an attacker can run code in CI, or publish a tampered artifact the cluster will pull, application-level controls never get a vote. Supply-chain security means you authenticate the builder (OIDC), inventory the contents (SBOM), prove integrity (signatures and in-toto), and verify again at admit or deploy time.
The artifacts page defines the digest and the provenance statement. This page is the control that refuses to run anything else. End-user login, authorization codes, and token audiences are a different cluster. The OIDC here is the CI platform acting as an identity provider for a cloud role.
Threats you are buying down
| Threat | Example | Control |
|---|---|---|
| Stolen long-lived cloud keys | A key in GitHub secrets is exfiltrated | OIDC federation, minutes-long credentials |
| Poisoned dependency | Typosquat or a compromised maintainer | Lockfiles, vetting, SCA, provenance |
| Tampered image at rest | Registry write or a mirror swap | Sign, then verify the digest at admission |
| Rogue fork workflow | pull_request_target with a privileged token | Least privilege, trustworthy triggers |
| Build-system compromise | A malicious runner | Hardened builders, SLSA provenance |
Flow
- 1
1. Developer opens a PR
- next2. Limit PR job permissions
- 2
2. Limit PR job permissions
- next3. Main CI mints an OIDC token
- 3
3. Main CI mints an OIDC token
- next4. Cloud role is short-lived
- 4
4. Cloud role is short-lived
- next5. Publish the artifact digest
- 5
5. Publish the artifact digest
- next6. Sign and attach the SBOM
- 6
6. Sign and attach the SBOM
- next7. Admit checks, then run
- 7
7. Admit checks, then run
Lesson map
Supply Chain Security — Signing, SBOMs & OIDC Federation
OIDC federation, Sigstore/cosign, SBOMs, admit-time policy, and CI permissions hygiene for supply-chain defense.
Architecture. Architecture
Select a node to see why it exists, or an edge to see the protocol, direction, effect, and consequence.
Mermaid export
flowchart TB a["1. Developer opens a PR"] b["2. Limit PR job permissions"] c["3. Main CI mints an OIDC token"] d["4. Cloud role is short-lived"] a -->|1. Developer opens a PR| b b -->|2. Limit PR job permissions| c c -->|3. Main CI mints an OIDC token| d
OIDC federation
The CI platform issues a JWT: issuer, subject, audience, repository, ref, environment. The cloud identity provider allows AssumeRole or workload identity only when those claims match.
Compared with a static secret, there is no long-lived key to leak from a log or a fork. Deploy rights bind to ref:refs/heads/main or to the production environment. The token expires in minutes.
The failure mode is a trust policy with a wildcard subject. Anyone who can obtain a token from that issuer becomes your role. Claim names differ by provider. Test the negative cases: wrong repo, wrong ref, fork, missing environment. Some tools still want a personal access token. Isolate those jobs. They do not share the production role.
A leaked deploy token is revoked immediately. Audit what it published. Move the role to OIDC. If you cannot prove integrity for artifacts published in the window, treat them as untrusted and rebuild from a known commit.
Signing and SBOMs
cosign / Sigstore signs with an ephemeral Fulcio certificate and a Rekor transparency log (keyless), or with a key in KMS (keyful). Verify in the deploy job or in an admission controller. Policy can require the repository and the workflow identity, not merely "some signature exists."
in-toto and SLSA provenance say how the artifact was built. That is a stronger claim than a bare signature. SLSA is a technical assurance model for provenance. A SOC 2 report is an organizational control report. Related goals, different artifacts. Do not swap the names in an interview.
An SBOM is CycloneDX or SPDX generated at build time and stored next to the digest. An SCA scan is vulnerability analysis against that inventory (and sometimes against source). You want generation plus continuous scanning of the digests that are still deployed. An SBOM that never gets re-scanned ages out of date. Critical CVEs block, with a documented exception that expires. The gate shape is on the anatomy page. The inventory is here.
| Approach | Ops burden | Fit |
|---|---|---|
| Cosign keyless (Sigstore) | Low | Open source and many internal registries |
| Cosign with a KMS or HSM key | Medium | Regulated or private Sigstore |
| Traditional GPG on jars | High | Legacy Maven shops |
Keyless signing skips key distribution and leaves a transparency log. It depends on public Sigstore, or on a private Sigstore you run. Shops that mandate an HSM use KMS-backed cosign. Either way, verify on the deploy path.
Everything that can reach production is signed. Scratch images that the registry policy cannot deploy may stay unsigned. A signature that is checked only in the build job does not stop a swapped digest later.
Permissions hygiene
| Setting | Prefer |
|---|---|
permissions | Least privilege per job. id-token: write only on publish and deploy |
pull_request_target | Avoid it when the job checks out or builds untrusted code |
| Fork pull requests | No secrets. No OIDC to production |
| Environment secrets | Production only, with required reviewers |
| Third-party actions | Pin by commit SHA |
Poisoned pipeline execution (PPE) is an attacker changing CI config, or feeding untrusted pull-request content, so the pipeline runs malicious steps with privileged secrets. Mitigate with builds of a trusted ref, least privilege, and a rule that privileged workflows do not check out untrusted code.
npm provenance proves a package version was published from a specific public CI workflow and source. It does not prove the code is safe. You still review and scan.
Policy at admit time
Verification should be mechanical. The engine (Kyverno, Gatekeeper, a cloud deploy policy) matters less than failing closed.
- The image reference is a digest. Reject
:latest. - The signature verifies against an allowlisted identity (repository plus workflow).
- Provenance, when required, matches the expected builder.
- The SBOM scan meets the severity policy, or an approved exception has an expiry.
- The deploy role was assumed with OIDC and the environment claim
production.
Helpers you can run
Press Run. Snippets must be self-contained — no network, files, or native modules.
Press Run. Snippets must be self-contained — no network, files, or native modules.
Interview Q&A
How does OIDC remove AWS keys from GitHub Actions?
Answer
The job requests an id-token. The IAM role trust policy validates GitHub's issuer and the subject. STS returns temporary credentials. That role does not store AWS_ACCESS_KEY_ID in the repository.
Does signing at build matter more than verifying at deploy?
Answer
You need both. An unsigned build is incomplete. Verify-at-deploy is what stops a swapped digest. Build-only signing without admission is theater.
SBOM versus an SCA scan?
Answer
The SBOM is the inventory. SCA is the vulnerability analysis of that inventory, sometimes also of the source tree. Generate the SBOM at build, and keep scanning the digests that are deployed.
What is poisoned pipeline execution?
Answer
The attacker changes CI config or supplies untrusted pull-request content so privileged steps run their code. Build from a trusted ref, keep permissions minimal, and do not check out untrusted code inside a privileged workflow.
SLSA versus a SOC 2 checkbox?
Answer
SLSA is a technical model for artifact provenance. SOC 2 is an organizational control report. Do not treat one as the other.
Should every image be signed?
Answer
Every image that can reach production, yes. A scratch CI image may stay unsigned when registry policy makes it undeployable.
What does npm provenance prove?
Answer
That the version was published from a specific public CI workflow and source. It does not prove the code is safe. Review and SCA remain.
How do you rotate after a leaked deploy PAT?
Answer
Revoke it, audit deploy logs, move the role to OIDC, and treat artifacts published in the window as untrusted if you cannot prove integrity.
What does a wildcard subject on the trust policy do?
Answer
It lets any token from that issuer assume the role. Pin repository, ref, and environment. Test a fork and a feature branch. Both must fail.
Pitfalls
id-token: writeon every job, including the untrusted pull-request workflow.- A trust policy subject of
*. - Signing the build and never checking the signature at admission.
- An SBOM generated once and never scanned again.
pull_request_targetthat checks out the fork and still has production secrets.- Calling this flow "the OAuth login" and explaining authorization-code PKCE.
For a service you ship, list the five checks that run before the new digest is eligible: reference shape, signer identity, provenance, severity policy, and which OIDC environment may assume the deploy role. Mark the one you would fail closed on tonight if it were missing.