Skip to content

ci(release): attest global artifacts (SBOMs, installer, source) + doc release verification - #329

Merged
jensholdgaard merged 5 commits into
mainfrom
sign-attest-global-artifacts-and-docs
Jul 2, 2026
Merged

ci(release): attest global artifacts (SBOMs, installer, source) + doc release verification#329
jensholdgaard merged 5 commits into
mainfrom
sign-attest-global-artifacts-and-docs

Conversation

@jensholdgaard

@jensholdgaard jensholdgaard commented Jul 2, 2026

Copy link
Copy Markdown
Owner

What

Two gaps from the build-signing review (the substance — image cosign + release
attestations — is already in place; these close the coverage/UX holes).

1. Attest the global release artifacts

build-local-artifacts attests the per-target binaries via
target/distrib/*<target-triple>*, so the assets produced in
build-global-artifacts — the CycloneDX SBOMs (ourios-*.cdx.xml), the
installer, source.tar.gz, sha256.sum — shipped unsigned. Confirmed on
v0.1.0: gh attestation verify ourios-server.cdx.xml → exit 1, tarball → exit 0.

Fix: attest them in build-global-artifacts, where they exist — add the
attestations: write / id-token: write permissions (matching the local job)
and an actions/attest step over the job's produced files (upload_files +
*.cdx.xml). Same SLSA build-provenance predicate (https://slsa.dev/provenance/v1,
buildType actions.github.io/buildtypes/workflow/v1) the local step emits.

2. Document how to verify

SECURITY.md gains a Verifying releases section with exact, tested commands:

  • keyless cosign verify for the image (identity regex pinned to the tag-built
    image.yml; note the image tag drops the leading vv0.1.0:0.1.0);
  • gh attestation verify --repo for release assets.

Both commands were run against the live v0.1.0 image and artifacts and pass.

Verification

  • release.yml parses as valid YAML; the added step/permissions introduce no
    shellcheck findings (the pre-existing SC2086/SC2129 notes are in
    dist-generated steps, untouched).
  • cosign verify … and gh attestation verify … from the new docs both pass
    against v0.1.0.

Scope / follow-up

Full artifact coverage takes effect from the next tagged release (v0.1.x);
v0.1.0's non-binary assets predate this and can't be retro-signed. The OpenSSF
Scorecard Signed-Releases
check (currently 0) is not fixed by this — it
scans release assets for signature/provenance files (*.intoto.jsonl,
.sig), which is a different mechanism from the attestation store this
populates. That fix (upload *.intoto.jsonl on the release and corpus
workflows) is the next PR.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Release artifacts now include SLSA provenance attestations for global, non–per-target downloads (such as SBOMs and installers), extending build-verification beyond previously covered binaries.
  • Documentation

    • Added a “Verifying releases” section with step-by-step guidance to validate release authenticity.
    • Covers both online and offline verification flows, including how to verify container image signatures and release-asset provenance attestations.

…sums) + doc verification

Gap 1 — the release only attested the per-target binaries. build-local-artifacts
globs `target/distrib/*<target-triple>*`, so the CycloneDX SBOMs
(`ourios-*.cdx.xml`), the installer, `source.tar.gz`, and `sha256.sum` — produced
in build-global-artifacts — shipped **unsigned** (`gh attestation verify
ourios-server.cdx.xml` → exit 1, while the tarball → exit 0).

Attest them in build-global-artifacts, where they exist: add the
`attestations`/`id-token` permissions (matching build-local) and an `actions/attest`
step over the job's produced files (`upload_files` + the `*.cdx.xml` SBOMs). Same
SLSA build-provenance predicate (`https://slsa.dev/provenance/v1`) the local step
emits — verified against the v0.1.0 tarball attestation.

Gap 2 — no user-facing "how to verify". Add a "Verifying releases" section to
SECURITY.md with the exact, tested commands: keyless `cosign verify` for the
container image (identity pinned to the tag-built image workflow; note the image
tag drops the leading `v`) and `gh attestation verify --repo` for release assets.
Both commands were run against the live v0.1.0 image / artifacts and pass.

Note: full coverage lands from the next tagged release (v0.1.x); v0.1.0's
non-binary assets predate this. The Scorecard Signed-Releases fix (uploading
`*.intoto.jsonl` provenance as release assets, which is what Scorecard scans for
— distinct from the attestation store this populates) is a separate follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jensholdgaard, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c032ae02-0b82-4558-8169-a158204b0f1b

📥 Commits

Reviewing files that changed from the base of the PR and between c940a69 and be955ac.

📒 Files selected for processing (1)
  • SECURITY.md
📝 Walkthrough

Walkthrough

This PR adds provenance attestation for global release artifacts in the release workflow and adds SECURITY.md guidance for verifying release assets and container images.

Changes

Global Artifact Attestation and Documentation

Layer / File(s) Summary
Attest global artifacts in release workflow
.github/workflows/release.yml
The build-global-artifacts job gains id-token: write permission and a new Attest global artifacts step that runs actions/attest against SBOMs, installer, source tarball, and checksums using subject paths from prior cargo-dist and cargo-cyclonedx steps.
Document release verification steps
SECURITY.md
A new Verifying releases section explains how to verify container image signatures with cosign and release artifacts with gh attestation verify, including repo-bounded signer identity and offline verification notes.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • jensholdgaard/ourios#262: Introduced the original build-provenance attestation wiring via actions/attest for per-target artifacts, which this PR extends to global artifacts.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: global artifact attestations and release verification docs.
Description check ✅ Passed The description covers summary, verification, and rollout context, but omits the template's Related and Checklist sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sign-attest-global-artifacts-and-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Closes remaining gaps in the release signing/verification story by extending SLSA provenance attestations to platform-agnostic release assets and documenting end-user verification steps in SECURITY.md.

Changes:

  • Add actions/attest to build-global-artifacts so SBOMs and other global artifacts produced there also receive build provenance attestations.
  • Add a “Verifying releases” section to SECURITY.md with commands for verifying the container image (cosign) and release assets (GitHub attestations).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
SECURITY.md Documents verification commands for the container image and release assets.
.github/workflows/release.yml Attests global artifacts (SBOMs + dist-produced global assets) via actions/attest with matching permissions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread SECURITY.md Outdated
Comment thread SECURITY.md Outdated
Comment thread SECURITY.md Outdated
…wnload pattern

Address Copilot's review of #329:

- Don't over-claim: the opening now names the two mechanisms (cosign image
  signature, SLSA build-provenance on assets) instead of a blanket "every
  release artifact is signed" that reads as covering historical releases.
- State the coverage boundary explicitly: binary archives attested from v0.1.0
  on; non-binary assets (SBOMs, installer, source, checksums) from the release
  after v0.1.0 on.
- Make the example copy/paste-safe: the `gh release download --pattern` now
  matches the exact filename the verify command checks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread SECURITY.md Outdated
Comment thread SECURITY.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread SECURITY.md Outdated
…lanket claim

Address Copilot's re-review of #329:

- The cosign example used an identity regexp matching any v* tag; pin
  `--certificate-identity` to the exact release tag being verified (with a note
  to substitute both version occurrences for other releases). Verified against
  the live v0.1.0 image.
- The release-artifacts paragraph still opened with a blanket "all carry"
  enumeration that contradicted the version scope stated below; it now defers
  to that scope.
- The rewrite also puts the "[SLSA build provenance]" reference link on one
  line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread SECURITY.md Outdated
Copilot follow-up on #329: `gh release download` resolves the repository from
the working directory, so the example failed outside a clone — exactly where an
end-user verifying a release runs it. Pass --repo explicitly, matching the
verify command.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/release.yml
@jensholdgaard
jensholdgaard merged commit cedef37 into main Jul 2, 2026
21 checks passed
@jensholdgaard
jensholdgaard deleted the sign-attest-global-artifacts-and-docs branch July 2, 2026 16:32
jensholdgaard added a commit that referenced this pull request Jul 2, 2026
…ard Signed-Releases) (#332)

OpenSSF Scorecard's Signed-Releases check scores 0: it scans release *assets*
for signature/provenance files (*.intoto.jsonl, *.sig, …) and never queries the
GitHub attestation store, so our releases — genuinely attested since #329 —
still read as unsigned, and the unsigned corpus/* releases drag the 5-release
window regardless.

Ship the existing attestations as assets too:

- release.yml: give both attest steps an id and stage each step's bundle-path
  output — Sigstore-bundle JSON Lines carrying the DSSE-wrapped SLSA-provenance
  statements — into target/distrib as
  `ourios-server-<target>.intoto.jsonl` / `ourios-global-artifacts.intoto.jsonl`,
  added to the uploaded artifact set; the host job's `gh release create
  artifacts/*` attaches them to the release. Staging runs after attest, so the
  bundle cannot self-attest (the local attest glob would otherwise match it).

- capture-otel-demo-corpus.yml: the publish job (gains attestations/id-token
  write) now attests the exact assets it releases (logs.jsonl.gz + manifest.md;
  gzip split into its own step so the .gz exists at attest time) and attaches
  `otel-demo-corpus.intoto.jsonl` on both the create and re-mint paths — corpus
  releases are signed in place from their next mint on.

- SECURITY.md: document the bundle assets + fully-offline verification
  (`gh attestation verify … --bundle <file>.intoto.jsonl`).

The attestation-store copy stays (online `gh attestation verify`); the asset is
the offline/scanner-visible form. Validation caveat: the check can only flip on
real releases — the next v0.1.x tag and the next corpus re-mint — followed by
Scorecard's next scan; a branch run cannot prove it.

Verified: both workflows parse; actionlint reports no new findings (baseline
SC2086/SC2129 notes in dist-generated steps only, line-shifted).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants