Trivy Security Scanner Hit Twice: How Incomplete Containment Led to a Second GitHub Actions Breach

Aqua Security's Trivy scanner was compromised a second time in March 2026 after attackers exploited credentials missed during the first incident response. Here's what happened, why it matters, and how to protect your CI/CD pipelines.

8 min read·

Key Takeaways

  • Trivy was compromised twice in one month. The second breach stemmed from credentials missed during the first incident response.
  • Attackers poisoned 75 out of 76 version tags in trivy-action, turning trusted version references into malware distribution points.
  • The infostealer targeted SSH keys, cloud credentials, Kubernetes tokens, and crypto wallets, exfiltrating data to a typosquatted domain.
  • Pin GitHub Actions to full SHA hashes, not version tags. Tags are mutable and can be rewritten by anyone with push access.
  • SOC 2 and ISO 27001 both require incident response that includes root cause analysis and complete containment, exactly what failed here.

In early March 2026, Aqua Security's Trivy vulnerability scanner was compromised for the second time in under a month. The first breach, carried out by the HackerBot-Claw campaign in late February, exploited a pull_request_target workflow to steal a Personal Access Token. The second breach happened because the first one wasn't fully contained.

This is not just a Trivy problem. It is a case study in why incident response must be thorough, why mutable references in CI/CD pipelines are dangerous, and why compliance frameworks demand root cause analysis after every security event.


What Happened: Tag Poisoning at Scale

The First Breach (February 2026)

We covered the initial compromise in detail in our HackerBot-Claw analysis. The short version: an autonomous bot exploited a pull_request_target workflow in the Trivy repository, achieving remote code execution in the CI environment and exfiltrating credentials including a Personal Access Token (PAT).

Aqua Security responded by rotating secrets and tokens. But they missed at least one credential with sufficient privileges to push code and rewrite Git tags.

The Second Breach (March 2026)

Using the credential that survived rotation, attackers force-pushed 75 out of 76 version tags in aquasecurity/trivy-action and 7 tags in aquasecurity/setup-trivy. Each modified tag pointed to malicious code instead of the legitimate scanner.

This technique, known as tag poisoning, is particularly dangerous because:

  • Git tags are mutable. Anyone with push access can rewrite them. Unlike branch protections, tag protections are often overlooked.
  • Most CI/CD pipelines reference actions by tag. A workflow using aquasecurity/trivy-action@v0.69.0 silently pulls whatever that tag points to, with no verification.
  • No standard release artifacts were created. The attackers avoided creating GitHub Releases or pushing to branches, making the compromise harder to detect through normal monitoring.

A compromised release version 0.69.4 was also published to the main aquasecurity/trivy repository.


The Infostealer: What Was Targeted

The malicious payload operated in three stages:

Stage 1: Data Harvesting

The stealer scanned the runner environment for:

  • SSH keys from ~/.ssh/
  • Cloud provider credentials (AWS, GCP, Azure)
  • Database connection strings and credentials
  • Git and Docker configurations
  • Kubernetes tokens and kubeconfig files
  • Cryptocurrency wallet keys (particularly Solana validator key pairs)
  • All environment variables from the GitHub Actions runner

Stage 2: Encryption

Collected data was encrypted before exfiltration, making network-level detection harder for organizations monitoring outbound traffic patterns.

Stage 3: Exfiltration

Encrypted data was sent via HTTP POST to scan.aquasecurtiy[.]org, a typosquatted domain designed to pass casual inspection (note the misspelling of "aquasecurity").

If the primary exfiltration channel failed, the stealer used captured GitHub PATs to push stolen data to a public repository named tpcp-docs, an indicator of compromise worth checking for.

Attribution

The credential harvester self-identified as "TeamPCP Cloud stealer" in its source code. Security researchers link this to TeamPCP (also known as DeadCatx3, PCPcat, PersyPCP, ShellForce, CipherForce), a group known for cloud-native theft operations.


Why Incomplete Containment Is So Dangerous

The core lesson here is straightforward: the first incident response failed to eliminate all compromised credentials. Aqua Security's VP of Open Source, Itay Shakury, acknowledged this directly, stating the second breach "stemmed from incomplete containment of the initial hackerbot-claw incident."

This pattern is more common than most teams realize:

Incident Response Gap Consequence
Rotating some but not all credentials Attacker retains access through surviving tokens
Focusing on the exploited vector only Missing lateral movement and secondary access paths
Not auditing what the attacker accessed Unknown scope of compromise
Rushing to "close" the incident Premature declaration of containment

After the second breach, Aqua Security implemented a more aggressive approach: "locking down all automated actions and any token in order to thoroughly eliminate the problem." This is the approach that should have been taken the first time.


Practical Recommendations for Your Team

