A GitHub Action that validates third-party actions in your workflows are using immutable releases, enhancing supply chain security.
This action scans your workflow files and reports on all actions, including first-party actions (actions/*, github/*, and octokit/* organizations) and third-party actions. It validates that third-party actions are using immutable releases, which prevents supply chain attacks where a release could be modified after you've started using it.
The action generates a report organized by workflow, making it easy to identify which workflows need attention:
Actions: 2 first-party, 1 immutable, 0 mutable
| Action | Status | Message |
|---|---|---|
| actions/checkout@v4 | β First-party | First-party action |
| actions/setup-node@v4 | β First-party | First-party action |
| owner/repo@v1.2.3 | β Immutable | Immutable release |
Actions: 0 first-party, 1 immutable, 2 mutable
| Action | Status | Message |
|---|---|---|
| owner/secure-action@v2.0.0 | β Immutable | Immutable release |
| owner/mutable-action@v1 | β Mutable | No release found for this reference |
| owner/another-action@v2.1.0 | β Mutable | Mutable release |
name: Check Action Immutability
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
check-immutable:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Ensure immutable actions
uses: joshjohanning/ensure-immutable-actions@v1- name: Ensure immutable actions
uses: joshjohanning/ensure-immutable-actions@v1
with:
workflows: 'ci.yml,deploy.yml,release.yml'- name: Ensure immutable actions
uses: joshjohanning/ensure-immutable-actions@v1
with:
exclude-workflows: 'experimental.yml,temp-workflow.yml'| Input | Description | Required | Default |
|---|---|---|---|
github-token |
GitHub token for API calls | Yes | ${{ github.token }} |
fail-on-mutable |
Fail the workflow if mutable actions are found | No | true |
workflows |
Specific workflow files to check (comma-separated, e.g., ci.yml,deploy.yml). If not specified, checks ALL workflows in .github/workflows/. |
No | All workflows |
exclude-workflows |
Workflow files to exclude from checks (comma-separated). Only applies when workflows is not specified. |
No | - |
| Output | Description |
|---|---|
mutable-actions |
JSON array of actions using mutable releases |
immutable-actions |
JSON array of actions using immutable releases |
first-party-actions |
JSON array of first-party actions (actions/*, github/*, octokit/*) |
all-passed |
Boolean indicating if all checks passed |
workflows-checked |
List of workflow files that were checked |
- uses: joshjohanning/ensure-immutable-actions@v1
with:
fail-on-mutable: true # This is the default- uses: joshjohanning/ensure-immutable-actions@v1
with:
fail-on-mutable: false- uses: joshjohanning/ensure-immutable-actions@v1
with:
workflows: 'ci.yml,cd.yml,build.yml'- Scans Workflows: Reads all workflow files (or specified ones) from
.github/workflows/ - Extracts Actions: Parses YAML to find all
uses:references to third-party actions - Filters: Excludes
actions/*,github/*, andoctokit/*organizations (these already publish immutable releases) - Checks Immutability: For each third-party action:
- Full 40-character SHA references (e.g.,
user/action@abc123...def) are considered inherently immutable (no API check needed) - For tag/branch references, attempts to fetch the release via GitHub API
- Checks the
immutableproperty of the release - Reports actions without releases as mutable (e.g., major tags like
v3, non-immutable SemVer releases, and branch references)
- Full 40-character SHA references (e.g.,
- Reports Results: Creates a summary with all findings
- Optionally Fails: If
fail-on-mutableis true, fails the workflow when mutable actions are found
- β
Full 40-character SHA:
user/action@1234567890abcdef1234567890abcdef12345678- Cryptographic hash that cannot change - β Immutable release tags: Release tags that have been marked as immutable via GitHub API
- β
Actions from trusted organizations:
actions/*,github/*, andoctokit/*organizations already publish immutable releases and are excluded from checks - β Mutable release tags: Release tags that can still be modified or deleted
- β Branch references:
user/action@main- Branches are always mutable - β Major version tags:
user/action@v1- Typically don't have releases, can be moved
Immutable releases are GitHub releases that have been marked with an immutable flag, indicating they cannot be modified or deleted. This is a GitHub feature that helps prevent supply chain attacks where an attacker could modify a release that your workflows depend on.
When checking actions:
- Tags with immutable releases: β Most secure - the release content cannot be changed
- Tags with mutable releases:
β οΈ Release exists but could be modified - Tags without releases: β No release found - typical for major version tags like
v3 - Commit SHAs:
β οΈ No releases (SHAs are inherently immutable in Git) - Branch names: β Not recommended - content can change
Best practices for supply chain security:
- Use specific release tags (e.g.,
v1.2.3) with immutable releases - Or use commit SHAs (e.g.,
abc123def456...) for maximum security - Avoid major version tags (like
v3) as they typically don't have releases and point to mutable branches
git clone https://github.com/joshjohanning/ensure-immutable-actions.git
cd ensure-immutable-actions
npm installnpm test- Run Jest testsnpm run lint- Run ESLintnpm run format:write- Format code with Prettiernpm run package- Bundle the action with nccnpm run all- Run format, lint, test, coverage, and package
You can test the action locally by setting environment variables:
export INPUT_GITHUB_TOKEN="ghp_your_token_here"
export INPUT_FAIL_ON_MUTABLE="true"
export INPUT_WORKFLOWS="ci.yml"
export GITHUB_WORKSPACE="/path/to/your/repo"
node src/index.jsMIT - See LICENSE for details