From 076110a2fbf42e52123b7182e0d3249d51fab651 Mon Sep 17 00:00:00 2001 From: AIOSAI Date: Mon, 8 Jun 2026 10:19:51 -0700 Subject: [PATCH] security(release): sign GitHub Release artifacts with Sigstore (keyless) publish.yml github-release job now signs the wheel + sdist via sigstore/gh-action-sigstore-python (pinned v3.3.0 / 04cffa1d), keyless OIDC, and attaches the .sigstore.json bundles to the GitHub Release through the existing dist/* glob. Added id-token: write to the job for OIDC. PyPI uploads were already attested (Trusted Publishing); Scorecard's Signed-Releases check inspects GitHub Releases, which only carried bare wheels -> score 0. .sigstore.json is in Scorecard's recognized signatureExtensions. Verified: action globs ./dist/*.whl ./dist/*.tar.gz (action.py:202), auto-attach gated on release-event (we trigger on push:tags) so we upload via dist/* and set release-signing-artifacts:false. First live proof = next v* tag. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish.yml | 12 ++++++++++++ CHANGELOG.md | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f12f9bf5..875357a7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -41,12 +41,24 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + id-token: write # keyless Sigstore signing (OIDC); no signing key exists steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: dist path: dist/ + - name: Sign artifacts with Sigstore (keyless, OIDC) + # Produces dist/.sigstore.json bundles next to each wheel/sdist. + # The 'gh release create dist/*' step below then attaches them to the + # GitHub Release, which is where Scorecard's Signed-Releases check looks. + # release-signing-artifacts is disabled: the action's own auto-attach only + # fires on a 'release: published' event, but we trigger on 'push: tags', + # so we upload the bundles ourselves via the dist/* glob. + uses: sigstore/gh-action-sigstore-python@04cffa1d795717b140764e8b640de88853c92acc # v3.3.0 + with: + inputs: ./dist/*.tar.gz ./dist/*.whl + release-signing-artifacts: false - name: Extract latest CHANGELOG section run: | # Grab the topmost "## [...]" block from CHANGELOG.md as release notes. diff --git a/CHANGELOG.md b/CHANGELOG.md index d2c2e72a..f83c1f6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,13 @@ and this project uses [Calendar Versioning](https://calver.org/) in the format default broad `GITHUB_TOKEN` scopes — dropping the OpenSSF Scorecard Token-Permissions check to 0. Added `permissions: contents: read`; the workflow only reads the repo to build and smoke-test the wheel. +- **Signed GitHub Releases via Sigstore (keyless).** The release workflow now + signs the built wheel + sdist with `sigstore/gh-action-sigstore-python` + (keyless OIDC — no signing key is generated, stored, or held by anyone) and + attaches the resulting `.sigstore.json` bundles to the GitHub Release. PyPI + uploads were already attested via Trusted Publishing; this extends verifiable + provenance to artifacts pulled from GitHub Releases and satisfies the OpenSSF + Scorecard Signed-Releases check. First proof lands on the next `v*` tag. ---