WIP: Nix/android devshell#434
Conversation
| uses: DeterminateSystems/nix-installer-action@v17 | ||
|
|
||
| - name: Enable Nix cache | ||
| uses: DeterminateSystems/magic-nix-cache-action@v13 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Action pinned to version tag @v13 instead of commit SHA, allowing action maintainers or attackers to inject malicious code into your workflow.
More details about this
The GitHub Action DeterminateSystems/magic-nix-cache-action is referenced using a semantic version tag @v13 instead of a pinned full-length commit SHA. This means the action can be re-tagged or modified by the maintainers without your knowledge.
Exploit scenario:
- An attacker gains access to the DeterminateSystems GitHub organization (via credential theft or social engineering)
- They push a malicious commit to the
magic-nix-cache-actionrepository that injects code to steal secrets or modify build artifacts - They re-tag this commit as
v13(or push it to thev13branch if the workflow uses branch references) - Your workflow runs and executes
uses: DeterminateSystems/magic-nix-cache-action@v13, which now pulls the malicious version - The attacker's code runs with access to your repository secrets, environment variables, and build artifacts during the build process for your Kotlin AAR
By pinning to a full commit SHA (e.g., @abc123def456...), you ensure that only that specific, immutable commit executes—even if v13 is later modified or re-tagged.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the tag reference in the
usesvalue with a full 40-character commit SHA for the same action version.
ChangeDeterminateSystems/magic-nix-cache-action@v13toDeterminateSystems/magic-nix-cache-action@<full-commit-sha>. -
Look up the commit SHA that corresponds to the
v13release in theDeterminateSystems/magic-nix-cache-actionrepository, and use that exact SHA in the workflow.
The final value should look likeuses: DeterminateSystems/magic-nix-cache-action@0123456789abcdef0123456789abcdef01234567. -
Keep the action repository and intended release the same, and only pin the version more precisely.
This makes the workflow use an immutable action revision instead of a movable tag. -
Alternatively, if you need to keep the readable version in the file, add it as a comment next to the pinned SHA, such as
uses: DeterminateSystems/magic-nix-cache-action@0123456789abcdef0123456789abcdef01234567 # v13.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Install Nix | ||
| uses: DeterminateSystems/nix-installer-action@v17 |
There was a problem hiding this comment.
An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.
🎉 Fixed in commit 81fbe52 🎉
| uses: DeterminateSystems/nix-installer-action@v17 | ||
|
|
||
| - name: Enable Nix cache | ||
| uses: DeterminateSystems/magic-nix-cache-action@v13 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub action is pinned to a mutable version tag (@v13) instead of an immutable commit SHA, allowing tag hijacking attacks if the upstream repository is compromised.
More details about this
The workflow step references DeterminateSystems/magic-nix-cache-action@v13, which pins only to a version tag rather than a full commit SHA. An attacker who compromises the DeterminateSystems repository could force-push a new commit to the v13 tag, causing your workflow to execute malicious code without any indication of tampering.
Exploit scenario:
- Attacker compromises the DeterminateSystems/magic-nix-cache-action repository
- Attacker force-pushes a backdoored commit to the
v13tag (e.g., code that steals secrets or injects malware into your build artifacts) - Your workflow runs and pulls the
v13tag, which now resolves to the attacker's malicious code instead of the original - The step executes the attacker's code in your CI/CD environment with access to repository secrets and the ability to modify build outputs
- Any downstream systems that consume your Android library artifacts (
libwalletkit.so) receive compromised binaries
To resolve this comment:
✨ Commit fix suggestion
-
Replace the third-party action tag with the exact 40-character commit SHA for the version you want to keep using.
Changeuses: DeterminateSystems/magic-nix-cache-action@v13touses: DeterminateSystems/magic-nix-cache-action@<full-commit-sha>. -
Resolve the SHA from the action's
v13release or the specific action version you intend to use, and use the full commit hash, not a tag or short SHA.
For example, use the commit shown on the action's release or repository page and format it asDeterminateSystems/magic-nix-cache-action@0123456789abcdef0123456789abcdef01234567. -
Keep the action repository and path unchanged, and only update the ref after
@.
Pinning to a full commit SHA makes the workflow use an immutable action revision instead of a movable tag likev13.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Install Nix | ||
| uses: DeterminateSystems/nix-installer-action@v17 |
There was a problem hiding this comment.
An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.
🧼 Fixed in commit 81fbe52 🧼
|
Semgrep found 10
GitHub Actions step uses a mutable tag or branch reference. Tags and branch names can be silently repointed by the action owner, enabling supply-chain attacks — as seen in the trivy-action and kics-github-action compromises. Pin the reference to a full 40-character commit SHA instead, e.g. |
|
|
||
| - name: Install Nix | ||
| # uses: DeterminateSystems/nix-installer-action@v17 | ||
| uses: cachix/install-nix-action@v31 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Action cachix/install-nix-action@v31 uses a mutable version tag that could be force-pushed with malicious code. Pin to a full commit SHA to ensure immutable, verifiable action execution.
More details about this
The GitHub Action cachix/install-nix-action@v31 is pinned to a semantic version tag instead of a full commit SHA. When you use a version tag like @v31, the maintainer can force-push changes to that tag, meaning the exact code your workflow runs could change between executions without any indication.
Here's how an attacker could exploit this:
- Compromised repository: An attacker gains access to the
cachix/install-nix-actionrepository (through social engineering, credential theft, etc.). - Backdoor injection: They add malicious code to the action—for example, code that exfiltrates AWS credentials from
${{ secrets.AWS_ROLE_TO_ASSUME }}or other environment variables available in the workflow. - Force-push to tag: The attacker force-pushes to the
v31tag with the backdoored code, even though the tag previously pointed to a different commit. - Automatic execution: The next time this workflow runs, GitHub pulls the latest commit for
v31and executes the backdoored version without any warning. Your step- name: Install Nixnow runs the attacker's code with full access to the CI/CD environment, secrets, and artifacts.
By pinning to the full 40-character commit SHA (e.g., cachix/install-nix-action@a1d0c6e83b0c44bea11db07e8d4f5a0b1e3c5f7a), you ensure the exact code executed is immutable—even if the maintainer's repository is compromised, the tag cannot be changed to point to malicious code.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the tag-based action reference with a full 40-character commit SHA in the
usesline for the third-party action.
Changeuses: cachix/install-nix-action@v31touses: cachix/install-nix-action@<full-commit-sha>. -
Keep the action name the same and only pin the version to the exact commit that corresponds to the release you want to use.
For example, use the commit published forcachix/install-nix-actioninstead of@v31. -
Add a comment with the human-friendly version next to the pinned SHA so future updates are easier.
For example,uses: cachix/install-nix-action@<full-commit-sha> # v31. -
Apply the same pinning format anywhere else this action is referenced in GitHub Actions workflow files.
GitHub tags can be moved, but a full commit SHA is immutable, which prevents silently pulling different action code later.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.
You can view more details about this finding in the Semgrep AppSec Platform.
|
|
||
| - name: Install Nix | ||
| # uses: DeterminateSystems/nix-installer-action@v17 | ||
| uses: cachix/install-nix-action@v31 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Action pinned to mutable version tag instead of immutable commit SHA, allowing tag hijacking attacks to inject malicious code into the workflow.
More details about this
The cachix/install-nix-action@v31 action is pinned to a version tag instead of a full commit SHA. Version tags like v31 are mutable—the maintainer can force-push changes to that tag, potentially injecting malicious code into your workflow.
Exploit scenario:
- An attacker compromises the
cachix/install-nix-actionrepository or its maintainer's account - The attacker force-pushes new code to the
v31tag, replacing the original version with their backdoored version - Your workflow runs and executes the
cachix/install-nix-action@v31step, which now contains the attacker's malicious code - The malicious code could steal secrets (like SSH keys or deployment credentials in the runner environment), exfiltrate source code, or sabotage the build output
Pinning to a full-length commit SHA (e.g., cachix/install-nix-action@a1751b...) ensures you always run the exact code you tested, making tag manipulation attacks impossible.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the tag-based action reference with the exact full commit SHA for the version you want to keep using.
Changeuses: cachix/install-nix-action@v31touses: cachix/install-nix-action@<40-character-commit-sha>. -
Pick the SHA from the
cachix/install-nix-actioncommit that corresponds to thev31release, instead of using the movablev31tag.
This makes the workflow use an immutable action revision. -
Keep the repository and action the same, and only change the part after
@.
For example:uses: cachix/install-nix-action@0123456789abcdef0123456789abcdef01234567. -
Apply the same change anywhere else this action is referenced with a tag in your workflow files, so each
uses:entry is pinned to a full 40-character SHA.
Alternatively, if you do not need this third-party action, replace it with a trusted local action such as uses: ./... or a GitHub-maintained action, but only if it provides the same behavior.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.
You can view more details about this finding in the Semgrep AppSec Platform.
|
|
||
| - name: Install Nix | ||
| # uses: DeterminateSystems/nix-installer-action@v17 | ||
| uses: cachix/install-nix-action@v31 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Actions step uses mutable version tag v31 instead of a pinned commit SHA, allowing the action owner to silently inject malicious code into your CI/CD pipeline.
More details about this
The GitHub Actions step uses: cachix/install-nix-action@v31 references the action using a mutable version tag (v31) instead of a pinned commit SHA. This is a supply-chain attack vulnerability because the action owner can silently update the v31 tag to point to a different, malicious version at any time without your knowledge.
Exploit scenario:
- An attacker compromises the
cachixGitHub account or repository - The attacker pushes malicious code and re-tags it as
v31(moving the tag pointer) - On your next workflow run, GitHub pulls the malicious version instead of the original one
- The malicious code in
cachix/install-nix-actionexecutes with full access to your CI environment (including secrets, credentials, and source code) - The attacker extracts sensitive data or injects backdoors into your build artifacts (like the
libwalletkit.sofiles being built in your workflow)
This is how real-world supply-chain attacks happened—for example, trivy-action and kics-github-action were compromised in exactly this way. Workflows running downstream of this step have no way to detect that the action has been replaced with malicious code until damage is done.
To resolve this comment:
✨ Commit fix suggestion
| uses: cachix/install-nix-action@v31 | |
| uses: cachix/install-nix-action@0f296d1d28c59d2a4a84658c1f5a2df7a6b0f0e3 # v31 |
View step-by-step instructions
- Replace the mutable action reference
cachix/install-nix-action@v31with a full 40-character commit SHA for the exact release you want to use, for exampleuses: cachix/install-nix-action@<40-character-commit-sha>. - Keep the action name the same and only change the part after
@. Do not use a tag like@v31, a branch like@main, or a shortened SHA. - If you still want the workflow to show which release the SHA came from, add that as a comment next to the pinned reference, for example
uses: cachix/install-nix-action@<40-character-commit-sha> # v31. - Get the correct commit SHA from the action's release or repository page and pin to that exact commit. This prevents the referenced code from changing silently if the tag is moved later.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
|
|
||
| - name: Install Nix | ||
| # uses: DeterminateSystems/nix-installer-action@v17 | ||
| uses: cachix/install-nix-action@v31 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
The workflow uses a mutable tag reference (@v31) for cachix/install-nix-action instead of a pinned commit SHA, allowing the action owner to silently update the code and execute malicious steps in your build pipeline.
More details about this
The workflow uses cachix/install-nix-action@v31, which references the v31 tag instead of a specific commit SHA. Tag references like @v31 are mutable—the cachix maintainers can push new code to that tag at any time without your knowledge.
An attacker who compromises the cachix GitHub account (or its CI/CD pipeline) could push malicious code to the v31 tag. The next time this workflow runs, it would execute the compromised action, which could steal secrets, modify your build artifacts, exfiltrate source code, or inject backdoors into your Android libraries. This mirrors real-world attacks like the trivy-action compromise, where attackers gained control of a popular action's tag and used it to compromise downstream projects.
For example:
- Attacker compromises
cachixaccount and pushes malicious code tov31tag - Your workflow runs and pulls the malicious
v31version instead of the legitimate code - The malicious action runs with access to your GitHub secrets and source code
- It uploads your signing keys or injects malicious code into
libwalletkit.so - The compromised library is shipped to end users
To resolve this comment:
✨ Commit fix suggestion
- Replace the mutable action reference
cachix/install-nix-action@v31with a full 40-character commit SHA for the exact release you want to trust, for exampleuses: cachix/install-nix-action@<full-40-char-sha>. - Resolve the SHA from the upstream
v31release page or by checking the commit that thev31tag currently points to, then use that commit directly in the workflow file. - Keep the existing step the same otherwise, so the line becomes
uses: cachix/install-nix-action@<full-40-char-sha>instead of using a tag. Pinning to a commit SHA prevents the action owner from silently moving the tag to different code later. - Alternatively, if you need to preserve the readable version in the file, add it as a comment next to the pinned reference, such as
# v31, but keepuses:pinned to the full commit SHA.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: DeterminateSystems/magic-nix-cache-action@v13 | ||
|
|
||
| - name: Cache Rust build artifacts | ||
| uses: actions/cache@v4 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Actions step uses mutable version tag v4 which can be silently repointed by the action owner, enabling supply-chain attacks that could steal secrets or inject malicious code into your build.
More details about this
The actions/cache@v4 step uses a mutable version tag (v4) instead of pinning to a specific commit SHA. Version tags like v4 can be silently repointed by the action owner—the maintainer of the actions/cache repository could push a malicious update under the same tag without your knowledge.
Here's how an attacker could exploit this:
- Compromise the actions/cache repository through phishing, credential theft, or exploiting a vulnerability in the GitHub organization.
- Force-push a malicious version to the
v4tag, replacing the legitimate caching action with code that steals secrets or injects malicious commands. - Your workflow automatically uses the poisoned action on the next run. The malicious action could intercept environment variables (like
GITHUB_TOKEN, API keys, or SSH keys), extract secrets from the build cache, or inject commands that execute duringcargo build. - Sensitive data is exfiltrated before your legitimate build continues, and you won't notice because the step name still says
actions/cache.
Additionally, other mutable references in this workflow are vulnerable in the same way: actions/checkout@v6, cachix/install-nix-action@v31, DeterminateSystems/magic-nix-cache-action@v13, and actions/upload-artifact@v4 all use version tags instead of commit SHAs.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the mutable action reference with a full 40-character commit SHA in the
usesline for the cache step.
Changeuses: actions/cache@v4touses: actions/cache@<full-commit-sha>. -
Get the commit SHA from the
actions/cacherelease or tag you intend to keep using, and pin that exact revision instead of the tag.
The final value should look likeuses: actions/cache@8f1...with all 40 hex characters present. -
Keep the existing
with:block unchanged unless the pinned revision’s documentation requires a different input format.
Pinning to a commit SHA prevents the action owner from silently movingv4to different code later.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: cachix/install-nix-action@v31 | ||
|
|
||
| - name: Enable Nix cache | ||
| uses: DeterminateSystems/magic-nix-cache-action@v13 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub action is pinned to a mutable version tag (@v13) instead of an immutable commit SHA, allowing attackers to redirect the tag to malicious code.
More details about this
The DeterminateSystems/magic-nix-cache-action is referenced by a version tag (@v13) instead of a pinned commit SHA. This means the actual commit executed could change if the maintainers push a new release to that tag.
Exploit scenario:
- An attacker compromises the
DeterminateSystemsorganization or their repository - They push malicious code to the
v13tag (or create a new release that gets tagged asv13) - When your workflow runs,
@v13resolves to the attacker's malicious commit instead of the original one - The malicious code runs with the permissions in your workflow (
actions: write), allowing the attacker to modify your build artifacts, steal secrets, or compromise downstream users - Unlike a pinned SHA-1 commit hash, there's no cryptographic guarantee that
@v13points to the code you originally tested
By using a version tag, you're trusting that the tag always points to safe code—but tags are mutable and can be moved or overwritten.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the third-party action tag with a full 40-character commit SHA in the
uses:line forDeterminateSystems/magic-nix-cache-action.
Changeuses: DeterminateSystems/magic-nix-cache-action@v13touses: DeterminateSystems/magic-nix-cache-action@<full-commit-sha> # v13. -
Look up the commit SHA that corresponds to the version you want to keep, and pin to that exact commit instead of the moving tag.
For example, use the action's release or tag page to find the commit behindv13, then update the workflow touses: DeterminateSystems/magic-nix-cache-action@0123456789abcdef0123456789abcdef01234567 # v13. -
Keep the version comment after the SHA so future updates are easier to review.
This makes the action immutable while still showing the intended release version. -
Repeat this format for any other third-party
uses:entries in the same workflow that are still pinned only to a tag or version.
GitHub Actions only treats a full commit SHA such as@0123456789abcdef0123456789abcdef01234567as immutable.
Alternatively, if you cannot verify a safe SHA for this action, replace it with a different maintained action that provides the same behavior and pin that replacement to a full commit SHA.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Install Nix | ||
| uses: cachix/install-nix-action@v31 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Action cachix/install-nix-action@v31 is pinned to a mutable version tag instead of a commit SHA, allowing tag manipulation attacks.
More details about this
The GitHub Action cachix/install-nix-action is referenced by version tag v31 instead of being pinned to a full commit SHA.
Exploit scenario:
- An attacker compromises the
cachix/install-nix-actionrepository on GitHub. - They push malicious code to the repository and force-update the
v31tag to point to their new commit containing a backdoor. - When this workflow runs, GitHub checks out the
v31tag, which now resolves to the attacker's malicious commit instead of the original one. - The malicious code in
install-nix-actionexecutes during the workflow with access to your repository's contents and secrets, allowing the attacker to steal credentials, modify your build artifacts, or compromise your CI/CD pipeline.
By pinning to a full commit SHA (like cachix/install-nix-action@abc123def456...), the action would always resolve to that exact immutable commit regardless of any tag manipulation.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the third-party action version tag with a full 40-character commit SHA in the
usesline for the Nix install step.
Changeuses: cachix/install-nix-action@v31touses: cachix/install-nix-action@<full-commit-sha>. -
Keep the readable version as a comment after the SHA so future updates are easier to track.
Use the same format asuses: cachix/install-nix-action@<full-commit-sha> # v31.... -
Get the correct commit SHA from the
cachix/install-nix-actionrelease or tag you intend to use, and pin to that exact commit rather than the mutablev31tag.
Pinning to a commit makes the workflow use an immutable action revision.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.
You can view more details about this finding in the Semgrep AppSec Platform.
| run: nix develop .#swift --command swift package compute-checksum WalletKit.xcframework.zip | ||
|
|
||
| - name: Upload Swift artifacts | ||
| uses: actions/upload-artifact@v4 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Mutable version tag @v4 allows the action owner to silently inject malicious code into your build process without your workflow changing.
More details about this
The actions/upload-artifact@v4 action is referenced using a mutable version tag (v4) instead of a pinned commit SHA. This means the action owner can silently update what code runs at this tag, potentially injecting malicious code without your awareness.
Exploit scenario:
- An attacker compromises the GitHub account that maintains
actions/upload-artifactor the repository itself - The attacker updates the code running under the
v4tag to exfiltrate build artifacts (in this case, yourWalletKit.xcframework.zipand Swift sources) - Your workflow continues to use
@v4, automatically pulling the compromised version on the next run - The attacker gains access to your compiled binaries and source code without any change to your workflow file—you won't know anything happened
This is exactly how the trivy-action and kics-github-action were compromised in real supply-chain attacks. By pinning to a specific commit SHA, you ensure only that exact code version runs, regardless of what the tag owner does later.
To resolve this comment:
✨ Commit fix suggestion
- Replace the mutable action reference with a full 40-character commit SHA in the
usesline for the upload step. - Update
uses: actions/upload-artifact@v4to the pinned formatuses: actions/upload-artifact@<40-character-commit-sha>. - Add the released version as a comment after the SHA so the workflow stays readable, for example
uses: actions/upload-artifact@<40-character-commit-sha> # v4.x.y. - Get the SHA from the official
actions/upload-artifactrelease you want to keep using, and make sure it is the exact commit for that release tag rather than a branch or shortened hash. Pinning to a commit SHA prevents the action owner from changing what code runs without changing your workflow file.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: DeterminateSystems/magic-nix-cache-action@v13 | ||
|
|
||
| - name: Cache Rust build artifacts | ||
| uses: actions/cache@v4 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Actions step actions/cache@v4 uses a mutable tag instead of a pinned commit SHA, allowing silent code updates by the action owner and enabling supply-chain attacks.
More details about this
The actions/cache@v4 step uses a mutable version tag (v4) instead of being pinned to a specific commit SHA. This means the action owner can silently update what code runs under this tag without your knowledge or control.
Exploit scenario:
- An attacker compromises the
actions/cacherepository or the maintainer's account. - The attacker pushes a malicious update and moves the
v4tag to point to their compromised code. - The next time this workflow runs, GitHub automatically fetches the latest commit under the
v4tag—which is now the attacker's malicious version. - The malicious action executes with access to your workflow's environment, including any secrets, repository code, and build artifacts stored in
~/.cargo/registry,~/.cargo/git, and thetarget/directories. - The attacker exfiltrates your private dependencies, signing keys, or proprietary code without leaving any audit trail showing a version change.
This bypasses the transparency you'd normally get by pinning to a commit SHA, where any supply-chain compromise would require an explicit edit to your workflow file—visible in version control history.
To resolve this comment:
✨ Commit fix suggestion
| uses: actions/cache@v4 | |
| uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.2 |
View step-by-step instructions
- Replace the mutable action tag in this step with a full 40-character commit SHA instead of
@v4. - Update the line from
uses: actions/cache@v4to a pinned form such asuses: actions/cache@<full-40-char-commit-sha> # v4.x.x. - Choose the SHA from the exact
actions/cacherelease you want to keep using, so the workflow stays on a known action revision and cannot silently move to a different commit.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: cachix/install-nix-action@v31 | ||
|
|
||
| - name: Enable Nix cache | ||
| uses: DeterminateSystems/magic-nix-cache-action@v13 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Actions step uses a mutable version tag (v13) instead of a pinned commit SHA, allowing the action owner to silently inject malicious code into your build pipeline.
More details about this
The workflow uses DeterminateSystems/magic-nix-cache-action@v13, which references a mutable version tag (v13) instead of a pinned commit hash. This creates a supply-chain attack risk: the action owner can silently update what v13 points to at any time, potentially injecting malicious code into your build pipeline without your knowledge or consent.
Exploit scenario:
- An attacker compromises the DeterminateSystems GitHub repository or account
- They force-push a malicious commit and retag
v13to point to it - The next time this workflow runs, it automatically pulls the new malicious version
- The attacker's code now executes with your repository's permissions (including
contents: readandactions: write), allowing them to steal your source code, modify workflows, or inject backdoors into your build artifacts
This happened in real incidents like the trivy-action and kics-github-action compromises, where attackers updated mutable tags to inject malicious steps into downstream CI/CD pipelines.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the mutable tag in the
usesline with the full 40-character commit SHA for the exact action version you want to keep.
Changeuses: DeterminateSystems/magic-nix-cache-action@v13touses: DeterminateSystems/magic-nix-cache-action@<full-40-character-sha> # v13.... -
Get the SHA from the action's GitHub release or tag page, and make sure it is the commit that the
v13tag currently points to.
Pinning to a commit SHA prevents the action owner from silently moving the tag to different code later. -
Keep the version as a comment after the SHA so future updates are easier to review, for example:
uses: DeterminateSystems/magic-nix-cache-action@<full-40-character-sha> # v13.x.x -
If this workflow must stay on a specific patch release, pin to the commit for that exact release instead of a moving major tag such as
v13.
Alternatively, if you intentionally need to consume a local action, change the reference to a local path such as uses: ./.github/actions/magic-nix-cache, but only if the action code is stored in this repository.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Install Nix | ||
| uses: cachix/install-nix-action@v31 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Actions step uses mutable tag v31 instead of pinned commit SHA, allowing supply-chain attack if the action's repository is compromised.
More details about this
The cachix/install-nix-action@v31 step uses a mutable version tag (v31) instead of pinning to a specific commit SHA. An attacker who controls the cachix/install-nix-action repository could silently push a malicious update to the v31 tag, and this workflow would automatically run the compromised action without any warning.
Here's a concrete attack scenario:
- Attacker gains access to the
cachix/install-nix-actionrepository (through compromised credentials, as seen in real incidents like trivy-action and kics-github-action) - Attacker force-pushes malicious code to the
v31tag, replacing the legitimate action with code that exfiltrates secrets or injects malware - Your workflow runs and checks out
cachix/install-nix-action@v31, which now resolves to the attacker's malicious code - The malicious action executes in your CI/CD environment with access to your repository secrets, build artifacts, and ability to modify your codebase
By pinning to a full 40-character commit SHA instead, you ensure this specific version of the action cannot be silently replaced.
To resolve this comment:
✨ Commit fix suggestion
-
Replace the mutable action tag with a full 40-character commit SHA in the
usesline forcachix/install-nix-action.
Changeuses: cachix/install-nix-action@v31touses: cachix/install-nix-action@<full-40-character-commit-sha>, and add the version as a comment if helpful, for exampleuses: cachix/install-nix-action@<sha> # v31.x.x. -
Pin the other third-party actions in this workflow the same way if they are also still using tags.
In this file, that includes entries likeactions/checkout@v6,DeterminateSystems/magic-nix-cache-action@v13, andactions/cache@v4, which should becomeuses: ...@<full-40-character-commit-sha>. -
Keep the action version visible in a comment after the SHA so future updates are easier to track.
For example, use the same pattern asuses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1. -
Use the commit SHA from the action release you intend to trust, not a short SHA or tag.
GitHub Actions only treats a full 40-character SHA as immutable for this protection.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
| actions: write # needed for cache save | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v6 |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
GitHub Actions step uses mutable version tag v6 which can be silently repointed by maintainers, enabling supply-chain attacks. Pin to a specific commit SHA instead.
More details about this
The actions/checkout@v6 step uses a mutable version tag (v6) instead of pinning to a specific commit. Version tags can be silently reassigned by the maintainer, allowing an attacker to inject malicious code into your build pipeline without any obvious sign of tampering.
Here's how an attacker could exploit this:
-
Compromise the actions/checkout repository or account — An attacker gains access to the GitHub repository or account that maintains the
actions/checkoutaction (e.g., through credential theft). -
Repoint the
v6tag to a malicious commit — The attacker updates the Git tagv6to point to a new commit that contains backdoored code, such as a modified checkout script that exfiltrates secrets from your workflow environment. -
Your workflow automatically runs the malicious version — The next time this workflow executes (on
workflow_dispatchorpush), your runner pulls the action using the same tag referencev6, which now resolves to the attacker's malicious commit instead of the intended one. -
Secrets and source code are compromised — Since this is a checkout action running with
contents: readandactions: writepermissions, the malicious code could steal environment variables, access the runner's cache containing sensitive artifacts (like~/.cargo/registry), or modify subsequent build steps.
This mirrors real-world attacks like the trivy-action and kics-github-action compromises.
To resolve this comment:
✨ Commit fix suggestion
| uses: actions/checkout@v6 | |
| uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v6 |
View step-by-step instructions
-
Replace the mutable version tag in the workflow step with a full 40-character commit SHA for the same action release.
Changeuses: actions/checkout@v6touses: actions/checkout@<40-character-commit-sha> # v6. -
Use the commit SHA published for the specific
actions/checkoutrelease you intend to keep using, instead of a tag likev6.
For example, the format should look likeuses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.7. -
Keep the version comment after the SHA so future updates are easier to review.
Pinning to a commit SHA prevents the action owner from moving the referenced version to different code without changing your workflow file.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
You can view more details about this finding in the Semgrep AppSec Platform.
No description provided.