When the security scanner is the attack: the Trivy action compromise
What the March 2026 Trivy compromise changed, what it took from build pipelines, and the checks that tell you whether your own repositories were in range.
Published Last updated
In March 2026 an attacker holding credentials left over from an earlier incident moved 76 of the 77 version tags of trivy-action, a GitHub Action many teams run in CI, onto code that steals secrets. A workflow that used a moved tag during the window handed its secrets over. Check your run history for March 19 and 20 (UTC), then rotate what those jobs could read.
What happened to Trivy?
Trivy is a vulnerability scanner from Aqua Security that teams run in their build pipelines. That position is the reason it was worth attacking: a job that scans your code is trusted with your code and the secrets around it. Microsoft attributes the activity to a group it tracks as TeamPCP. Aqua's advisory (CVE-2026-33634, rated critical, published March 21, 2026) lists three affected components.
| Component | Affected | Window (UTC) | Fixed or unaffected |
|---|---|---|---|
| trivy-action | Versions before 0.35.0 | March 19 about 17:43 to March 20 about 05:40 | 0.35.0 |
| setup-trivy | Versions before 0.2.6 | March 19 about 17:43 to about 21:44 | 0.2.6 |
| trivy binary | v0.69.4 | March 19 18:22 to about 21:42 | v0.69.2, v0.69.3 |
| Docker Hub images | v0.69.5 and v0.69.6 | March 22 15:43 to March 23 about 01:40 | v0.69.3 |
The advisory states the root cause plainly. An earlier incident was answered with a credential rotation that was not atomic, meaning not every credential was revoked at the same moment, so the attacker could keep using a still-valid token to capture newly rotated secrets. Microsoft's write-up adds that the attacker force-pushed malicious commits onto existing tags: 76 of 77 trivy-action tags and all seven setup-trivy tags.
According to the advisory, the injected code read the memory of the GitHub runner process, searched more than 50 file locations for SSH keys, cloud credentials, Kubernetes tokens, Docker configuration and .env files, and, when sending the data out failed, created a public repository named tpcp-docs on the victim's GitHub account to hold it.
Why was a moved tag enough to reach my secrets?
A workflow line such as owner/action@tag tells GitHub to fetch whatever that tag points at on the day the job runs. Your repository does not change when the tag moves, so nothing shows up in a pull request or a diff. GitHub's secure use reference says a tag can be moved or deleted if someone gains access to the repository storing the action, and recommends pinning to a full-length commit SHA instead.
The second half of the problem is what the job can see. GitHub notes that an action can reach the workflow token through the github.token context even when you never pass it in, and the advisory says the injected code read the memory of the runner process itself. A scanner that runs inside your build therefore sits next to everything the build can read.
One check Dependabot does not make
GitHub documents that Dependabot alerts only cover actions that use semantic versions and are not raised for actions pinned to a SHA. If you pin, you take on the job of updating the pin on purpose.
Why does this matter if I build apps rather than security tools?
Because the pipeline that builds an app holds the keys to ship it. If you download your project code or connect your own repository to a Newly project, the CI around it is yours, and it may keep an Expo access token, a store upload credential, an AI provider key and a database service key near that pipeline. Expo's documentation states that anything included in client-side code should be considered public, and that secret-visibility variables exist to give values to build and workflow jobs. The job is the audience, so code that runs in the job is too.
The Trivy compromise also travelled. According to the GitHub advisory for litellm, LiteLLM versions 1.82.7 and 1.82.8 were uploaded to PyPI after an API token was exposed through an exploited Trivy dependency. PyPI's incident report says the same chain led to the telnyx package, and recommends dependency cooldowns, lock files with hashes and Trusted Publishers. The full story of that package is on our LiteLLM page for app builders.
LiteLLM was compromised again in October. At the time of writing on October 21, 2026, Datadog Security Labs stated that no connection between the two compromises had been established, and LiteLLM's own post was marked as an investigation in progress. Treat the two incidents as separate until a primary source says otherwise.
How do I check my own repositories?
None of this needs special tools. You are looking for three things: which actions you reference, how you reference them, and whether any job ran an affected one in the window.
1. List every action you use
In each repository, search the .github/workflows folder for lines that start with uses:. Search the same folder for aquasecurity. Do this for the repositories of every project and every client app, including ones you stopped touching.
2. Read the history for March 19 to 23
Open the Actions tab and filter runs by date. Any run on March 19 or 20 (UTC) that used trivy-action or setup-trivy is in range. Runs on March 22 and 23 matter if a job pulled the Trivy Docker image. The setup step of a run log lists the actions it downloaded. Keep the logs you read, because they are your owner evidence.
3. Look for the fallback repository
Aqua's advisory says to search your GitHub organization for a repository named tpcp-docs. Search each personal account and organization that owns a repository with an affected run. Finding one you did not create means detected. Not finding one leaves you at unknown, because the fallback only ran when the first method failed.
| What you found | State | What to do |
|---|---|---|
| An affected run in the window, or a repository you did not create named tpcp-docs | Detected | Treat every secret that job could read as exposed and rotate it. Keep the run logs. |
| A trivy-action reference that uses a tag, with no run history to read | Unknown | Rotate the secrets that workflow can read. Absence of logs proves nothing. |
| No Trivy reference and no run in the window | Unknown for other actions | This clears Trivy only. Apply the same tag check to every other action you use. |
| Affected run, secrets rotated together, old keys shown refused by the provider | Confirmed by owner evidence | Keep the audit log entries and move on to the changes below. |
What should I rotate, and in what order?
Aqua's advisory is direct: all secrets accessible to affected pipelines must be treated as exposed and rotated. It also names the mistake that let the first incident continue, which is a rotation that was not atomic. Plan the swap before you start so that the old values die together.
- Write the list first: repository and environment secrets, the organization secrets that repository can read, and anything the runner could reach from disk.
- Create every replacement, store it where the workflow reads it, and confirm one clean build.
- Revoke all the old values in one sitting, then read the provider audit logs for use after the revocation.
- Put signing and store credentials, cloud keys and AI provider keys at the top, since those cost money or let someone publish as you.
Our page on rotating secrets after a platform breach has a longer worksheet, and red.run.cloud has a rotation guide for sites. For a related case where the fake action was a "security audit", see red.run.cloud's page on GhostAction, and for dependency worms, the ChainDrop check.
What should I change in my workflows?
| Change | What it limits | Source |
|---|---|---|
| Pin each third-party action to a full commit SHA | A moved tag can no longer change what your job runs | GitHub secure use |
| Enforce SHA pinning in the allowed actions policy | Workflows that use an unpinned action fail | GitHub changelog, August 15, 2025 |
| Set a permissions block with contents: read | What a stolen workflow token can change | GITHUB_TOKEN docs |
| Scope secrets to an environment, not the whole repository | Which jobs can read a given secret | Using secrets |
| Publish packages through a trusted publisher | A long-lived token that outlives the job; PyPI tokens minted this way expire after 15 minutes | PyPI Trusted Publishers |
Update pins deliberately. A weekly pull request that bumps each pin, read by a person, replaces a tag that updates itself. For the Newly-built part of your project, the same rule holds for the dependencies in a downloaded or connected repository.
What a website scan can and cannot tell you here
Red by run.cloud reads a live site from outside. It cannot see a build pipeline, a workflow file or a run log, so it cannot say whether an action ran in your CI. It can show whether the site that pipeline deployed serves keys, .env files or readable source maps, which is a separate question worth asking after any build-secret scare.
Where do you stand?
Everything starts as unknown, because that is what an unchecked item is. Move an item to confirmed only when you hold the evidence listed under it. For the wider app check, see the 15-minute check for an AI-built app.
Your pipeline check
- Detected: You found the problem.
- Unknown: Not checked yet, or the check could not tell.
- Confirmed by owner evidence: You checked and kept the proof.
Your answers stay in this browser tab. Nothing is saved or sent.
Frequently asked questions
Was the Trivy scanner itself broken, or only the GitHub Action?
Three things were affected. The Trivy binary release v0.69.4, the trivy-action GitHub Action and the setup-trivy GitHub Action carried the credential-stealing code, each for a different window on March 19 and 20, 2026 (UTC). Docker Hub images v0.69.5 and v0.69.6 were affected on March 22 and 23. Aqua Security's advisory lists the exact windows and the fixed versions.
I never used Trivy. Does any of this apply to me?
The same weakness applies to any third-party action you reference by a tag or branch name, because the owner of that repository, or anyone holding its credentials, can move the tag. The Trivy case is the clearest recent example. The checks in this article work for every action in your workflows.
Does a clean scan from red.run.cloud show my CI is unaffected?
No. A scan reads what your live site shows an outsider. A build pipeline answers no public request, so a scan cannot see which actions your workflows run or what they read. Only your repository, your run history and your provider's audit log can settle that.
Is pinning to a commit SHA enough?
It stops a moved tag from changing what your workflow runs, which is the failure in this incident. It does not review the code you pinned, and it does not limit what that code can read. Pair it with a read-only token, narrow secrets and a plan to update pins on purpose.
Do I need to rotate every secret in my repository?
Rotate every secret that a job running an affected action could read, which is usually every secret available to that workflow. Aqua Security's advisory says to treat all secrets accessible to affected pipelines as exposed. Secrets in other repositories that never ran the action are lower priority, but check their run history first.
Does this affect the app that people install on their phones?
The compromise targeted build pipelines and the machines that run them. An app built on a pipeline that ran an affected action could have been built next to stolen signing or store credentials, so check those credentials. Code on the phone is a separate question that your own build logs and repository history answer.
Sources
Checked October 24, 2026. The hub for this section is newly.app/security.
- Trivy Supply Chain Attack advisory, CVE-2026-33634 (GHSA-69fq-xp46-6x23), Aqua Security on GitHub, March 21, 2026
- Detecting, investigating, and defending against the Trivy supply chain compromise, Microsoft Security Blog, March 24, 2026
- Security update, March 2026, LiteLLM docs
- GHSA-5mg7-485q-xm76, litellm 1.82.7 and 1.82.8, GitHub Advisory Database, March 25, 2026
- Incident report: LiteLLM and Telnyx supply chain attack, PyPI blog, April 2, 2026
- LiteLLM compromised on PyPI and Docker, Datadog Security Labs, October 21, 2026
- Security incident, October 21, 2026, LiteLLM docs
- Secure use reference, GitHub Docs
- Controlling permissions for GITHUB_TOKEN, GitHub Docs
- Using secrets in GitHub Actions, GitHub Docs
- GitHub Actions policy now supports blocking and SHA pinning actions, GitHub Changelog, August 15, 2025
- Trusted Publishers, PyPI docs
- Environment variables in EAS, Expo docs
Continue Learning
LiteLLM was compromised twice in 2026 →
How the March incident that started with Trivy differs from the October one.
Supply-chain attacks on AI and LLM tooling →
The wider pattern behind incidents like this one, and how to defend.
Rotate secrets after a platform breach →
A calm order of operations when a tool you rely on is breached.
