Skip to content

fix: pin 19 actions to commit SHA, extract 7 expressions to env vars - #92016

Merged
bgw merged 3 commits into
vercel:canaryfrom
dagecko:runner-guard/fix-ci-security
Apr 1, 2026
Merged

fix: pin 19 actions to commit SHA, extract 7 expressions to env vars#92016
bgw merged 3 commits into
vercel:canaryfrom
dagecko:runner-guard/fix-ci-security

Conversation

@dagecko

@dagecko dagecko commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Re-submission of #91933. Had a problem with my fork and had to delete it, which closed the original PR. Apologies for the noise.

Summary

This PR pins all GitHub Actions to immutable commit SHAs instead of mutable version tags and extracts expressions from run: blocks into env: mappings.

  • Pin 19 unpinned actions across workflow files to full 40-character SHAs
  • Add version comments for readability (e.g., @abc123 # v1.0.9)
  • Extract 2 secrets and 5 workflow_dispatch inputs from run blocks to env vars

Changes by file

File Changes
build_and_deploy.yml Pinned ijjk/rust-cache, ast-grep/action, taiki-e/install-action to SHA
build_reusable.yml Pinned ijjk/rust-cache, SimenB/github-actions-cpu-cores to SHA
cancel.yml Pinned withgraphite/graphite-ci-action to SHA, extracted GRAPHITE_TOKEN to env var
lock.yml Pinned dessant/lock-threads to SHA
notify_slack.yml Pinned slackapi/slack-github-action to SHA (2 instances)
publish_canary.yml Extracted NPM_TOKEN_ELEVATED to env var
publish_release.yml Extracted 5 workflow_dispatch inputs to env vars
retry_deploy_test.yml Pinned dtolnay/rust-toolchain to SHA
triage.yml Pinned balazsorban44/nissuer to SHA
turbopack_benchmark.yml Pinned taiki-e/install-action, ijjk/rust-cache, CodSpeedHQ/action to SHA
turbopack_benchmark_wasm.yml Pinned taiki-e/install-action, CodSpeedHQ/action to SHA
turbopack_benchmark_xtask.yml Pinned taiki-e/install-action, CodSpeedHQ/action to SHA

Actions Pinned

Action Version SHA
ijjk/rust-cache turbo-cache-v1.0.9 a34594c45081...
ast-grep/action v1.5.0 cf62e780f0c8...
taiki-e/install-action nextest / v2 3a0adb... / 7627fb...
withgraphite/graphite-ci-action main ee395f3a7825...
dessant/lock-threads v5 1bf7ec25051f...
slackapi/slack-github-action v1.25.0 6c661ce58804...
SimenB/github-actions-cpu-cores v2 97ba232459a8...
dtolnay/rust-toolchain stable 631a55b12751...
balazsorban44/nissuer 1.10.0 92ef22afd6a7...
CodSpeedHQ/action v4 1c8ae4843586...

A note on internal action pinning

This PR pins all actions including org-owned ones. Best practice is to pin everything \u2014 the tj-actions/changed-files attack was an internally maintained action that was compromised, and every repo referencing it by tag silently executed attacker code. That said, it's your codebase. If you'd prefer to leave org-owned actions unpinned, let us know and we'll adjust the PR.

How to verify

Review the diff \u2014 each change is mechanical and preserves workflow behavior:

  • SHA pinning: action@v3 becomes action@abc123 # v3 \u2014 original version preserved as comment
  • Expression extraction: ${{ expr }} in run: moves to env: block, referenced as $ENV_VAR in the script
  • No workflow logic, triggers, or permissions are modified

I put up some research on this on Twitter and a research site if you want more context. I wrote a scanner called Runner Guard and open sourced it here.

If you have any questions, reach out. I'll be monitoring comms.

\- Chris Nyhuis (dagecko)

@nextjs-bot

nextjs-bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Allow CI Workflow Run

  • approve CI run for commit: afc9ff9

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

Comment thread .github/workflows/graphite_ci_optimizer.yml Outdated
@dagecko
dagecko force-pushed the runner-guard/fix-ci-security branch from 7edb970 to afc9ff9 Compare March 29, 2026 04:03
@dagecko

dagecko commented Mar 29, 2026

Copy link
Copy Markdown
Contributor Author

Pushed an update. Fixed the missing trailing newline on graphite_ci_optimizer.yml and found some additional hardening opportunities:

  • 1 critical: github.ref was inside a single-quoted string in build_and_deploy.yml — GitHub Actions expands expressions before the shell runs, so single quotes don't protect against injection. Extracted to env var.
  • 2 high: inline secrets (NPM_TOKEN_ELEVATED, GRAPHITE_TOKEN) extracted from run blocks to env mappings
  • 5 high: workflow_dispatch inputs extracted from run blocks to env mappings
  • 19 action pins across 14 workflow files

All changes are mechanical and preserve existing workflow behavior.

I also posted on Twitter about a lot of these hardening techniques if you want to read through the research, and if you like it wouldn't mind a repost.

- Chris (dagecko)

Comment on lines +559 to +561
run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN_ELEVATED}" > ~/.npmrc
env:
NPM_TOKEN_ELEVATED: ${{ secrets.NPM_TOKEN_ELEVATED }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's little risk of escaping issues here because the stuff in secrets.* is not user-supplied.

Comment thread .github/workflows/turbopack-benchmark.yml Outdated
Comment thread .github/workflows/turbopack-benchmark.yml Outdated
Comment thread .github/workflows/turbopack-benchmark.yml Outdated
Comment on lines 47 to +48
CODE_FREEZE_TOKEN: ${{ secrets.CODE_FREEZE_TOKEN }}
INPUT_TYPE: ${{ github.event.inputs.type }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also, not really user-controllable, this would have to be done by somebody with workflow_dispatch permissions, but it doesn't hurt

Comment thread .github/workflows/setup-nextjs-build.yml Outdated
reproduction-comment: '.github/comments/invalid-link.md'
reproduction-hosts: 'github.com,bitbucket.org,gitlab.com,codesandbox.io,stackblitz.com'
reproduction-blocklist: 'github.com/vercel/next.js.*,github.com/\\w*/?$,github.com$'
reproduction-blocklist: 'github.com/vercel/next.js.*,github.com/\w*/?$,github.com$'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah, yep, does look like a typo, thanks

Comment thread .github/workflows/turbopack-benchmark.yml Outdated
Comment thread .github/workflows/turbopack-benchmark.yml Outdated
Comment thread .github/workflows/turbopack-benchmark.yml Outdated
bgw and others added 2 commits March 31, 2026 14:19
@bgw
bgw enabled auto-merge (squash) March 31, 2026 21:21
@nextjs-bot

nextjs-bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Tests Passed

@bgw
bgw merged commit f7de136 into vercel:canary Apr 1, 2026
394 of 402 checks passed
@bgw

bgw commented Apr 1, 2026

Copy link
Copy Markdown
Member

Thanks @dagecko. This had always bothered me a little, but I didn't prioritize it how I probably should've.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Apr 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants