docs(security): fix release-verification instructions that cannot work - #755
Merged
Conversation
SECURITY.md and CONTRIBUTING.md describe a release pipeline this project no longer has. Every parameter is wrong, so an operator following them verifies nothing: - they pass --certificate checksums.txt.pem --signature checksums.txt.sig; releases ship a bundle, checksums.txt.sigstore.json, and neither .pem nor .sig exists; - they name the signer as netresearch/ofelia/.github/workflows/release-slsa.yml, a workflow that does not exist — releases are signed by the reusable netresearch/.github/.github/workflows/release-go-app.yml, so the identity never matches; - they call slsa-verifier against ofelia-linux-amd64.intoto.jsonl; v0.28.0 ships zero .intoto.jsonl assets; - the container command omits --certificate-identity-regexp and --certificate-oidc-issuer, which keyless cosign requires. Replace them with the procedure the pipeline actually produces, including the --signer-workflow flag that provenance verification needs because the signing identity is the reusable workflow rather than this repository. Every command in the new text was executed against the published v0.28.0 assets before committing: both cosign verify-blob invocations report "Verified OK", sha256sum -c passes, and gh attestation verify exits 0. Signature verification is the only control an operator has before granting this daemon access to the Docker socket. Instructions that fail teach people to skip the step. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
|
There was a problem hiding this comment.
Automated approval for maintainer PR
All automated quality gates passed. See SECURITY_CONTROLS.md for compensating controls.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #755 +/- ##
==========================================
- Coverage 87.65% 87.63% -0.02%
==========================================
Files 90 90
Lines 12058 12058
==========================================
- Hits 10569 10567 -2
- Misses 1198 1199 +1
- Partials 291 292 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
CybotTM
added a commit
to netresearch/.github
that referenced
this pull request
Jul 28, 2026
…uld (#315) `SECURITY.md` tells users how to check a release: verify each signature with cosign, check the checksums, confirm build provenance. Nothing executed those instructions, so they were free to rot — and they had. Every documented command in ofelia was wrong until [netresearch/ofelia#755](netresearch/ofelia#755): wrong file extensions, a signer workflow that does not exist, a verifier pointed at assets no release ships. They looked fine to anyone who did not run them. This workflow runs them, against the published assets, with the same commands and identity constraints the documentation hands out. ## The accounting is arithmetic, not pattern-based ``` total = payloads + bundles every payload has <payload>.sigstore.json, and every bundle has its payload the checksum manifest lists exactly the payloads minus itself ``` A name-pattern *exemption* — "skip files matching X" — is what lets an asset slip through: a new artifact kind appears, matches no rule, and is silently never verified. Classifying by suffix is fine as long as the counts must close, because then an unclassified file breaks the sum instead of being ignored. The signature and provenance steps additionally require at least one artifact each, so an empty release cannot pass by verifying nothing. ## Verified against a real release, not a fixture Run against the published [ofelia v0.28.0](https://github.com/netresearch/ofelia/releases/tag/v0.28.0): | Check | Result | |---|---| | Accounting | 34 assets = 17 payloads + 17 bundles, no orphans | | `cosign verify-blob` | `Verified OK` for `ofelia-linux-amd64` and `checksums.txt` | | `sha256sum -c` | clean, without `--ignore-missing` | | `gh attestation verify` | exit 0 against the default signer workflow | | Provenance classification | exactly the 8 binaries, no SBOMs or bundles | And five injected faults, each failing with its own specific finding: | Fault | Finding | |---|---| | removed a binary's signature bundle | `no signature bundle for asset 'ofelia-linux-amd64'` | | removed an asset, kept its bundle | `signature bundle '...' has no matching asset` | | added an unsigned asset | `no signature bundle for asset 'ofelia-linux-riscv64'` | | deleted an entry from `checksums.txt` | manifest does not list exactly the shipped payloads | | added a phantom entry to `checksums.txt` | manifest does not list exactly the shipped payloads | ## Notes The defaults match how `release-go-app.yml` publishes today (`.sigstore.json` bundles, `checksums.txt`, `.spdx.json` SBOMs); every one of them is an input, so a repo that ships differently can adjust without forking the workflow. `container-image` is optional and skipped when empty. Caller wiring for ofelia follows separately.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



SECURITY.mdandCONTRIBUTING.mddescribe a release pipeline this project no longer has. Every parameter is wrong, so an operator following the documented procedure verifies nothing — and signature verification is the only control they have before handing this daemon the Docker socket.What is broken
--certificate checksums.txt.pem --signature checksums.txt.sigchecksums.txt.sigstore.json. Neither.pemnor.sigexists.netresearch/ofelia/.github/workflows/release-slsa.ymlnetresearch/.github/.github/workflows/release-go-app.yml, so the identity never matches.slsa-verifier ... --provenance-path ofelia-linux-amd64.intoto.jsonl.intoto.jsonlassets.cosign verify ghcr.io/netresearch/ofelia:<TAG>--certificate-identity-regexpand--certificate-oidc-issuer; without them it fails.Asset inventory of v0.28.0, for reference:
What this replaces it with
The procedure the pipeline actually produces, including the
--signer-workflowflag that provenance verification needs because the signing identity is the reusable workflow rather than this repository — the single detail most likely to make a correct-looking command fail.Verified by execution, not by reading
Every command in the new text was run against the published v0.28.0 assets before committing, with cosign v2.6.3:
Follow-up worth considering
Nothing in CI verifies a release after it is published, which is why this drift went unnoticed across several releases. A job triggered
on: release: [published]that runs exactly these commands against the uploaded assets would turn this class of drift into a build failure instead of a silent one. Raised separately rather than bundled here.