Skip to content

ci: pin third-party actions to commit SHAs - #2047

Open
arpitjain099 wants to merge 1 commit into
denoland:mainfrom
arpitjain099:ci/pin-actions-to-shas
Open

arpitjain099 wants to merge 1 commit into
denoland:mainfrom
arpitjain099:ci/pin-actions-to-shas

Conversation

@arpitjain099

Copy link
Copy Markdown

Second half of the follow-up to #1981, separate from #2046 so the noisy diff stays out of the behavioural change. Either can land without the other.

Every action outside the denoland org resolves from a mutable ref at run time. Four of them track something that moves on purpose:

cargo-bins/cargo-binstall@main
taiki-e/install-action@nextest
dtolnay/rust-toolchain@nightly
actions/checkout@v3, @v4, actions/cache@v4, actions/setup-python@v5, actions/upload-artifact@v4, actions/download-artifact@v4

The major-version tags belong in that list rather than above it. CVE-2025-30066 did not involve a malicious release: the attacker rewrote existing tags on tj-actions/changed-files so that every workflow tracking @v45 picked up the payload on its next run without anything in any repository changing. A pin to a commit is the only ref an upstream compromise cannot rewrite.

This pins all 37 non-denoland uses: entries to the commit each ref currently resolves to, with the version in a trailing comment. No versions change, so the actions that run after this are byte-identical to the ones running today.

Two details worth flagging for review:

  • denoland/setup-deno is left on v1 and main. It is yours, and pinning it would mean a bump in this repository every time you release it. Say the word if you would rather have it pinned as well.
  • taiki-e/install-action@nextest and dtolnay/rust-toolchain@nightly look like they encode their tool and toolchain in the ref string, which would break under a SHA pin. They do not. Each ref carries its own action.yml with tool: default: nextest and toolchain: default: nightly respectively, so pinning to the commit that ref points at preserves the default and needs no added with: block. I read both files at those refs to confirm before pinning rather than assuming it.

Keeping these current is dependabot with package-ecosystem: github-actions, which understands SHA pins and rewrites both the SHA and the comment. Happy to add that config in a third PR if you want it.

Every action outside the denoland org resolved from a mutable ref at run
time. Four of them from branches or moving tags (cargo-binstall@main,
install-action@nextest, rust-toolchain@nightly, and the actions/* major
tags), which is the shape the tj-actions/changed-files compromise took:
the attacker moved existing tags rather than publishing a new release,
so every workflow tracking a tag picked up the payload on its next run.

Pins all 37 non-denoland uses: to the commit each ref currently resolves
to, with the version in a trailing comment. No version changes.

denoland/setup-deno is left on v1 and main since it is first-party.

taiki-e/install-action@nextest and dtolnay/rust-toolchain@nightly select
their tool and toolchain through a default baked into action.yml on that
ref rather than through the ref string itself, so pinning to the commit
each one points at keeps the same default and needs no added with:
block. Verified by reading action.yml at both refs.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant