Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/semgrep-rules/actions-need-pinned-commits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# actions-need-pinned-commits

For actions that look like:

```
uses: actions/checkout@v4
```

GitHub uses the underlying git label v4 to fetch the action to run. As seen in the [tj-actions/changed-files](https://semgrep.dev/blog/2025/popular-github-action-tj-actionschanged-files-is-compromised/) vulnerabilty, these lables are not immutable and trivially changeable. So what you think is a nice stable safe version, an attacker has changed behind your back to something nefarious.

We are strongly encouraging use to use the full git commit hash instead to prevent this type of attacks.

## Ratchet

[Ratchet](https://github.com/sethvargo/ratchet) provides an easy way to do this.

You can pin all your workflow files like this:

```
ratchet pin .github/workflows/*
```

And upgrade them (as needed, under your control and not someone elses):

```
ratchet upgrade .github/workflows/action_to_upgrade.yml
```
18 changes: 18 additions & 0 deletions semgrep-rules/actions/actions_need_pinned_commits.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
rules:
- id: actions-need-pinned-commits
languages:
- yaml
severity: WARNING
message: 'Referencing an action to run by git tag is risky, due to the mutability of git tags. Prefer
to use full git SHAs instead. '
metadata:
category: best-practice
technology:
- github-actions
patterns:
- pattern-either:
- patterns:
- pattern-inside: "{steps: ...}"
# Match all uses patterns that don't contain the full SHA1 hash. Yes, short hashes exist but suffer from a similar (but slightly harder) attack vector by purposely crafting a colliding SHA.
- pattern: "uses: ..."
- pattern-not-regex: ".*@[0-9A-Fa-f]{40}"
17 changes: 17 additions & 0 deletions semgrep-tests/actions/actions_need_pinned_commits.test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: 'Test Actions Needing Pinned Commits'
on:
pull_request:
jobs:
do-stuff:
steps:
- name: 'Step 1'
# ruleid: actions-need-pinned-commits
uses: actions/checkout@v4
- name: 'Step 2'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # ratchet:actions/checkout@v4
- name: 'Step 3'
# ruleid: actions-need-pinned-commits
uses: 'actions/checkout@11bd719'
- name: 'Step 4'
# ruleid: actions-need-pinned-commits
uses: 'actions/checkout@my_git_label'
Loading