Skip to content

Security: pin softprops/action-gh-release to commit SHA in release workflow - #16

Open
pimfeltkamp wants to merge 1 commit into
mainfrom
ai-security/code-54968d95
Open

pimfeltkamp wants to merge 1 commit into
mainfrom
ai-security/code-54968d95

Conversation

@pimfeltkamp

Copy link
Copy Markdown
Contributor

What was vulnerable

The tag-triggered publish job in .github/workflows/release.yml runs with contents: write and id-token: write and uses secrets.NPM_TOKEN in an earlier step. Its last step ran softprops/action-gh-release@v3, a mutable tag. If that tag were moved or the action compromised, attacker-controlled code would run with the job's GITHUB_TOKEN and could tamper with the workspace and the GitHub release.

What the fix does

Pins the action to the full commit SHA that both v3 and v3.0.4 resolve to today, with a # v3.0.4 version comment:

softprops/action-gh-release@8a0cd651e5b2365bd640854a3fa5dfc70e4875f3 # v3.0.4

The SHA was resolved via gh api by dereferencing the annotated v3 tag object to its commit, and cross-checked against the v3.0.4 tag. .github/dependabot.yml already has a github-actions ecosystem entry, so Dependabot will keep the SHA and version comment updated.

Why it is non-breaking

The pinned commit is exactly the code @v3 runs today, so release behaviour is unchanged. The action's inputs used here (generate_release_notes, prerelease) are unchanged at that commit. The only behavioural difference is that future v3.x patches arrive via Dependabot PRs instead of silently.

Tests run

  • git diff: one line changed in one file.
  • YAML syntax check: no YAML parser available in this environment (no PyYAML, no node_modules), so no parser-based check was run. The change swaps a single token on one line and keeps structure identical; the trailing comment is preceded by a space, so YAML treats it as a comment.
  • An independent read-only review (Opus) confirmed the SHA is the commit v3/v3.0.4 point to, that it is on upstream history (identical to master), that inputs and permissions are unchanged, and found no regression.

Noted, not changed (pre-existing, out of scope of this finding)

actions/checkout@v6 and actions/setup-node@v6 in release.yml and ci.yml remain on mutable tags. In release.yml they run before the npm publish step in the same privileged job. Worth a separate follow-up.

🤖 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

…rkflow

The tag-triggered publish job holds contents: write and id-token: write and uses NPM_TOKEN, but ran softprops/action-gh-release by the mutable @V3 tag. Pin it to the commit that v3 / v3.0.4 resolve to today so a moved tag cannot run different code with the job's token. Dependabot's github-actions ecosystem keeps the pin updated via the version comment.

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 9, 2026
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