Important update, 20 March 2026 This post covers the second episode of the Trivy incident. My first article described the initial compromise of late February and the disappearance of the GitHub repository. New public evidence published on 20 March 2026 shows that a new twist took place on 19 March, with the publication of a compromised
v0.69.4release. The external investigation is still ongoing, so some points remain to be confirmed.
Important update, 23 March 2026 This post initially covered the second episode of the Trivy incident around the compromised
v0.69.4release of 19 March. New analyses published by Socket and StepSecurity now indicate that Docker Hub images0.69.5and0.69.6, pushed on 22 March without a matching GitHub release, also contain indicators of compromise. Thelatesttag was pointing to0.69.6at the time. As I write this update, this point is solidly documented by external researchers, but I keep this extended scope clearly separate from the elements officially confirmed by the GitHub advisory and the Aqua communication, which remain centred onv0.69.4,trivy-actionandsetup-trivy.
This blog is written in French, and the linked guides are in French. I kept them because they are the underlying references, but be aware of the language before you follow them.
What happened on 19 March?
On 19 March 2026, a Trivy release v0.69.4 was published with malicious
code embedded, then propagated through several distribution channels. I
thought the Trivy story was behind us: repository restored, public incident,
first fixes on the GitHub Actions workflows. But the new analyses
published by BoostSecurity show a far more worrying scenario.
BoostSecurity considers it highly probable that the same PAT
stolen in late February was reused. BoostSecurity also states that its
investigation was published early to help community threat hunting, and
that some details still need to be consolidated.
In other words, we are no longer talking only about a wiped repository or deleted releases. We are talking about a poisoned release that travelled through the project's normal distribution channels.
Why is this second incident more serious?
The first episode was destruction; this one is infiltration, an attacker managing to publish a malicious artifact as if it were legitimate. During the first episode, the visible effect was brutal: releases deleted, repository replaced, installers broken. It was spectacular, but it remained mostly a destruction incident. In this second act, the risk is different.
BoostSecurity indicates that the v0.69.4 release was distributed through
GitHub Releases, Homebrew, AWS ECR, Docker Hub, GHCR, and
that a large share of the trivy-action tags were also rewritten to serve
malicious code. If this analysis is fully confirmed, we are facing a
compromise of the distribution chain, not just of the source repository.
Where did the attack most likely start?
The probable starting point is a stolen PAT that was never revoked. In
its analysis, BoostSecurity goes back to the initial compromise of
February: a GitHub Actions secret named ORG_REPO_TOKEN, tied to the
aqua-bot service account, was exfiltrated through a Pwn Request attack.
According to Boost, this token had a very broad scope, being used in at
least 33 workflows of the organisation, which made it an extremely dangerous
single point of failure. BoostSecurity also considers it very likely
that this PAT was not rotated immediately after the initial incident.
This hypothesis fits the publicly observed sequence of events: the aqua-bot
service account appears in the actions related to the publication of
v0.69.4, to the deletion of a v0.70.0 tag, and to operations on the
repositories of the Trivy ecosystem.
How was the poisoned release built to look legitimate?
The attacker prepared two impostor commits, detached from any branch,
crafted to blend into an ordinary diff. One targeted actions/checkout, the
other aquasecurity/trivy. These commits used credible authors, plausible
messages and deliberately discreet modifications to disappear into the noise
of a routine change.
The Trivy-side commit introduced three key changes:
- a pinning of
actions/checkoutto a malicious but credible SHA; - the addition of
--skip=validateto GoReleaser; - cosmetic changes in the YAML to dilute the real signal in the diff.
This is exactly the kind of detail that should make us think: in principle, pinning an action by SHA is a good practice. But if the SHA itself points to a malicious commit, that good practice becomes a false sense of security.
What role did the typosquatted domain play?
BoostSecurity identified a telling command and control domain:
scan.aquasecurtiy.org, a typosquat of the Aqua Security domain with swapped
letters in security. According to the analysis, the fake
actions/checkout downloaded from this domain several Go files meant to
replace components of the Trivy binary, plus a .golangci.yaml file to
silence the linter alerts on the injected code.
Still according to Boost, the downloaded files make the intent clear: a modified entry point, a persistent daemon and Unix/Windows specific code. Building on Socket's analysis, BoostSecurity also links this payload to capabilities for in-memory secret theft, collection of SSH keys, cloud credentials and Kubernetes tokens.
What is the timeline of 19 March?
The sequence published by BoostSecurity is particularly instructive.
At 17:43 UTC, the v0.69.4 tag was pushed to the poisoned commit, which
triggered the documentation and release workflows. Eight minutes later, at
17:51 UTC, aqua-bot deleted a v0.70.0 tag, which suggests a first
attempt abandoned for being too visible. The attacker then apparently came
back to v0.69.4 to blend better into the existing version series.
BoostSecurity then indicates that the release pipeline executed a chain that is classic but dangerous in this context: login to the registries, checkout of the code, multi-platform build with GoReleaser, publication of the images and of the GitHub Release. The publication of the compromised release reportedly happened at 18:25:54 UTC.
How far did the downstream propagation go?
This is where the incident truly changes dimension: the poisoned release rode the automated distribution channels.
Homebrew
BoostSecurity documents that at 18:05 UTC, a Homebrew bot opened an
automatic PR to integrate trivy 0.69.4 into homebrew-core. The PR was
merged at 19:35:58 UTC, which made compromised bottles available on
several platforms before an emergency downgrade to 0.69.3 was triggered.
StepSecurity also confirms this emergency rollback to v0.69.3.
setup-trivy
BoostSecurity indicates that between 22:06 and 22:08 UTC, aqua-bot
published a burst of releases on aquasecurity/setup-trivy, rewriting the
version history from v0.1.0 to v0.2.5. BoostSecurity also notes that
no workflow was triggered that day on this repository, which suggests
publications made directly through the GitHub API. Later, the incident
response deleted every tag except the clean v0.2.6, which broke the
pipelines pinned to the older versions. StepSecurity confirms that only
v0.2.6 was kept as a healthy tag.
trivy-action
BoostSecurity writes that 75 tags out of 76 of
aquasecurity/trivy-action were force-pushed to malicious code, with only
@0.35.0 remaining intact. StepSecurity, more cautious in its wording,
indicates that trivy-action was still compromised at the time of its
publication. If accurate, the potential impact is enormous, because this
action is widely referenced in GitHub workflows.
Image registries
BoostSecurity states that GoReleaser pushed multi-architecture
images to public ECR, Docker Hub and GHCR under the 0.69.4
tag. Here again, if this chain is confirmed end to end, the problem goes far
beyond the single GitHub Release binary.
What changed with Docker Hub 0.69.5, 0.69.6 and latest?
On 22 March 2026, Socket reported that new images aquasec/trivy:0.69.5
and aquasec/trivy:0.69.6 had been pushed to Docker Hub without any matching
GitHub release or source tag. According to their analysis, these images
contain the same indicators of compromise as v0.69.4, notably the
reference to the typosquatted domain scan.aquasecurtiy.org, along with
artifacts such as payload.enc, tpcp.tar.gz and a fallback reference to
tpcp-docs.
StepSecurity published an update on 23 March pointing in the same
direction. Their team says it extracted the trivy binary from the
aquasec/trivy:0.69.5 and aquasec/trivy:0.69.6 images and found the string
https://scan.aquasecurtiy.org through a strings analysis.
The most disturbing point is that the latest tag was then pointing to
0.69.6. In other words, even pipelines that did not explicitly request
0.69.5 or 0.69.6 could pull a compromised image through a simple
latest.
I therefore now treat 0.69.4, 0.69.5, 0.69.6 and latest on Docker
Hub as untrustworthy during that window, even though the scope officially
confirmed by Aqua and the GitHub advisory remains narrower.
Why was the incident response itself disrupted?
The attacker apparently also targeted the community's coordination, not
just the code. Another troubling element: BoostSecurity indicates that
the initial GitHub discussion of the February incident, #10265, was deleted
during the response phase. StepSecurity also reports that this discussion
contained active exchanges about the new v0.69.4 compromise.
BoostSecurity also describes a flooding campaign by bot accounts in the replacement discussion, with generic comments meant to drown the useful signals. If true, we are not only talking about a technical compromise, but also about an attempt to jam the community coordination during remediation.
What do we know, what do we suspect, what remains unconfirmed?
Several elements are publicly observable, while others remain at the level of highly probable analysis.
At this point, we can observe publicly that:
- a
v0.69.4release did exist and was then deleted; - an emergency Homebrew rollback to
v0.69.3did happen; setup-trivywas purged to leave only a cleanv0.2.6tag;- the community launched a broader audit of the Trivy workflows after the
first incident. A public PR mentions 26 findings across 22 workflows
and 2 composite actions, including fixes for secret exposure and the
addition of explicit
permissions:blocks.
On the other hand, some points still sit at the level of very probable analysis, not absolute certainty:
- that the same PAT is indeed the direct cause of this second episode;
- that all the cited distribution channels actually served compromised artifacts during the same window;
- that the full extent of the
trivy-actioncompromise is precisely known.
I prefer to stay rigorous: the clues are very strong, but the external investigation is still active.
What are the real lessons for our pipelines?
1. An organisation secret in GitHub Actions is a major security debt
The most striking point here is not the initial exploitation, it is the blast radius of a secret shared across many workflows. When a PAT potentially grants access to several repositories, releases, tags and discussions, the compromise of a single workflow becomes an organisation-wide compromise.
2. Immediate rotation is not negotiable
If the BoostSecurity hypothesis is correct, this second incident is exactly what happens when a stolen credential is not revoked in time. The twenty-day gap between the two episodes is not a detail: it is an enormous exploitation window.
3. SHA pinning is not enough
Pinning GitHub actions by SHA is necessary, but you also have to validate
the provenance of the commit. Check whether it is signed, whether it
belongs to the expected history, and whether it is not simply an orphan
commit prepared to fool defenders. BoostSecurity notes that the commits
used here were unsigned and that neither actions/checkout nor
aquasecurity/trivy enforced commit signing.
4. Even good workflows must be treated as attack surfaces
The public audit launched after the first incident is revealing: secrets exposed on the command line, possible shell injections, missing or overly broad permissions. These are not style details. They are entry points.
5. Automated distribution channels propagate a compromised release very fast
Homebrew, OCI images, GitHub Actions: once a release looks legitimate, propagation can be very fast and largely automated. Here, it is precisely this automation that turns a repository incident into a supply chain incident.
What should you do right now if you use Trivy?
If you consumed Trivy between 19 and 23 March 2026, treat the following as untrustworthy:
v0.69.4for binaries and images;aquasecurity/trivy-actionon the compromised tags;aquasecurity/setup-trivybeforev0.2.6;- on Docker Hub,
aquasec/trivy:0.69.4,0.69.5,0.69.6and potentially any use oflatestduring the affected window.
Concretely, you should:
- search for
0.69.4,0.69.5,0.69.6andlatestin your workflows, Dockerfiles, Helm values and manifests; - check your CI/CD caches and your mirror registries;
- audit the Docker Hub pulls performed around 19–23 March;
- look for any communication towards
scan.aquasecurtiy.org; - consider as compromised any pipeline that executed an affected Trivy action during the exposure window;
- perform a full rotation of the exposed secrets, including self-hosted runners and credentials persisted on disk;
- replace the references with healthy versions and, when possible, with pinned digests rather than floating tags.
Where do I stand?
This second episode is, in my view, even more instructive than the first.
The first showed that a badly designed GitHub Actions workflow could lead to a major compromise. The second shows something harder to hear: once an attacker holds a powerful credential, they can come back later, blend into the project's automation, then turn the build and distribution ecosystem into an attack vector.
The real lesson is therefore not only "do not use pull_request_target
carelessly". The real lesson is broader: a CI/CD pipeline must be
administered as a critical system, with privilege separation, very
short-lived secrets, immediate rotation, mandatory signatures, tag control,
provenance verification and fast response capability.
Otherwise, the day the chain breaks, it is not just your repository that goes down. It is the trust of your users that leaves with it.
The new signal on Docker Hub also changes the nature of the lesson. We are
no longer talking only about a GitHub release compromised for a few hours, but
about the incident persisting in heavily used distribution channels,
including through newer tags and latest. It reinforces a simple conclusion:
in critical CI/CD, we should no longer consume external images on the fly
without quarantine, provenance verification, internal promotion
and control before execution.
In the meantime, my personal recommendation is clear: stop using Trivy.
Sources
- BoostSecurity Security Labs, 20 Days Later: Trivy Compromise, Act II
- StepSecurity, Trivy Compromised a Second Time - Malicious v0.69.4 Release
- Socket, Trivy Supply Chain Attack Expands to Compromised Docker Images
- Aqua Security, Trivy supply chain attack: what you need to know
- GitHub Advisory, GHSA-69fq-xp46-6x23
- NHS England, Aqua Security Trivy GitHub Action Compromised
- GitHub Discussions, Trivy security incident 2026-03-01
- GitHub Discussions, GitHub Actions Workflow Security Audit, Post-Incident Hardening
- My first post, Trivy wiped out after a supply chain attack by an AI bot