1. Pin GitHub Actions to Full SHA Hashes

This is the single most impactful change you can make. Instead of:

YAML
# DANGEROUS: Tags can be rewritten
- uses: aquasecurity/trivy-action@v0.35.0

Use:

YAML
# SAFE: SHA hashes are immutable
- uses: aquasecurity/trivy-action@a7a829a0747c05025eb0f57263b5537ca3f6bab1 # v0.35.0

Tools like StepSecurity's pin-github-action or Dependabot can automate this conversion across your workflows.

2. Audit Your Incident Response Completeness

After any credential compromise:

  • Enumerate all tokens and keys the attacker could have accessed, not just the ones you know they used.
  • Rotate everything in scope, even if you aren't sure it was compromised. The cost of unnecessary rotation is far lower than the cost of a second breach.
  • Audit access logs for the compromised credentials to understand the full blast radius.
  • Wait before declaring containment. Monitor for at least 72 hours after remediation for signs of persistent access.

3. Enable Tag Protection Rules

GitHub supports tag protection rules that restrict who can create or update tags matching specific patterns. Enable these for your release tags:

Text
Settings → Rules → Tag protection rules → Add rule
Pattern: v*

This prevents unauthorized tag rewrites even if an attacker obtains push access.

4. Monitor for Supply Chain Indicators

Add these checks to your security monitoring:

  • Unexpected tag updates in repositories you depend on (use GitHub's RSS feeds or the API)
  • DNS queries to typosquatted domains resembling your vendors
  • Outbound HTTP POST requests from CI/CD runners to unknown endpoints
  • New public repositories created by your GitHub service accounts (the tpcp-docs exfiltration method)

5. Use Dependency Review and Allow-Lists

Rather than allowing any action from any repository, maintain an allow-list of approved GitHub Actions and their pinned SHAs. Review and update this list on a regular cadence.


What Your Compliance Framework Says About This

SOC 2

Several Trust Services Criteria apply directly:

  • CC7.3 (Detection of unauthorized activities): Organizations must detect unauthorized changes to system components, including CI/CD configurations. Tag poisoning that goes undetected for days signals a detection gap.
  • CC7.4 (Incident response): Requires organizations to respond to identified security incidents, including root cause analysis and complete containment. The Trivy case is a textbook example of incomplete containment leading to a second incident.
  • CC9.2 (Vendor risk management): Organizations must assess and manage risks associated with vendors and third-party components. If your pipeline depends on mutable external references, that's an unmanaged risk.

ISO 27001

Relevant controls from Annex A:

  • A.5.19-A.5.23 (Supplier relationships): Require identifying and managing security risks in the supply chain, including monitoring supplier security performance. A supplier being breached twice in a month is a significant signal.
  • A.8.25 (Secure development lifecycle): Mandates security controls within the development pipeline, including integrity verification of third-party components.
  • A.5.26 (Response to information security incidents): Requires that incident response includes determining the root cause and ensuring complete remediation. "We rotated some tokens" is not sufficient.

Both frameworks share the same expectation: when a security incident occurs, your response must be thorough enough to prevent recurrence. Incomplete containment that leads to a second breach is exactly the kind of finding an auditor will flag.


Safe Versions and Immediate Actions

If you use Trivy in your CI/CD pipelines, take these steps now:

Component Safe Version
trivy 0.69.3
trivy-action 0.35.0
setup-trivy 0.2.6

Immediate actions:

  1. Check your workflow files for any reference to aquasecurity/trivy-action or aquasecurity/setup-trivy. Verify the tag or SHA you're using.
  2. Rotate all pipeline secrets if you ran any version between the first breach (late February) and the fix.
  3. Block the exfiltration domain scan.aquasecurtiy[.]org and IP 45.148.10[.]212 at your network perimeter.
  4. Search for tpcp-docs repositories in your GitHub organization as an indicator of successful exfiltration.
  5. Pin to SHA hashes going forward for all third-party GitHub Actions.

The Bigger Picture

This incident reinforces a trend we've been tracking throughout 2026. From HackerBot-Claw to the Shai-Hulud campaigns, attackers are increasingly targeting the development toolchain itself. CI/CD pipelines run with elevated privileges, process secrets, and are often the least monitored part of the infrastructure.

The Trivy case adds a new dimension: even when you detect and respond to a breach, incomplete containment can hand attackers a second chance. Incident response is not a checkbox. It requires exhaustive credential enumeration, aggressive rotation, and patient monitoring before you can declare an incident closed.

Your CI/CD pipeline is part of your attack surface. Treat it accordingly.

Share this article

Other platforms check the box

We secure the box

Get in touch and learn why hundreds of companies trust Bastion to manage their security and fast-track their compliance.

Get Started