fix: pin 19 actions to commit SHA, extract 7 expressions to env vars (#92016)
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](https://x.com/vigilance_one/status/2036581210663616729) and a
[research
site](https://www.vigilantdefense.com/research/github-top-50k-repos-cicd-security-scan)
if you want more context. I wrote a scanner called Runner Guard and open
sourced it [here](https://github.com/Vigilant-LLC/runner-guard).
If you have any questions, reach out. I'll be monitoring comms.
\\- Chris Nyhuis (dagecko)
---------
Co-authored-by: Benjamin Woodruff <github@benjam.info>
Co-authored-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>