From 3aaab8624ff70760728e220ef60f13d9c0535310 Mon Sep 17 00:00:00 2001 From: FosterStack Admin <317177128+fosterstack-admin@users.noreply.github.com> Date: Sat, 10 Oct 2026 14:25:51 -0400 Subject: [PATCH 1/6] DRAFT-HOLD v0.3.0: verify-a-release (rule 78 shape) and the new-chain NIST/SLSA page, every claim TO-VERIFY; do not merge before v0.3.0 is live --- .../index.html | 173 +++-------------- verify-a-release/index.html | 182 ++++-------------- 2 files changed, 61 insertions(+), 294 deletions(-) diff --git a/how-our-pipeline-maps-to-nist-and-slsa/index.html b/how-our-pipeline-maps-to-nist-and-slsa/index.html index d01decc..61ef05e 100644 --- a/how-our-pipeline-maps-to-nist-and-slsa/index.html +++ b/how-our-pipeline-maps-to-nist-and-slsa/index.html @@ -1,12 +1,13 @@ + NIST SP 800-204C, 800-204D and SLSA: Our Release Pipeline - + - + @@ -87,156 +88,32 @@
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.2 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.2 at: Level 2, not Level 3.

-

This is guidance we followed when designing the pipeline. It is not a certification.

-

Words used here:

- - - -

The two NIST documents

- -

Parts of both documents cover running services in your own cluster, such as service mesh and GitOps. That is your environment, not 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.2 tag. What changed since v0.2.1 is listed after the table. "Signs" means the stage records what it did and signs it, with a short-lived key and no stored signing key. The signature is tied to that stage's own workflow and logged in a public transparency log.

-
- - - +

How the v0.3.0 release pipeline maps to NIST and SLSA

+

This page puts each stage of the new release pipeline next to the NIST practice it was designed against. It says where a stage only partly implements a practice.

+

DRAFT for v0.3.0, not published and never merged before v0.3.0 is live. [TO-VERIFY] marks anything not yet run against a real release.

+

This is guidance we followed when designing the pipeline. It is not a certification.

+

Stage by stage

+

"Signs" means the stage records what it did and signs it with a short-lived key, under its own workflow identity, logged in a public transparency log. [TO-VERIFY] against the workflow files at the v0.3.0 tag.

+
StageWhat it does in v0.2.2NIST practiceHow much
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + -
StageWhat it doesNIST practiceHow much
Source admissionThe tag must be annotated, signed and strictly named: signed by the owner's key or, for an automatic patch tag only, by the release workflow's own keyless identity. The commit must be signed (by the owner's key, or GitHub's own key for merges made on github.com) and be on main. Every required check must pass on that exact commit or, for the checks that run only on pull requests, on the pull request that produced it. An owner-approved requirements list must exist for the version. The lists of allowed signers and required checks are read from main, not from the tagged commit. 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.
BuildBuilds 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 assemblyChecks 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, using a BuildKit image that is also pinned by digest. 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"Matches the practice as we read it.
Reproducibility checkAssembles 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.
ScansTwo scanners with different vulnerability databases run, each on its own machine. They first check the image-assembly and reproducibility statements, then scan every platform image of every variant. One also scans the archives, the other the Go module files. Any finding blocks the release, even the lowest-rated one. 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 testsRun 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)Matches the practice as we read it. The individual test jobs do not sign their own results.
Release authorizationVerifies 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. It also stops the release if a VEX statement says a flaw affects us and no owner acceptance of that risk is recorded. 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 publishWill 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. Publishes the VEX statements in three forms: OpenVEX, scanner suppression rules and CSAF 2.0. 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. Promotion only copies the digests named in the signed approval. Enforcing that at deploy time is up to your own environment.
Signing, across all stagesKeyless 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 bundlerelease-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)Matches the practice as we read it. Neither document has a section on VEX.
Source admission[TO-VERIFY] whether unchanged from v0.2.2: signed tag, signed commit on main, required checks passed.[TO-VERIFY] 800-204D 5.1.4 and 5.1.2[TO-VERIFY]
Build[TO-VERIFY] Builds the binaries and the signed packages once. The image is assembled from those packages, with no base image.[TO-VERIFY] 800-204D 5.1.1[TO-VERIFY]
Sign[TO-VERIFY] A separate stage records the build and signs it under its own identity, from the build's digest list only.[TO-VERIFY] the part of 5.1.1 that asks for signing outside the build steps[TO-VERIFY]
Rebuild[TO-VERIFY] Builds the release again, independently. The digests must match or the release fails.[TO-VERIFY] none found in either document[TO-VERIFY]
Check[TO-VERIFY] Scans and acceptance tests run against the exact candidate images, and the stage signs a verdict for those digests.[TO-VERIFY] 800-204C 4.8 and 800-204D 5.2[TO-VERIFY]
Release[TO-VERIFY] Verifies every stage's signature together, then publishes the same digests.[TO-VERIFY][TO-VERIFY]
- -

What changed from v0.2.1 to v0.2.2

-

The v0.2.2 tag changed 31 workflow files. The build stage and the scan stage did not change. These did:

- - -

Which SLSA Build level do we assess v0.2.2 at?

-

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

- -

Level 3 is not claimed. It asks the build platform to "prevent runs from influencing one another, even within the same project" and to "prevent secret material used to sign the provenance from being accessible to the user-defined build steps". We have not shown either. In v0.2.2 the build job can ask for a signing identity for the whole job, and it also runs this repository's build configuration and compiles its code: the goreleaser hooks and the Go build. The image job can ask for a signing identity too, and it builds this repository's Dockerfiles. So the build steps could reach the signing, and Level 3 needs that kept apart. The build job also restored a GitHub Actions cache written by earlier runs, and we have not shown that other workflows or branches cannot write to it. The spec calls that "cache poisoning" under its "Isolated" requirement. Build Level 3 is not claimed for v0.2.2.

- -

What we do not meet

+ +

Our wording: signed at every stage, verified together at release.

+

SLSA

+

[TO-VERIFY] The SLSA Build level we assess v0.3.0 at. We claim Level 3 for the Build stage only after a test shows that a malicious build step cannot produce provenance the release step accepts. Until that test has passed, this page says nothing about Level 3.

+

What this page does not say

- -

Check it yourself

-

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

-
$ gh attestation verify oci://ghcr.io/fosterstack/cache:0.2.2 \
-  --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. This is guidance we followed when designing the pipeline. It is not a certification.

- -
- Verify a release - How we build -
+

Related: verify a release yourself and how releases are built and signed.