


















|
Incident |
Supply chain attack on aquasecurity/trivy-action and the Trivy binary, March 2026 |
|
Scope |
76 of 77 trivy-action version tags rewritten. Any pipeline referencing a tag before 0.35.0 was potentially compromised. |
|
Attack method |
Compromised credentials used to force-push malicious code into GitHub Action tags. The payload ran silently before the legitimate scanner and exfiltrated CI/CD secrets. |
|
Data at risk |
AWS credentials, GitHub tokens, Kubernetes service account tokens, SSH keys, Docker registry passwords, database credentials, and cryptocurrency wallet keys |
|
Safe versions |
trivy-action 0.35.0 • setup-trivy v0.2.6 • Trivy binary v0.69.3 |
|
Immediate action |
Check workflows for any trivy-action tag other than 0.35.0. Rotate all pipeline secrets. Block scan.aquasecurtiy[.]org and IP 45.148.10.212 at the network level. Check your GitHub account for an unexpected repository named tpcp-docs. |
|
Key takeaway |
This attack exploited mutable Git tags — a risk that applies to every third-party GitHub Action you reference by tag. Pin your actions to full commit SHAs and treat your CI/CD runners as production infrastructure. |
Trivy is one of the most trusted open-source security scanners in the DevOps world. Maintained by Aqua Security, it is used by thousands of engineering teams to scan container images, filesystems, and Kubernetes clusters for known vulnerabilities. In March 2026, attackers compromised Trivy's own GitHub Actions. They rewrote 76 of 77 version tags to deliver a credential-stealing payload directly into CI/CD pipelines around the world.
This was not a theoretical risk. It was a real, active attack that ran silently inside GitHub Actions runners, collected secrets from the environment, encrypted them, and sent them to an attacker-controlled server. Every team that ran a Trivy scan during the window of compromise was potentially exposed.
This article explains exactly what happened, how the attack worked at a technical level, what data was at risk, what you should do right now, and how to prevent this class of attack from reaching your pipelines in the future. The analysis draws on reporting from The Hacker News, CrowdStrike's engineering team, Socket Security, and Aqua Security's own public disclosure.
Trivy is an open-source vulnerability scanner maintained by Aqua Security. It scans container images, code repositories, Infrastructure-as-Code files, and Kubernetes clusters for known CVEs (Common Vulnerabilities and Exposures). Many teams integrate it into GitHub Actions using the official action, aquasecurity/trivy-action, or set it up through aquasecurity/setup-trivy. Whether you use Trivy today or not, this attack matters to you — because the mechanism it exploited, trusted GitHub Actions running inside your pipeline with full access to your secrets, applies to any third-party action you reference by tag.
The trust teams place in Trivy is exactly what made this attack so effective. When your CI/CD pipeline runs aquasecurity/trivy-action, it runs code directly on your GitHub Actions runner. That runner has access to every secret you have configured in your repository, from AWS credentials to Kubernetes service account tokens. As CrowdStrike's engineering team noted in their post-compromise analysis: if an action's code is modified, whether by its maintainers or by someone who gained write access, every pipeline that references it will trust and execute the new code on its next run, with full access to that pipeline's secrets, credentials, and infrastructure.
To understand this incident clearly, it helps to think of it as two separate attacks with two separate victim groups. The first attack targeted Aqua Security internally. The second attack targeted the thousands of organisations that trusted Trivy's release tags in their own pipelines. The only reason the second attack was possible is because the first one was not fully contained.

Act One: Aqua Security's own CI is compromised. In late February 2026, an automated bot called hackerbot-claw scanned public GitHub repositories for a well-known misconfiguration in GitHub Actions workflows. It found one inside Aqua Security's own aquasecurity/trivy repository. The misconfiguration involved a pull_request_target workflow — a GitHub Actions trigger that runs in the context of the base repository and carries write access to that repository's secrets, even when triggered by a pull request from a complete stranger on the internet. Critically, this workflow also checked out code from the incoming pull request and executed it, which meant an external contributor's code was running inside a privileged environment with access to Aqua Security's internal tokens. The attacker opened a pull request against the Trivy repository itself, triggered that workflow, and stole a Personal Access Token belonging to aqua-bot — a service account with write access across 33 workflows in the Aqua Security GitHub organisation. This had nothing to do with your pipeline or your workflows. This was a break-in to Aqua Security's internal CI infrastructure.
Act Two: downstream users are hit through tag poisoning. Aqua Security caught the first attack, rotated their secrets and tokens, and believed the problem was contained. As their VP of open source Itay Shakury later acknowledged, however, the rotation was not atomic — meaning credentials were rotated one by one over time rather than all at once in a single coordinated action. This gave the attacker a window to capture freshly rotated tokens before the old ones were fully invalidated. Using those surviving credentials, the attacker force-pushed 76 of 77 version tags in the aquasecurity/trivy-action repository, rewriting them to point at commits containing a malicious payload. This is the attack that affected downstream organisations. Every team that referenced a trivy-action tag other than 0.35.0 in their CI pipeline was now running malicious code, regardless of whether their own workflows were correctly configured. They were not compromised because of anything they did wrong — they were compromised because they trusted a release tag that had been silently rewritten.
The most dangerous words in incident response are "we rotated our secrets." Rotation means nothing if the attacker captured a new token before the old one was invalidated, or if not every credential surface was covered in a single coordinated action.
CrowdStrike confirmed the scope of the tag poisoning by independently downloading and scanning every release tag. Force-pushing a tag means rewriting it so it points to a different commit than it originally did — the tag name stays the same, the release page looks identical, but the code it delivers has been replaced. The only clean tag was 0.35.0. Every other release from 0.0.1 through 0.34.2 served malicious code.
A key evasion detail from CrowdStrike's analysis: the attacker forged the malicious commits' metadata. The author name, commit message, and timestamps all mirrored a legitimate prior commit. Git allows setting arbitrary author and committer dates via environment variables, so commit metadata alone cannot be trusted when investigating a compromise.
Separately from the tag poisoning of the GitHub Actions, the attackers also published a malicious version of the Trivy binary itself: version 0.69.4. This version was flagged by security researcher Paul McCarty and has since been removed from the repository. Version 0.69.4 started the legitimate Trivy process as normal, so nothing looked broken, and simultaneously executed the malicious code alongside it. This is a deliberate attacker technique: keep the expected behavior running so no alerts are triggered while malicious activity runs in the background.
Before getting into the technical stages, it is worth being precise about the moment of compromise for a downstream organisation, because this is the part the article so far has only implied. When your GitHub Actions workflow contains a line like uses: aquasecurity/[email protected], GitHub resolves that tag name to whatever commit it currently points to, downloads that code onto your runner, and executes it. There is no warning, no diff, no notification that the tag has been rewritten since the last time it ran. Your pipeline simply trusts the tag. So the moment of compromise was not when Aqua Security was breached, and it was not when the tags were rewritten. It was the next time your workflow ran after the poisoning — a normal-looking Trivy scan step that started with your secrets already injected into the runner environment, ran the malicious code first, stole everything it could find, and then handed off to the legitimate scanner so your pipeline showed a green check mark. From your perspective, nothing looked wrong.
The payload embedded in the compromised tags was a multi-stage credential stealer. CrowdStrike's engineering team identified approximately 105 lines of malicious code prepended to the legitimate entrypoint.sh before the real Trivy scanner logic. The stealer ran first, then handed off to the real tool so the workflow completed normally and operators saw a green check mark.
A critical detail is that the attack behaved differently depending on whether it was running on a GitHub-hosted runner or a self-hosted runner, because the attack surface is different in each environment.

The script began by enumerating the process IDs of GitHub Actions runner processes, specifically Runner.Worker, Runner.Listener, runsvc, and run.sh. It then read their /proc/{PID}/environ files, filtering for environment variables whose names contained "env" or "ssh". This gave the attacker a map of what credentials were present before deciding which harvesting path to follow.
On GitHub-hosted Linux runners, a Base64-encoded Python script was decoded and executed. It located the Runner.Worker process, read its memory maps via /proc/{PID}/maps, and scraped raw process memory via /proc/{PID}/mem to extract GitHub Actions secrets directly. It specifically looked for JSON structures matching the pattern "name":{"value":"...","isSecret":true}, which is how GitHub Actions stores secrets internally in the runner process.
On self-hosted runners, the attack took a broader approach. A separate script performed comprehensive filesystem credential harvesting, targeting SSH private keys and configs, cloud provider credentials for AWS, Google Cloud, and Azure, Kubernetes configs and service account tokens, Docker registry credentials, database credentials for MySQL, PostgreSQL, MongoDB, and Redis, CI/CD configuration files for GitLab CI, Travis, Jenkins, and Drone, Infrastructure-as-Code secrets from Terraform state files, Ansible, and Helm, TLS and SSL private keys, .env files, API keys, cryptocurrency wallet files including Solana validator keypairs, and system files including shell history.
Self-hosted runners are a larger target because they are persistent machines that accumulate credentials over time, unlike GitHub-hosted runners which are ephemeral and destroyed after each workflow run.
Collected data was not sent in plaintext. The stealer encrypted the bundle using AES-256-CBC with a randomly generated session key, and then wrapped that session key with a hardcoded 4096-bit RSA public key. The encrypted bundle was packaged as tpcp.tar.gz. This two-layer encryption means that even if network traffic is intercepted, only the attacker holding the corresponding RSA private key can decrypt the stolen data.
The primary exfiltration channel was an HTTPS POST to scan.aquasecurtiy[.]org — note the deliberate misspelling of "Aqua Security". The IP address behind this domain was 45.148.10.212. Both should be blocked at the network or DNS level immediately if you were running Trivy during the compromise window.
If the primary channel returned a non-2XX response, the stealer fell back to exfiltrating through GitHub itself. Using the captured INPUT_GITHUB_PAT environment variable, it created a public repository named tpcp-docs in the victim's own GitHub account, created a timestamped release, and uploaded the encrypted bundle as a release asset. This fallback uses GitHub's own API and requires no direct connection to attacker infrastructure, making it harder to catch with outbound traffic monitoring alone. If you find a repository named tpcp-docs in your GitHub account that you did not create, this is a strong indicator that exfiltration succeeded.
All temporary files were removed. The script then handed off to the legitimate Trivy scanner, which ran normally and produced the expected vulnerability report. From an operator reviewing workflow logs, the step appeared to have completed successfully with nothing to alert on.
The compromised Trivy binary 0.69.4 went further. When executed on a developer's local machine, it dropped a Python script to ~/.config/sysmon.py. After an initial five-minute sleep, designed to outlast automated sandbox analysis timeouts, it entered a polling loop contacting a command-and-control server approximately every 50 minutes.
What makes this C2 infrastructure notable is where it was hosted: on the Internet Computer (ICP) blockchain, making it resistant to traditional domain takedowns since there is no registrar to contact or DNS record to remove. On each polling cycle, the loader fetched a URL from the C2, and if the URL was new, downloaded a binary to /tmp/pglog, a filename chosen to mimic PostgreSQL logging, then executed it as a detached background process with all output suppressed. This allowed the attacker to rotate payloads at will simply by updating the C2.
A Git tag is simply a pointer from a human-readable name to a specific commit hash. When you write aquasecurity/[email protected] in a workflow file, GitHub resolves that tag name to whatever commit hash it currently points to, downloads that content, and executes it. The tag name is not cryptographically bound to any particular content.
CrowdStrike confirmed this by comparing what the 0.24.0 tag delivered during the attack against its parent commit. The tag resolved to commit e0198fd2b6e1679e36d32933941182d9afa82f6f, which contained an entrypoint.sh of 17,592 bytes. The legitimate version of that same file on the master branch was 2,855 bytes. The attacker simply ran:
# Force-push a tag to point at a malicious commit
# The release page on GitHub showed the same name, dates, and description as before
git tag -f 0.24.0 <malicious-commit-sha>
git push -f origin refs/tags/0.24.0
# The malicious commit also had forged metadata:
# Author name, commit message, and timestamp copied from a legitimate prior commit
# Git allows arbitrary date overrides via GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
The release page on GitHub did not change. The tag name, the published date, the description — everything looked identical to before. The only way to detect the change was to compare the actual commit SHA that the tag resolved to against what it historically resolved to, which almost no team does in practice.
Here is a standard GitHub Actions workflow that builds a Docker image and runs a Trivy scan before pushing to a registry. Tag 0.24.0 was confirmed by CrowdStrike as compromised, resolving to the malicious commit e0198fd during the attack window. Any tag other than 0.35.0 should be treated as potentially rewritten.
# .github/workflows/build-and-scan.yml
name: Build and Security Scan
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:latest .
# Tag 0.24.0 confirmed compromised by CrowdStrike (malicious commit e0198fd)
# Every tag before 0.35.0 was rewritten — this is not a single named bad version
- name: Run Trivy vulnerability scan
uses: aquasecurity/[email protected] # <-- tag was poisoned
with:
image-ref: 'myapp:latest'
format: 'table'
exit-code: '1'
severity: 'CRITICAL,HIGH'
- name: Push to registry
run: docker push myapp:latest
When that Trivy scan step executed on a GitHub-hosted runner, the malicious entrypoint.sh ran first. It located the Runner.Worker process, read its process memory to extract secrets, and collected any credentials in the runner environment and filesystem. These would typically include values like the following.
# Secrets injected into the runner environment by GitHub Actions
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
DOCKER_REGISTRY_PASSWORD=myRegistryPass123
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
DB_CONNECTION_STRING=postgresql://user:[email protected]:5432/prod
KUBECONFIG=/home/runner/.kube/config
# The stealer encrypted all of this with AES-256-CBC + RSA-4096,
# packaged it as tpcp.tar.gz, and POSTed it to scan.aquasecurtiy[.]org
# If that failed, it staged the encrypted bundle in a public GitHub repo: tpcp-docs
The Trivy scan then completed successfully and produced a normal vulnerability report. You saw a green check mark. The attacker had your AWS keys, your Docker registry password, your GitHub token, and potentially your Kubernetes cluster credentials. With AWS keys, an attacker can enumerate your infrastructure, read data from S3 buckets, extract secrets from Secrets Manager, and pivot to other services. With a Kubernetes service account token, they can list and exec into pods, read ConfigMaps and Secrets, and potentially gain cluster admin access depending on your RBAC configuration.
If there is any chance your pipelines ran a compromised version of Trivy, treat every secret that was available to those pipelines as already compromised. Here is the response plan in order of priority.
Every tag of trivy-action other than 0.35.0 was confirmed compromised by CrowdStrike's independent analysis. Check your workflow files across all repositories.
# Search all your workflow files for Trivy references
grep -r 'trivy' .github/workflows/
# SAFE versions confirmed by Aqua Security
aquasecurity/trivy v0.69.3 or later
aquasecurity/trivy-action 0.35.0 only (every other tag was rewritten)
aquasecurity/setup-trivy v0.2.6 or later
# Also check your GitHub account for the fallback exfiltration repository
# If this exists and you did not create it, exfiltration succeeded:
# Repository name: tpcp-docs
Rotation means generating entirely new credentials, not just changing passwords on the same credential. The following categories were all targeted by the stealer and should be rotated if they were available to any affected pipeline.
Block the attacker's domain and IP address at your network or DNS level. Also block the blockchain-hosted C2 used by the Trivy binary persistence module.
# Block at your firewall or DNS sinkhole
# Primary exfiltration domain (note the deliberate misspelling)
Domain: scan.aquasecurtiy[.]org
IP: 45.148.10.212
# Blockchain-hosted C2 used by the Trivy binary persistence module
# Traditional domain takedown does not work against ICP-hosted endpoints
C2: hxxps://tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io
# Example: block the exfiltration IP using iptables
sudo iptables -A OUTPUT -d 45.148.10.212 -j DROP
# Check outbound proxy logs for past connections to any of these endpoints
Update all workflow files to reference the confirmed safe versions, then immediately pin those references to full commit SHAs. The SHA pinning step is not optional — the next section explains why.
# BEFORE: Mutable tag — can be silently repointed to malicious code
uses: aquasecurity/[email protected]
# STEP 1: Update to the safe version
uses: aquasecurity/[email protected]
# STEP 2 (strongly recommended): Pin to the full commit SHA
# Get the SHA by running:
# git ls-remote https://github.com/aquasecurity/trivy-action refs/tags/0.35.0
# Then use the resolved SHA, not the tag itself
uses: aquasecurity/trivy-action@<40-character-sha> # pinned to 0.35.0
The Trivy incident is a textbook supply chain attack. The target was not your application but the tools and automation that build it. These are the controls that would have contained or prevented the impact.
This is the single most effective control against tag poisoning. A commit SHA is derived cryptographically from the content of the commit itself. You cannot change the content of a commit without changing its SHA. When you reference a GitHub Action by its full 40-character SHA, you are guaranteed to run exactly that code regardless of what happens to the tag. An attacker who rewrites a tag cannot affect a workflow pinned to a SHA, because the SHA and the tag are now independent references.
# SHA pinning makes tag poisoning irrelevant
# Get the SHA for a tag:
git ls-remote https://github.com/aquasecurity/trivy-action refs/tags/0.35.0
# Use the resolved SHA in your workflow:
uses: aquasecurity/trivy-action@<resolved-sha> # pinned to 0.35.0
# Tools that can automate SHA pinning across all your workflows:
# - StepSecurity Harden-Runner
# - pin-github-action CLI
# - Dependabot (can pin and auto-update SHAs)
The first Trivy breach began because a pull_request_target workflow was configured in a way that gave external contributors access to repository secrets. Unlike the standard pull_request trigger, pull_request_target runs in the context of the base branch and has write access to secrets. Any public repository using this trigger allows external pull requests to invoke workflows with elevated permissions. Search your workflow files for pull_request_target and review whether those workflows also run checkout steps referencing the pull request head.
OpenID Connect (OIDC) allows GitHub Actions workflows to authenticate with cloud providers like AWS without storing long-lived access keys as repository secrets. Instead of a static AWS_ACCESS_KEY_ID that an infostealer can capture and use indefinitely, the workflow requests a short-lived token that expires after the workflow run. A stolen OIDC token is useless within minutes.
# OIDC-based AWS authentication: no long-lived keys stored as secrets
# deliver malicious code into this workflow.
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 # v5.1.0
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
aws-region: eu-west-1
# GitHub generates a short-lived OIDC token for this workflow run only
# A stolen token from a compromised action would expire almost immediately
CrowdStrike detected this attack because their Falcon sensor was running on affected runners and flagged script execution behaviors inconsistent with CI/CD activity, specifically credential collection, encrypted data staging, and outbound exfiltration. Most teams treat their CI/CD runners as disposable infrastructure with far less monitoring than a production server. This attack demonstrates that a runner is production infrastructure: it holds your secrets and has network access to your internal systems. Tools like Falco, StepSecurity's Harden-Runner, or a commercial EDR deployed on runners can detect the behavioral patterns this attack relied on.
This attack exfiltrated data over HTTPS to an external domain. A network policy restricting outbound connections from CI/CD runners to a known allowlist would have blocked the primary exfiltration channel entirely. Self-hosted runners can be placed behind a firewall or proxy that enforces outbound rules. Blocking connections to anything other than your package registries, GitHub itself, and your internal infrastructure is a strong control.
The Aqua Security team's incomplete rotation was not unusual. Rotating secrets across an entire organization under time pressure is genuinely difficult. The teams that do it effectively are the ones who have documented and practiced the process before an incident. A rotation runbook should map every credential to the systems that depend on it, define who owns the rotation for each credential type, specify how to verify that old credentials are fully revoked, and set a target time window for completing rotation end to end.
The Trivy incident was publicly disclosed quickly. Teams subscribed to Aqua Security's GitHub release notifications or monitoring the GitHub advisory database would have had actionable information within hours. For any tool running in your CI/CD pipeline with access to secrets, watching its repository for security announcements is worth the noise.
The Trivy attack fits a pattern that has been building for several years. The XZ Utils backdoor, the Codecov breach, the SolarWinds incident, and now Trivy all share the same fundamental structure: attackers gaining access to a trusted tool and using that trust as the delivery mechanism for malicious code. The target is not a vulnerability in the tool itself but a compromise of the humans, credentials, or processes that maintain it.
The most dangerous tools are the ones you trust the most. A scanner that protects you from vulnerabilities is also a tool that runs code with access to your secrets on every single pipeline run. Trust in open-source software is not binary, and it cannot be set-and-forget.
What makes the Trivy incident particularly instructive is the cascading failure. The first attack succeeded because of an insecure workflow configuration. The response was incomplete because secret rotation was not atomic. The second attack succeeded because of that gap. After the Trivy compromise, researchers found that stolen credentials were then used to push malicious versions of several npm packages, spreading the attack further into the ecosystem.
There is no such thing as a fully trusted tool. Every external dependency you bring into your pipeline is a potential entry point. The question is not whether to trust open-source tools, you have to use them, but how to structure that trust so that a compromise of any single tool cannot cascade into a full infrastructure breach. SHA pinning, OIDC authentication, least-privilege secrets, and runtime monitoring on runners are not optional hardening steps. After this incident, they are the baseline.
The Trivy compromise did not happen in a vacuum. It is part of a clear and accelerating pattern of attackers targeting GitHub Actions as a delivery mechanism for credential theft. The table below summarises the most significant confirmed incidents. In each case the attack method is essentially the same as what happened to Trivy: a trusted action is compromised, version tags are rewritten to point at malicious code, and the payload harvests secrets from CI/CD runners. The difference between incidents is largely a matter of scale and how secrets were exfiltrated.
|
Repository / Action |
Date |
CVE |
What happened |
Impact |
|
reviewdog/action-setup |
Mar 11, 2025 |
CVE-2025-30154 |
Attacker exploited an automated contributor invite process to gain write access, then force-pushed the v1 tag to a malicious commit. Payload dumped runner secrets to workflow logs. |
Root cause of the cascading tj-actions attack. 6 downstream reviewdog actions also compromised. |
|
tj-actions/changed-files |
Mar 10–14, 2025 |
CVE-2025-30066 |
All version tags rewritten to point at a malicious commit. Payload printed CI/CD secrets to workflow logs as double-encoded base64. Attacker impersonated the Renovate bot to disguise the commit. |
Over 23,000 repositories affected. Initially targeted Coinbase, then expanded broadly. AWS keys, GitHub PATs, npm tokens, and RSA keys exposed in public workflow logs. |
|
spotbugs/sonar-findbugs |
Nov 2024 |
— |
A maintainer added a PAT to a workflow for legitimate reasons. Attacker submitted a malicious pull request exploiting a pull_request_target trigger to steal that token. The stolen credentials were later used as the entry point for the tj-actions cascade. |
Origin of the entire March 2025 cascade. Attack went undetected for over three months. |
Beyond the incidents in the table above, the HackerBot-Claw campaign in February 2026 is worth singling out because it demonstrates something new: fully automated, AI-driven exploitation at scale. The bot claimed to have scanned over 47,000 public repositories in one week, looking for misconfigured pull_request_target workflows, and successfully exploited seven of them using five different attack techniques, each one tailored to the specific workflow configuration of the target. The repositories hit included microsoft/ai-discovery-agent (arbitrary code execution via CI workflow), DataDog/datadog-iac-scanner (filename injection), avelino/awesome-go (GitHub token exfiltration from a 140,000-star repository), project-akri/akri from the CNCF, RustPython/RustPython, and aquasecurity/trivy, which suffered the worst outcome of the group. The only target that came through intact was ambient-code/platform, where Claude Code was integrated as a CI code reviewer and detected the attack as a prompt injection attempt, refusing to follow the malicious instructions.
A few patterns stand out across all of these incidents that are worth internalising. First, the pull_request_target trigger appears repeatedly as the entry point, in the spotbugs case that started the 2025 cascade and in the first Trivy breach. It is a legitimate feature that is genuinely useful, but any public repository using it should be treated as a high-risk surface until it is audited. Second, mutable version tags are the common mechanism in every single case. Every attack reused the same technique: force-push a tag, point it at malicious code, let normal workflow execution do the rest. Third, the attacks are connected. The November 2024 spotbugs breach fed into the March 2025 reviewdog breach, which fed into the tj-actions breach, which exposed Coinbase credentials that were then potentially available to fund further attacks. The Trivy March 2026 breach was itself a second strike enabled by incomplete remediation of an earlier compromise. Supply chain attacks are not one-off events — they cascade.
The Trivy supply chain attack turned a security tool into a credential harvester. Attackers rewrote 76 of 77 version tags to deliver a multi-stage infostealer that collected cloud credentials, Kubernetes tokens, SSH keys, and database passwords, encrypted them with AES-256-CBC and RSA-4096, and exfiltrated them to infrastructure designed to evade detection. The persistence mechanism on the Trivy binary used a blockchain-hosted C2, making it resistant to traditional takedown. The forged commit metadata made the malicious commits look identical to legitimate ones.
If you use Trivy, check your workflow files right now. Update to safe versions. Rotate any secrets that were available to affected pipelines. Check your GitHub account for a repository named tpcp-docs that you did not create. And if you have not already done so, start pinning your GitHub Actions to full commit SHAs.
The broader lesson is that your security posture is only as strong as the trust you extend to your tools, and that trust must be earned continuously, not assumed permanently. Build systems that limit what any single compromised component can reach, keep credentials short-lived where possible, and maintain a rotation plan you can execute under pressure.
If you suspect your pipeline ran a compromised version of Trivy, the table below gives you the specific artifacts to hunt for. The domain and IP address are what the malware used as its primary exfiltration channel — check your outbound proxy or firewall logs for any connections to either of them during the period you were running trivy-action. T
he blockchain C2 address is the command-and-control server used by the persistence module in the Trivy 0.69.4 binary on developer machines. It cannot be taken down through normal registrar or DNS channels, so blocking it at the network level is the only reliable control.
The malicious commit SHA lets you verify whether a specific tag in your pipeline history actually pointed at the backdoored code — you can compare it against what your workflow resolved at runtime.
The two malicious files are what the Trivy binary drops when it detects it is running on a developer machine rather than in CI; if either path exists on a machine that ran Trivy 0.69.4, treat that machine as fully compromised. Finally, if the fallback exfiltration channel ran successfully, a repository named tpcp-docs will have been created in your own GitHub account with the stolen data staged as a release asset inside it.
|
Type |
Indicator |
|
Domain |
scan.aquasecurtiy[.]org (note misspelling) |
|
IP Address |
45.148.10.212 |
|
C2 (blockchain) |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io |
|
Malicious commit |
e0198fd2b6e1679e36d32933941182d9afa82f6f (trivy-action) |
|
Malicious file |
~/.config/sysmon.py (trivy binary persistence) |
|
Malicious file |
/tmp/pglog (payload dropped by sysmon.py) |
|
GitHub repo |
tpcp-docs (fallback exfiltration staging) |
|
Archive |
tpcp.tar.gz (encrypted credential bundle) |
|
Package |
Safe Version |
Notes |
|
aquasecurity/trivy |
v0.69.3 or later |
v0.69.4 was confirmed malicious. Remove it from all machines. |
|
aquasecurity/trivy-action |
0.35.0 only |
All 76 other tags were rewritten. Pin to SHA after updating. |
|
aquasecurity/setup-trivy |
v0.2.6 or later |
7 tags were force-pushed. Update and pin to SHA. |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。