Skip to content

SEC001 — unpinned-action

Severity: blocker · Category: Security

What it checks

Flags any uses: reference to a third-party action (or reusable workflow) that isn't pinned to a full 40-character commit SHA — a mutable tag like @v4 or a branch like @main instead.

Why it matters

Tags and branches can be moved. If an action's maintainer's account is compromised — or a malicious actor gains write access to the action's repo — they can silently repoint @v4 at a different commit without anyone's workflow file changing at all. Every consumer picks up the new code on their very next run. A commit SHA can't be moved; it's the only form of uses: reference that's actually immutable.

Examples

Flagged — the ref after @ is a mutable tag:

steps:
  - uses: actions/checkout@v4
  - uses: some-org/deploy-action@main

Fixed — pinned to a full commit SHA, with the human-readable version kept as a trailing comment so it's still easy to see at a glance:

steps:
  - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.2.2
  - uses: some-org/deploy-action@f1a2b3c4d5e6f7890123456789abcdef0123456 # v2.1.0

Local actions (uses: ./my-action) and Docker actions (uses: docker://alpine:3.19) are exempt — there's no equivalent SHA to pin for either.

Suppressing

- uses: actions/checkout@v4 # vlotpipe: ignore[SEC001]

Only do this for actions you fully trust and actively monitor — this is the rule with the strongest real-world evidence behind it (see docs/SECURITY_RESEARCH.md's account of the tj-actions/changed-files incident, where every tag-pinned consumer was compromised simultaneously).