Infrastructure worth keeping — and kept patched.

How our release pipeline maps to NIST SP 800-204C, 800-204D and SLSA

This page takes the release pipeline that built FosterStack Cache v0.2.1 and puts each stage next to the NIST practice it maps to. It says where a stage only partly implements a practice, and it says which SLSA Build level we assess v0.2.1 at.

Words used here: SBOM is a parts list of what is inside a build. VEX is a note saying a known flaw does not affect us. Provenance is a signed record of how and where something was built. Digest is the fingerprint of a file or image. SLSA is a public scale of how well a build can be trusted, from Level 1 to Level 3 in its Build track.

Guidance we designed against, not a certification we hold.

The two NIST documents

Parts of both documents are about running services in your own cluster: service mesh, runtime monitoring, deployment by GitOps. That part happens in your environment, not in our release pipeline, so this page does not map it.

Stage by stage: what runs, and which practice it maps to

This describes the workflow files as they were at the v0.2.1 tag. "Signs" means the stage writes a statement about its work and signs it with keyless signing tied to that stage's own workflow identity, logged in a public transparency log.

StageWhat it does in v0.2.1NIST practiceHow much
Source admission Checks the tag and commit signatures against the allowed signers on main (or GitHub's own key for merges made on github.com), that the commit is on main, that every required check passed, and that an approved requirements list exists for the version. Signs. 800-204D 5.1.4 "Secure Code Commits" (commit-signing enforcement, COMMIT-REQ-2); 5.1.2 "Secure Pull-Push Operations on Repositories" (automated checks before code is trusted) Partly. There is one maintainer, so no second person reviews or approves a change.
Build Builds the binaries once on a fresh GitHub-hosted machine with the toolchain pinned, and checks that the dependency files did not change. Writes checksums and an SBOM per archive. Signs a build statement and SLSA provenance. 800-204D 5.1.1 "Secure Build"; 800-204C 3.3.3 (SBOM generation and code signing as pipeline tasks) Partly. The signing runs in the same job as the build steps, not in a separate, more trusted process as 5.1.1 asks.
Image assembly Checks every archive against the signed build statement before opening it. Adds one binary to a base image pinned by digest, with no commands run inside the image. Pushes by digest only, with no version tags, to a separate candidates package. Signs, recording the base digest and binary hashes, plus SLSA provenance. 800-204D 4.2: "The inputs and outputs of each build step should be verified" Implements the practice.
Reproducibility check Assembles the images again on a separate machine. The digests must match, or the release fails. Signs. No direct match in either document. Not mapped. It repeats the image assembly; it does not rebuild the binaries from source.
Scans Two different scanners with different vulnerability databases, each on its own machine, check the image-assembly and reproducibility statements first, then scan every platform image of every variant. One also scans the archives, the other the Go module files. A finding at any severity blocks the release. For one of the two scanners, a published VEX statement can clear a finding. Each scanner signs its verdict for the exact digests. 800-204C 4.8 and 4.8.1 (container image scans, software composition analysis); 800-204D 5.2, DEPLOY_REQ-4 (evidence the image was scanned) Partly. The release pipeline runs no static or dynamic application security testing itself. The signed verdict records a pass, not the full scan report.
Acceptance tests Run against the exact candidate images: the Linux archives and binaries (macOS archives are checked, not run), the images on both CPU architectures, the image variants, the Gradle and Maven test suites, the Kubernetes setup from our docs, and a test that the server makes no outbound connections. A final job checks that every release-blocking acceptance test in the approved list passed, then signs one statement. 800-204C 3.3.1 (tests run in the pipeline; an organisation may choose to stop the pipeline when a test fails); 4.6 (stop further pipeline tasks if a test fails) Implements the practice. The individual test jobs do not sign their own results.
Release authorization Verifies every earlier statement: signed by the expected stage, naming this commit and these digests, scan verdicts pass, acceptance results complete. Anything missing stops the release. Records each statement's transparency-log entry. Signs the approval. 800-204C 4.6: "verify that all required signatures … are present to ensure that no one bypasses the pipeline"; 800-204D 5.1.1 (policy checks that the required attestations are found) Partly. The policy is code in the workflow file, not a separate signed policy document as 5.1.1 describes.
Promotion and publish Will not start without the signed approval. Copies the approved digests to GitHub's registry and the Docker Hub mirror with no rebuild, and checks the digests did not change. Signs the public images and the checksums file. Uploads the release files, re-checks the image signatures, the signed checksums and every tag the way a customer would, without credentials, then makes the release page public. 800-204D 5.2, DEPLOY-REQ-3 (only an artifact made by the approved build process is cleared) Partly. We refuse to publish anything the approved build did not make. Enforcing that at deploy time is up to your own environment.
Signing, across all stages Keyless signing: a short-lived signing identity per stage, no stored signing key, every signature logged publicly. 800-204C 4.6: "signing the release artifact during each required CI/CD stage (preferably multi-party signing)"; 800-204D 5.1.1 (attestations signed, stored tamper-proof) Partly. Not multi-party: every signature is made by automation in one repository, run by one maintainer.
Evidence bundle release-manifest.json lists every digest, the hash of the approved requirements list, per-test results, and the transparency-log entry of every statement the authorization verified. It is attached to each image in GitHub's registry as a signed statement and published with the SBOMs, VEX file and signed checksums. 800-204D 4 (record provenance, with a way to verify and authenticate it) Implements the practice. Neither document has a section on VEX.

Which SLSA Build level does v0.2.1 meet?

We assess v0.2.1 at SLSA Build Level 2, against the SLSA v1.0 requirements. We do not claim Build Level 3.

Level 3 is not claimed. It requires that the build steps cannot reach the material used to sign the provenance ("Unforgeable" and "Isolated" in the spec). In v0.2.1, the build steps and the provenance signing run in the same job, so that separation is not there. Build Level 3 is planned. It is not part of v0.2.1.

What is not met today

Check it yourself

This checks the SLSA provenance of the v0.2.1 image and the workflow that signed it:

$ gh attestation verify oci://ghcr.io/fosterstack/cache:0.2.1 \
  --repo fosterstack/cache \
  --signer-workflow fosterstack/cache/.github/workflows/stage-image.yml

Section numbers refer to the final published versions of NIST SP 800-204C and NIST SP 800-204D. Guidance we designed against, not a certification we hold.

Verify a release How we build