Skip to content

Security: pin GitHub Actions in release and CI workflows to commit SHAs - #7

Open
pimfeltkamp wants to merge 1 commit into
mainfrom
ai-security/code-67fe569e
Open

pimfeltkamp wants to merge 1 commit into
mainfrom
ai-security/code-67fe569e

Conversation

@pimfeltkamp

Copy link
Copy Markdown
Contributor

What was vulnerable

.github/workflows/release.yml grants id-token: write (RubyGems trusted-publishing OIDC) and contents: write, yet referenced four third-party actions by mutable tag: actions/checkout@v6, ruby/setup-ruby@v1, rubygems/configure-rubygems-credentials@v1.0.0 and softprops/action-gh-release@v3. Tags can be moved or an upstream repository compromised, in which case the replaced action code runs inside the job that can mint the gem-publishing OIDC token and could push a malicious cryptohopper gem. Verified by reading the workflow: all four uses: entries were tag references.

What the fix does

Pins every action to the full commit SHA its tag resolves to today, with a version comment so the existing Dependabot github-actions config keeps bumping both SHA and comment together:

Action Pinned commit Version
actions/checkout d23441a4 v6.1.0 (what v6 points at)
ruby/setup-ruby de492cf3 v1.336.0 (head of the v1 branch)
rubygems/configure-rubygems-credentials bc6dd217 v1.0.0
softprops/action-gh-release efb35369 v3.0.3 (annotated v3 tag dereferenced)

Each mapping was resolved via the GitHub API in this run and independently re-verified by a reviewer pass.

ci.yml uses the same two actions (checkout, setup-ruby) and shares the bundler-cache with release runs on the same runner image and Ruby version, so it is pinned to the identical SHAs to close that lateral path.

Why it is non-breaking

Every pinned commit is exactly the code the mutable tag currently resolves to, so the workflows run the same action code as before. No inputs, permissions or steps changed. Not breaking.

Tests

  • git diff --check: clean (no whitespace errors).
  • All six uses: lines confirmed SHA-pinned by reading the files back with Node.
  • A full YAML parse could not be run: Ruby and yq are blocked in this unattended sandbox and Python has no yaml module. Only the ref token on each existing line changed, so structure is unaffected. CI on this PR will exercise ci.yml for real.

Reviewer notes (not addressed here, out of scope)

  • There is no Gemfile.lock, so bundle install in the release job resolves gem versions at release time while the OIDC token is available. Committing a lockfile or running tests in a separate job without id-token would close that.
  • Permissions are workflow-level; splitting test and publish jobs with per-job permissions would shrink exposure.
  • configure-rubygems-credentials v1.0.0 runs on Node 20; newer v2.x tags exist. Upgrading is a separate change.

🤖 Automated security fix by claude-code-security. It is reviewed by the automated PR reviewer and auto-merged only if the review passes, CI is green, and the change is small and non-breaking.

🤖 Generated with Claude Code

release.yml runs with id-token: write (RubyGems trusted publishing) and contents: write, but referenced actions/checkout, ruby/setup-ruby, rubygems/configure-rubygems-credentials and softprops/action-gh-release by mutable tag. A retagged or compromised upstream action would execute inside the job that can mint the gem-publishing OIDC token. Pin each action to the full commit SHA its tag currently resolves to, with a version comment so Dependabot (github-actions ecosystem) keeps bumping them. ci.yml uses the same two actions and shares the bundler cache with release runs, so it is pinned to the identical SHAs.

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

@pimfeltkamp pimfeltkamp left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

✅ Automated review passed — no issues found. (Would approve, but the reviewer account authored this PR and GitHub forbids self-approval.)

✅ Safe to merge

@pimfeltkamp pimfeltkamp added the ai-security-needs-human Security agent: this PR needs a human decision label Nov 3, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-security-needs-human Security agent: this PR needs a human decision

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant