feat(ci): add release artifact signing workflow#27
Conversation
Adds cosign-based signing for all release assets (.whl and .tar.gz). Signatures (.sig) and certificates (.pem) are uploaded back to the GitHub release after successful signing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
WalkthroughThis PR introduces a new GitHub Actions workflow that automatically signs Python release artifacts (wheels and tarballs) using Cosign when releases are published. The workflow downloads assets from the release, signs each with Cosign, and uploads the generated signature files back to the release for distribution. ChangesRelease Artifact Signing Workflow
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release-sign.yml:
- Around line 7-9: Remove the top-level "id-token: write" entry from the
workflow-level permissions block so the workflow-wide default no longer grants
OIDC token write access; keep "permissions: contents: read" at top-level and
rely on the "permissions" block defined on the "sign" job (the job-level
permissions will still control OIDC access for that job), ensuring no unintended
jobs inherit id-token write.
- Around line 24-25: Remove the unnecessary "Checkout" step that uses
actions/checkout in the release-sign workflow: delete the step block with name
"Checkout" and the uses: actions/checkout@... entry (ensure no other steps
reference checked-out repo files or rely on workspace contents) so the job only
downloads release assets via the GitHub API, signs with cosign, and uploads
signatures without executing the checkout action.
- Around line 19-22: The "Harden runner" step using
step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 currently
sets egress-policy: audit which only logs outbound connections; change the input
egress-policy from audit to block (egress-policy: block) to prevent outbound
network exfiltration for this signing workflow and, if the action requires
specific allowed endpoints, add the appropriate allow list via the harden-runner
inputs after switching to block.
- Line 28: The cosign-installer action SHA is incorrect: replace the pinned SHA
`dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da` used in the `uses:
sigstore/cosign-installer@...` step with the correct commit
`1aa8e0f2454b781fbf0fbf306a4c9533a0c57409` or simply reference the `v3.7.0` tag
(e.g., `sigstore/cosign-installer@v3.7.0`) to fix the mismatch; additionally, if
this workflow requires cosign v3+, update the action to a v4+ release (e.g., use
`sigstore/cosign-installer@v4` or the appropriate v4 commit) because
cosign-installer v3.x installs cosign v2.x.
- Around line 58-62: Replace the deprecated cosign sign-blob flags
--output-signature and --output-certificate with the recommended --bundle flag:
update the cosign sign-blob invocation (the command using the "$artifact"
variable) to write a single bundle file (e.g. "${artifact}.bundle") instead of
separate .sig and .pem files, and update any downstream upload/consume steps
that referenced "${artifact}.sig" or "${artifact}.pem" to use the new bundle
filename; ensure the bundle filename is consistently used across the workflow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 57f461cc-e39b-4d2d-a0a1-1d857c75ca5a
📒 Files selected for processing (1)
.github/workflows/release-sign.yml
| permissions: | ||
| contents: read | ||
| id-token: write |
There was a problem hiding this comment.
Remove id-token: write from the workflow-level permissions block
The job already declares its own permissions block (lines 15–17), which completely replaces the workflow-level permissions for that job. The top-level id-token: write here has no effect on the sign job but does become the default permission for any future job that is added without its own permissions block, silently granting OIDC token write access to unanticipated steps.
🔒 Proposed fix
permissions:
contents: read
- id-token: write🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release-sign.yml around lines 7 - 9, Remove the top-level
"id-token: write" entry from the workflow-level permissions block so the
workflow-wide default no longer grants OIDC token write access; keep
"permissions: contents: read" at top-level and rely on the "permissions" block
defined on the "sign" job (the job-level permissions will still control OIDC
access for that job), ensuring no unintended jobs inherit id-token write.
| - name: Harden runner | ||
| uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 | ||
| with: | ||
| egress-policy: audit |
There was a problem hiding this comment.
Upgrade egress-policy from audit to block for this signing workflow
audit mode only logs outbound connections — it does not block them. A compromised transitive dependency running in this job could exfiltrate the OIDC token or signed artifacts without obstruction. Because this workflow specifically requests id-token: write and calls out to Sigstore services, restricting egress to the required endpoints is especially important.
🔒 Proposed fix
- name: Harden runner
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
- egress-policy: audit
+ egress-policy: block
+ allowed-endpoints: >
+ api.github.com:443
+ fulcio.sigstore.dev:443
+ rekor.sigstore.dev:443
+ tuf-repo-cdn.sigstore.dev:443
+ oauth2.sigstore.dev:443
+ uploads.github.com:443As per coding guidelines: "Security best practices (minimal permissions, pinned actions)" — restricting egress is a key hardening control for sensitive workflows.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Harden runner | |
| uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 | |
| with: | |
| egress-policy: audit | |
| - name: Harden runner | |
| uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 | |
| with: | |
| egress-policy: block | |
| allowed-endpoints: > | |
| api.github.com:443 | |
| fulcio.sigstore.dev:443 | |
| rekor.sigstore.dev:443 | |
| tuf-repo-cdn.sigstore.dev:443 | |
| oauth2.sigstore.dev:443 | |
| uploads.github.com:443 |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release-sign.yml around lines 19 - 22, The "Harden runner"
step using step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7
currently sets egress-policy: audit which only logs outbound connections; change
the input egress-policy from audit to block (egress-policy: block) to prevent
outbound network exfiltration for this signing workflow and, if the action
requires specific allowed endpoints, add the appropriate allow list via the
harden-runner inputs after switching to block.
| - name: Checkout | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
The actions/checkout step is unnecessary and increases attack surface
This workflow only downloads release assets from the GitHub API, signs them with cosign, and uploads the resulting signature files back. No repository source files are referenced at any point. Removing checkout eliminates one more action execution path from the signing environment.
♻️ Proposed fix
- - name: Checkout
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Checkout | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| # (Previous workflow steps would appear here) | |
| # The checkout step and its blank line are removed entirely | |
| # (Next workflow steps would appear here) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release-sign.yml around lines 24 - 25, Remove the
unnecessary "Checkout" step that uses actions/checkout in the release-sign
workflow: delete the step block with name "Checkout" and the uses:
actions/checkout@... entry (ensure no other steps reference checked-out repo
files or rely on workspace contents) so the job only downloads release assets
via the GitHub API, signs with cosign, and uploads signatures without executing
the checkout action.
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
|
|
||
| - name: Install cosign | ||
| uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm the SHA pinned in the workflow matches the v3.7.0 tag on cosign-installer
git ls-remote https://github.com/sigstore/cosign-installer.git refs/tags/v3.7.0Repository: ByronWilliamsCPA/python-libs
Length of output: 130
🌐 Web query:
cosign-installer v3 v4 cosign binary version compatibility
💡 Result:
cosign-installer v3.x is incompatible with cosign binary v3.x and later; it cannot install cosign v3.x and defaults to cosign v2.x versions (e.g., v2.6.1 in v3.10.1).[1][2][3] cosign-installer v4.x (starting v4.0.0) adds support for installing cosign v3.x and later, with defaults like v3.0.2 in v4.0.0 progressing to v3.0.5 in v4.1.1.[4][5][3][6] v4.x can still install cosign v2.x via the cosign-release input.[1][3] To use cosign v3+, upgrade to cosign-installer v4+; v3.x is limited to cosign v2.x.[1][2]
Citations:
- 1: https://github.com/sigstore/cosign-installer/releases
- 2: https://github.com/sigstore/cosign-installer/releases/tag/v3.10.1
- 3: https://github.com/sigstore/cosign-installer/releases/tag/v4.0.0
- 4: https://github.com/sigstore/cosign-installer/releases/tag/v4.1.1
- 5: https://github.com/sigstore/cosign-installer/releases/tag/v4.1.0
- 6: sigstore/cosign-installer@v4.0.0...v4.1.0
Fix SHA pinning mismatch for cosign-installer v3.7.0
The pinned SHA dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da does not correspond to the v3.7.0 tag. The actual commit for v3.7.0 is 1aa8e0f2454b781fbf0fbf306a4c9533a0c57409. Either update the SHA to the correct value or use the tag reference directly.
Additionally, cosign-installer v3.x installs cosign v2.x (not v3.x). If cosign v3+ is required for this workflow, upgrade to cosign-installer v4+, which supports cosign v3.x.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release-sign.yml at line 28, The cosign-installer action
SHA is incorrect: replace the pinned SHA
`dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da` used in the `uses:
sigstore/cosign-installer@...` step with the correct commit
`1aa8e0f2454b781fbf0fbf306a4c9533a0c57409` or simply reference the `v3.7.0` tag
(e.g., `sigstore/cosign-installer@v3.7.0`) to fix the mismatch; additionally, if
this workflow requires cosign v3+, update the action to a v4+ release (e.g., use
`sigstore/cosign-installer@v4` or the appropriate v4 commit) because
cosign-installer v3.x installs cosign v2.x.
| cosign sign-blob \ | ||
| --yes \ | ||
| --output-signature "${artifact}.sig" \ | ||
| --output-certificate "${artifact}.pem" \ | ||
| "$artifact" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Does cosign v2 (installed by cosign-installer v3.7.0) support the --bundle flag for cosign sign-blob?
💡 Result:
Yes. Cosign v2’s cosign sign-blob supports the --bundle flag to write the Sigstore “bundle” file for the blob signature/verification metadata. [1][2] In particular, the Sigstore documentation shows cosign sign-blob <file> --bundle artifact.sigstore.json as the recommended way to sign blobs. [1] Additionally, the cosign sign-blob flag reference documents --bundle string as “write everything required to verify the blob to a FILE”. [2] Note: if you install Cosign v2 using cosign-installer, whether --bundle is available is independent of the installer version; --bundle is a cosign sign-blob CLI flag in v2. [1][2]
Citations:
- 1: https://docs.sigstore.dev/cosign/signing/signing_with_blobs/
- 2: https://github.com/sigstore/cosign/blob/main/doc/cosign_sign-blob.md
Switch from --output-signature/--output-certificate to --bundle for cosign sign-blob
The --output-signature and --output-certificate flags are deprecated in Cosign v2. Sigstore documentation officially recommends using the --bundle flag to write the entire Sigstore bundle (containing both signature and certificate) to a single file. This avoids a future breaking change, simplifies verification workflows (one file instead of two), and aligns with standardized Sigstore practices.
♻️ Proposed fix
cosign sign-blob \
--yes \
- --output-signature "${artifact}.sig" \
- --output-certificate "${artifact}.pem" \
+ --bundle "${artifact}.sigstore.json" \
"$artifact"The upload step filter would also need updating:
- for f in *.sig *.pem; do
+ for f in *.sigstore.json; do🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release-sign.yml around lines 58 - 62, Replace the
deprecated cosign sign-blob flags --output-signature and --output-certificate
with the recommended --bundle flag: update the cosign sign-blob invocation (the
command using the "$artifact" variable) to write a single bundle file (e.g.
"${artifact}.bundle") instead of separate .sig and .pem files, and update any
downstream upload/consume steps that referenced "${artifact}.sig" or
"${artifact}.pem" to use the new bundle filename; ensure the bundle filename is
consistently used across the workflow.
|
Closing — not mergeable after other CI workflow PRs merged. Renovate will recreate. |



Adds cosign-based signing for release assets. Part of standard workflow set for python-package repos.
Summary by CodeRabbit