ci: GitHub Actions workflow security cleanup#678
Conversation
Set persist-credentials: false on every actions/checkout invocation so the default GITHUB_TOKEN is not left in the local git config after checkout. None of these workflows push back to the repo using that token, so the credential is unused after checkout completes.
Set a top-level permissions: {} on each workflow and grant each job the
narrowest GITHUB_TOKEN scopes it actually needs (contents: read for
checkout-based jobs, id-token: write preserved for the PyPI trusted
publishing jobs). Previously the workflows ran with the repository's
default token permissions.
The release workflow runs on tag push and produces the artifacts that get uploaded to PyPI, so any cache it reads is also a way for an earlier untrusted run to influence what gets shipped. Switch setup-uv to enable-cache: false and drop the actions/cache step for .venv so the release build resolves dependencies from scratch each time.
Replace tag references (@v4, @v5, @release/v1, ...) with the corresponding commit SHA, keeping the tag in a trailing comment so the human-readable version is still visible. This protects CI from an upstream tag being moved to point at different code than what we last reviewed. The ably/features reusable workflow reference is left on @main on purpose, since that's an internal Ably workflow.
WalkthroughFour GitHub Actions workflows are hardened with explicit least-privilege permissions and pinned action SHAs. Each workflow now declares ChangesWorkflow Security Hardening
🎯 2 (Simple) | ⏱️ ~12 minutes
🚥 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.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
.github/workflows/features.yml (1)
13-18:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix reusable-workflow permissions mismatch in
.github/workflows/features.yml(lines 13-18)The reusable workflow
ably/features/.github/workflows/sdk-features.yml@maindeclaresjobs.build.permissionsasdeployments: writeandid-token: write, but this caller limits the job permissions for the reusable workflow call topermissions: contents: read; the caller’s permissions cap what the reusable workflow can use, so this can break the workflow (e.g., AWS OIDC requiresid-token). Update the caller permissions to include the required scopes.🤖 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/features.yml around lines 13 - 18, The caller limits reusable-workflow scopes to only contents: read which prevents the called workflow (uses: ably/features/.github/workflows/sdk-features.yml@main) from obtaining the deploy and OIDC tokens it requests; update the caller permissions block (the permissions: entry around the reusable workflow call) to include deployments: write and id-token: write (alongside contents: read) so the reusable workflow’s jobs.build permissions are not capped..github/workflows/release.yml (1)
19-41:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix incorrect version-tag label for pinned PyPI publish action in release workflow
In
.github/workflows/release.yml, the pinpypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277bis labeled# release/v1, but there is norelease/v1tag in the upstream repo; that SHA points to thev1.14.0tag instead (appears in both thepublish-to-pypiandpublish-to-testpypisteps). Other pinned action SHAs in this workflow match their labeled tags (actions/checkoutv4,actions/setup-pythonv5,astral-sh/setup-uvv7,actions/upload-artifact/actions/download-artifactv4).🤖 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.yml around lines 19 - 41, The workflow uses a pinned SHA for pypa/gh-action-pypi-publish but the trailing comment label is wrong; update the comment label for the pinned SHA cef221092ed1bacb1cc03d23a2d87d1d172e277b (used in the publish-to-pypi and publish-to-testpypi steps) to the correct tag (v1.14.0) so the comment matches the actual upstream tag for that SHA; locate the two steps referencing pypa/gh-action-pypi-publish in release.yml (publish-to-pypi and publish-to-testpypi) and replace the incorrect `# release/v1` label with `# v1.14.0`.
🤖 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.
Outside diff comments:
In @.github/workflows/features.yml:
- Around line 13-18: The caller limits reusable-workflow scopes to only
contents: read which prevents the called workflow (uses:
ably/features/.github/workflows/sdk-features.yml@main) from obtaining the deploy
and OIDC tokens it requests; update the caller permissions block (the
permissions: entry around the reusable workflow call) to include deployments:
write and id-token: write (alongside contents: read) so the reusable workflow’s
jobs.build permissions are not capped.
In @.github/workflows/release.yml:
- Around line 19-41: The workflow uses a pinned SHA for
pypa/gh-action-pypi-publish but the trailing comment label is wrong; update the
comment label for the pinned SHA cef221092ed1bacb1cc03d23a2d87d1d172e277b (used
in the publish-to-pypi and publish-to-testpypi steps) to the correct tag
(v1.14.0) so the comment matches the actual upstream tag for that SHA; locate
the two steps referencing pypa/gh-action-pypi-publish in release.yml
(publish-to-pypi and publish-to-testpypi) and replace the incorrect `#
release/v1` label with `# v1.14.0`.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8581515b-c34e-4f0b-bf0d-392c2975adbc
📒 Files selected for processing (4)
.github/workflows/check.yml.github/workflows/features.yml.github/workflows/lint.yml.github/workflows/release.yml
Routine hygiene pass over the GitHub Actions workflows in this repo, addressing findings from a workflow security audit. Changes are split into four commits, one per finding type:
using that token.
id-token: write preserved on the PyPI / TestPyPI trusted-publishing jobs).
can't read a cache populated by an earlier untrusted run.
reusable workflow reference is intentionally left on @main.
No behavioural changes intended — the workflows run the same checks against the same inputs.
Summary by CodeRabbit