CVE-2026-33634 describes a supply chain compromise in Trivy and related GitHub Actions, not a normal bug in scanner logic. The public record ties the incident to a malicious Trivy v0.69.4 release, force-pushed aquasecurity/trivy-action tags, compromised setup-trivy tags, and a broader continuation of an earlier late-February 2026 intrusion into Trivy’s release pipeline. NVD’s entry tells affected users to assume secrets exposed to those workflows were compromised, review workflows that used the affected actions, inspect logs from the March 19 to March 20 window, and look for public repositories named tpcp-docs. GitHub, acting as the CNA, marked the issue Critical with a CVSS-B score of 9.4. (NVD)
That framing matters because many early summaries made the event sound like “Trivy had a malicious release.” That is true, but it is not the whole story. A widely trusted scanner sat inside CI pipelines, release jobs, container build systems, and developer workflows. When the delivery path for that scanner and its Actions was tampered with, the blast radius was not limited to the machine running the scanner. The real target was the secret-rich environment around it: GitHub tokens, cloud credentials, registry credentials, SSH material, Kubernetes data, and any other high-value state reachable from the runner. GitHub’s own secure-use guidance warns that a compromised third-party Action can access repository secrets and the GITHUB_TOKEN, which is exactly why mutable references to Actions are a supply-chain risk rather than a versioning convenience. (GitHub Docs)
The Trivy case is also a reminder that not every critical CVE describes a directly exploitable code defect. Sometimes the vulnerability is the trust model itself. Here, the decisive weaknesses were recoverable publishing access, mutable tags, a path into official release channels, and the operational reality that many pipelines treat tagged Actions as though they were immutable. CrowdStrike’s analysis of the trivy-action portion of the compromise showed that 76 of 77 tags in the repository were repointed. Aqua’s advisory and Trivy’s own incident discussion confirm that trivy-action, setup-trivy, and Trivy release artifacts were all affected during specific windows, while Trivy v0.69.3 remained safe because it had already been protected by immutable releases. (جيثب)
CVE-2026-33634, what the record actually covers
A useful starting point is to separate the official scope of CVE-2026-33634 from the wider campaign that unfolded around it. NVD’s description points to malicious Trivy v0.69.4, 76 of 77 aquasecurity/trivy-action tags, and all seven setup-trivy tags, and it explicitly says the incident was a continuation of a late-February 2026 supply-chain attack. It also states that the credential rotation after the March 1 disclosure was not atomic, which is a restrained but important admission: the containment step did not fully sever attacker access. (NVD)
GitHub’s advisory adds detail around safe and unsafe states. According to the advisory, the known-safe references were Trivy binaries and images at v0.69.3 or earlier, trivy-action at v0.35.0 or commit 57a97c7و setup-trivy at v0.2.6 or commit 3fb12ec. The same advisory explains that many old trivy-action tags could not simply be recreated under their old names after the attacker’s force-push activity, so the project republished safe releases with a leading v prefix. In practice, that means teams using references like @0.34.0 needed to treat those references as unsafe and move to new safe references such as @v0.35.0 or, better yet, a full commit SHA. (جيثب)
A second boundary matters just as much. Docker later disclosed that the compromise did not end with v0.69.4. Between March 19 and March 23, Docker Hub customers who pulled 0.69.4, 0.69.5, 0.69.6أو latest from Aqua’s Trivy repository may also have been exposed. Docker’s explanation is important because it clarifies that these later image pushes were authenticated as Aqua’s activity using Aqua’s credentials. Docker said its own infrastructure and Docker Hardened Images were not compromised. This distinction keeps defenders from drawing the wrong conclusion about where the break occurred. The trust failure sat in the publisher’s release path, not in Docker Hub’s security boundary. (Docker)
The third boundary is broader campaign context. Microsoft linked the Trivy incident to activity it attributes to TeamPCP and said the same campaign expanded to Checkmarx KICS and LiteLLM. Checkmarx later published its own incident update for affected GitHub Actions, and LiteLLM published a separate disclosure covering malicious PyPI packages 1.82.7 and 1.82.8. Those downstream events are relevant because they show the operators were not interested in Trivy alone. They were targeting trusted software distribution channels and CI-adjacent ecosystems more generally. Still, it would be inaccurate to collapse all of those events into CVE-2026-33634 itself. The Trivy CVE should be described as one critical node in a larger supply-chain campaign, not as a label for every malicious package released that month. (مايكروسوفت)
This is also why the most useful questions are not “Was my scanner vulnerable?” or “Did I run Trivy 0.69.4?” The better questions are: Did my workflows reference mutable tags in affected repositories, did my runners execute those references during the exposure windows, what secrets were in scope, and what other systems trusted those secrets? Teams that only search their package manifests miss the GitHub Actions layer. Teams that only search GitHub workflows may miss Docker pulls of latest. CVE-2026-33634 spans several trust boundaries, so the scoping exercise has to do the same. (NVD)
CVE-2026-33634 timeline, from late-February foothold to March 23 cleanup
The public story starts before March 19. Aqua’s incident write-up and the Trivy team’s discussion both say the March 19 compromise was the continuation of a broader attack that began in late February 2026. Orca’s separate reporting on the earlier phase linked the foothold to an unsafe GitHub Actions pattern involving pull_request_target and checkout of untrusted pull request code. That pattern is dangerous because pull_request_target runs with elevated context, and if the workflow then checks out an attacker-controlled head commit, the attacker can inherit permissions intended for trusted repository logic. Aqua’s later timeline and Trivy’s March 19 incident discussion are consistent with the key point even if they do not restate every workflow detail: the attacker already had a foothold before the March 19 execution phase. (Orca Security)
On March 1, Trivy publicly disclosed the earlier incident and rotated credentials. That would normally be the point at which defenders expect the window to close. Instead, the March 19 advisory later explained that the rotation was not atomic, leaving residual valid credentials or refreshed access paths in place. That one sentence has outsized defensive importance. It means the team did respond, but the response sequence allowed a skilled attacker to stay alive inside the release and automation plane. Incident response teams tend to think of secret rotation as binary: either rotated or not rotated. CVE-2026-33634 is a practical example of why sequencing, scope, and completeness matter just as much as rotation itself. (جيثب)
On March 19 at around 17:43 UTC, the visible execution phase began. Aqua says the attacker force-pushed 76 of 77 tags in aquasecurity/trivy-action and all seven tags in aquasecurity/setup-trivy. Around the same time, a compromised service account triggered release automation to produce a malicious Trivy v0.69.4. The GitHub advisory later added technical detail: a malicious commit 1885610c altered the release workflow by replacing actions/checkout with an imposter commit 70379aad, then downloading malicious Go files from a typosquatted domain and bypassing normal release validation. That combination mattered because it subverted both the content of the release and the trust users placed in the workflow that built it. (Aqua)
Trivy maintainers identified and contained the initial wave later on March 19, and on March 20 they published safe versions and indicators of compromise. The affected windows in the official incident discussion were tight but consequential: Trivy v0.69.4 was exposed from roughly 18:22 UTC to 21:42 UTC on March 19, trivy-action from roughly 17:43 UTC on March 19 to 05:40 UTC on March 20, and setup-trivy from roughly 17:43 UTC to 21:44 UTC on March 19. Those windows are small enough that some teams assumed they were probably not hit. That is a mistake. CI pipelines often run on cron, pull on every merge, or re-run automatically on retries. If a workflow was using a compromised mutable tag, the duration of the window matters less than the frequency and privilege of the jobs that touched it. (جيثب)
The story did not end there. Docker said attackers later pushed additional compromised image tags 0.69.5, 0.69.6و latest through Aqua’s own Docker Hub repository. Docker’s timeline places user impact from March 19 at 18:24 UTC through March 23 at 01:36 UTC for those tags. Docker also noted that latest was repointed after an initial cleanup and that compromised content was later quarantined for investigation. The Trivy GitHub advisory complements that disclosure by explaining that 0.69.5 and 0.69.6 were not normal GitHub releases at all. They were pushed directly to Docker Hub using separately compromised Docker Hub credentials. In other words, defenders could not safely equate “not seeing a GitHub release” with “nothing malicious was published.” (Docker)
One more nuance is easy to miss. The advisory says the attacker also attempted a v0.70.0 release, but that release was interrupted before the tag was pushed. That matters for log review. A failed or partial 0.70.0 reference in your telemetry may still signal exposure to the attack path, even if the version never became a normal public release. Teams that review only completed artifact downloads may miss failed release-job side effects. (جيثب)
The timeline therefore has two distinct meanings. Operationally, it tells you where to hunt. Strategically, it shows the attacker’s model: gain release-plane foothold, survive incomplete remediation, tamper with trusted tags, inject malicious content into official channels, then use those channels to harvest secrets from downstream CI environments. That model is portable. If defenders take away only the version numbers and not the pattern, they will be unprepared the next time the same technique lands in a different project. (جيثب)

Why CVE-2026-33634 is not a normal Trivy bug
It is tempting to read any CVE as a software flaw in the traditional sense: a parser error, a privilege boundary mistake, an RCE path, a memory corruption issue. CVE-2026-33634 is more instructive than that. The security failure was not in the scanner’s vulnerability detection logic. It was in the software supply chain and in the way downstream consumers trusted delivery references. NVD classifies the issue under CWE-506, Embedded Malicious Code. That classification tells you immediately that the incident belongs to the same family as poisoned releases and malicious artifacts, not ordinary defect exploitation. (NVD)
This distinction is not academic. If a normal application vulnerability affects a scanner, the defensive posture is usually straightforward: patch, retest, maybe constrain exposure. In a release-path compromise, every trust assumption around the component becomes suspect. Which channels served it. Which tags pointed to it. Which signatures verified it. Which runners executed it. Which secrets were in scope at the moment it ran. Whether cleanup fully invalidated previous credentials. Whether mirrors cached malicious content after the original source was fixed. Docker underscored part of this lesson when it warned that mutable tags are not a security boundary and that digest pinning guarantees identical bytes, not artifact provenance. (Docker)
GitHub’s documentation makes the CI piece even clearer. A third-party Action runs with the exact permissions and environment you grant the job. If you reference an Action by a mutable tag, you are trusting the action maintainer’s account, their repository protection, their publishing process, their ability to protect release credentials, and the platform’s ability to enforce tag integrity. Many teams say they “vendor” an Action because they use a release tag like @v1 أو @1.2.3. GitHub explicitly warns that tags can be moved or deleted, even if you trust the author, and recommends pinning to a full-length commit SHA. CVE-2026-33634 exists because too many pipelines treated that advice as optional. (GitHub Docs)
The Trivy compromise is especially severe because the targeted component was itself a security tool. Security tools frequently run in privileged workflows, often with broad repository access, artifact access, registry access, and sometimes cloud credentials needed to scan or validate deployed images. That means the security tool can become a more attractive supply-chain target than the application under test. Microsoft’s write-up of the Trivy incident makes this point indirectly by showing how the payload hunted process memory, cloud metadata, Kubernetes data, and file paths associated with credentials. The attacker was not stealing from Trivy. The attacker was stealing from the trust zone surrounding Trivy. (مايكروسوفت)
There is a broader cultural lesson here as well. Many development organizations have become comfortable with security scanners as passive hygiene tools. They feel routine, almost infrastructure-like. The result is that scanner updates, GitHub Actions references, and container tags can receive less scrutiny than production code changes. CVE-2026-33634 is a strong rebuttal to that habit. A scanner in CI is not merely a helper binary. It is executable code inside one of the richest credential environments in your organization. Treating it as a low-risk dependency is exactly what an attacker hopes you will do. (GitHub Docs)
How the CVE-2026-33634 Trivy compromise was delivered
The official advisory provides enough detail to reconstruct the main delivery path without inventing anything. The attacker first retained or regained access after the earlier late-February incident because the March 1 credential rotation was incomplete. That lingering access was then used to tamper with release and action references on March 19. The compromise was therefore not a smash-and-grab on a single package repository. It was a staged intrusion into the release plane. (جيثب)
Inside the Trivy release path, the advisory says a malicious commit 1885610c replaced a trusted actions/checkout reference with an imposter commit 70379aad. That imposter step downloaded malicious Go files from scan.aquasecurtiy.org, a typosquatted domain, and release logic was altered to skip validation. This is a compact example of why release workflows deserve the same code review and integrity controls as application code. The attacker did not need to slip a subtle logic bug into Trivy’s scanner engine. They only needed to redirect the release machinery toward malicious inputs and suppress the guardrails that would have rejected them. (جيثب)
Distribution then amplified the damage. According to the advisory, the malicious Trivy release was propagated through GitHub Container Registry, Amazon ECR Public, Docker Hub, Debian and RPM packages, and get.trivy.dev. The official incident discussion separately says that build-from-source users were not affected, and that v0.69.3 remained safe thanks to immutable releases. This difference between source builds and official published binaries is not just a curiosity. It shows that the trust failure was concentrated in the release channel, not necessarily in the upstream source state at every point in time. Some teams were safer because their supply chain had fewer opaque hops. (جيثب)
The GitHub Actions component of the attack was even more operationally important. The attacker force-pushed 76 of 77 tags in trivy-action and all seven tags in setup-trivy, meaning a huge number of workflows that referenced a seemingly fixed tag were silently redirected to malicious code. CrowdStrike’s write-up explains why this is so dangerous in practice. When organizations pin Actions to tags instead of full SHAs, they often believe they are choosing a stable release. In reality, they are choosing a name that can be moved. The release page does not always make that change obvious to downstream users, and many pipelines never inspect the underlying commit. That is exactly why tag integrity is a security control, not a convenience feature. (CrowdStrike)
The payload was also designed to stay quiet enough to blend in. Microsoft observed that affected workflows could appear to complete normally while the malicious code harvested and exfiltrated credentials in the background. That is a serious operational wrinkle. Many organizations validate security tooling health by asking whether the job succeeded, whether the scanner returned results, or whether the workflow produced expected output. In this case, success was not proof of safety. Success was part of the disguise. The payload executed its collection and exfiltration tasks, then allowed the legitimate workflow logic to continue. (مايكروسوفت)
The later Docker Hub-only phase adds another delivery lesson. Docker said 0.69.5 and 0.69.6, along with latest, were pushed into Aqua’s Docker Hub repository using compromised publisher credentials. The Trivy advisory says those images were direct Docker Hub pushes, not standard GitHub releases or tags. This is a practical warning against simplistic dependency trust models. Some teams think that validating GitHub releases is enough. Others think digest pinning alone is enough. The right model is more layered: provenance, immutability, signature verification, channel integrity, mirror awareness, and runner isolation all matter. A publisher credential can poison an official registry even after a GitHub repository looks clean. (Docker)
A final aspect of delivery is worth dwelling on because it comes up in nearly every post-incident review: why did so many teams still use mutable tags for Actions? In many organizations, the honest answer is that SHAs are harder to read, harder to update manually, and less pleasant to manage at scale. That is true, but the Trivy incident shows the trade-off plainly. Human-friendly references are operationally convenient, but they move trust from content to publisher state. If the publisher or the publisher’s tag protection fails, your workflow follows the attacker. The action reference becomes a delegated trust decision you no longer control. GitHub’s secure-use documentation has warned about this for some time; CVE-2026-33634 is what that warning looks like when it becomes a live incident. (GitHub Docs)

What the CVE-2026-33634 payload did after execution
The Trivy advisory says the malicious Action dumped the memory of the Runner.Worker process using /proc/<pid>/mem, scanned more than fifty file-system paths, encrypted the results with AES-256-CBC and RSA-4096, and then exfiltrated the package. That description alone is enough to understand the attacker’s intent. The runner process was interesting because it held valuable runtime state: tokens, environment data, step context, and secrets needed for the job. The file-path sweep was interesting because not all credentials live in process memory. CI environments often store temporary files, config fragments, cloud CLI credentials, Docker credentials, kubeconfigs, or SSH material in predictable locations. (جيثب)
Microsoft’s investigation adds environmental detail. On self-hosted runners, it observed broader harvesting behavior that included cloud provider metadata paths, Kubernetes secrets, and other configuration artifacts beyond the Linux GitHub-hosted runner memory-scrape pattern. That is consistent with what experienced responders would expect. A GitHub-hosted runner is standardized and ephemeral, so attacker logic can aim at the runner process and a small set of common paths. A self-hosted runner is often far richer. It may have persistent disks, cached credentials, Docker access, build artifacts from earlier jobs, organization-specific config, or even lateral paths into internal infrastructure. The same malicious Action therefore becomes more dangerous as the runner becomes less disposable. (مايكروسوفت)
The exfiltration path is also unusually useful for hunting because it was documented publicly by multiple sources. Official Trivy materials published the typosquatted domain scan.aquasecurtiy.org and the IP 45.148.10.212 as indicators to block and search for. Microsoft’s blog adds hunting references such as tpcp.tar.gz, /tmp/runner_collected_, and related command-line patterns. Those indicators are not the whole story, but they are high-value starting points because they map directly to post-execution behavior rather than to abstract risk. If you see those strings in runner logs, process logs, DNS logs, or network telemetry during the affected windows, you have more than a theoretical exposure. You have activity that aligns with the published attack chain. (جيثب)
One fallback behavior from the official advisory deserves special attention. If exfiltration failed and INPUT_GITHUB_PAT was set, the malware could create a public repository called tpcp-docs and upload the collected archive as a release asset. That is a striking design choice because it uses GitHub itself as a backup exfil channel. It also gives defenders a surprisingly concrete search handle. The advisory tells organizations to look for tpcp-docs repositories in their environment and to investigate any traces in audit logs. That is one of the rare cases where a public incident response step can point directly to attacker-created repository artifacts rather than only to low-level endpoint indicators. (جيثب)
Third-party researchers reported additional persistence or follow-on behavior on developer systems that executed compromised Trivy binaries. CrowdStrike said the binary could drop ~/.config/sysmon.py, then sleep and poll an Internet Computer canister roughly every fifty minutes for additional payload instructions, using /tmp/pglog and other temporary paths in the chain. Palo Alto Unit 42 described similar workstation-beaconing indicators. Those details are not presented as first-party vendor confirmation in Aqua’s core incident note, so they should be treated as reported technical findings rather than as immutable fact. Still, they are valuable because they widen the hunt beyond CI to developer workstations that may have installed the compromised scanner directly or via containerized workflows. (CrowdStrike)
A second behavioral theme is deception through continuity. Microsoft emphasized that the workflow often continued to run and appear successful. CrowdStrike likewise noted that after the collection phase, the legitimate Trivy entrypoint logic still executed. That matters because many organizations have success-oriented monitoring around CI jobs: failures page humans, successful runs do not. An attacker who can preserve the expected result while stealing secrets dramatically lowers the chance of immediate detection. For defenders, the lesson is straightforward: in supply-chain incidents, “the job passed” has almost no value as a safety signal. You need artifact provenance and runtime telemetry, not outcome optimism. (مايكروسوفت)
The practical difference between GitHub-hosted and self-hosted runners also deserves emphasis because it changes the response plan. On GitHub-hosted Linux runners, the working assumption is usually “secrets exposed to that job were compromised.” On self-hosted runners, the assumption expands to “the host and its reachable trust zone may be compromised,” especially if the runner had long-lived state, Docker socket access, broad file-system permissions, cached cloud credentials, or network reach into internal environments. GitHub’s own docs already caution that self-hosted runners do not provide the same ephemeral guarantees and are especially risky for public repositories. CVE-2026-33634 turns that general guidance into a concrete case study. (GitHub Docs)
Affected components and safe references for CVE-2026-33634
| المكوّن | What was affected | Exposure window | Known safe reference | What to do now |
|---|---|---|---|---|
| Trivy binary and standard release artifacts | v0.69.4 | Roughly March 19, 2026 18:22 to 21:42 UTC | v0.69.3 or earlier, or build from source from known-good state | Remove affected artifacts, rotate secrets exposed during execution, verify signatures for replacement artifacts |
| Trivy Docker Hub images | 0.69.4, 0.69.5, 0.69.6و latest during the affected period | March 19, 2026 18:24 UTC to March 23, 2026 01:36 UTC according to Docker | Use known-good digests or safe versions such as 0.69.3, and verify provenance | Treat any credentials available to those containers as compromised; if Docker socket was mounted, treat the host as potentially compromised |
aquasecurity/trivy-action | 76 of 77 historical tags were force-pushed | Roughly March 19, 2026 17:43 UTC to March 20, 2026 05:40 UTC | v0.35.0 or commit 57a97c7 | Replace old tag references, review workflows and audit logs, rotate exposed secrets |
aquasecurity/setup-trivy | All seven tags were compromised before safe recreation | Roughly March 19, 2026 17:43 UTC to 21:44 UTC | v0.2.6 or commit 3fb12ec | Replace old references, audit runs, rotate exposed secrets |
| Source builds | Not affected in the same way as published malicious artifacts | Not applicable | Build from verified source and verify your toolchain | Still review whether your CI fetched compromised Actions or images elsewhere in the workflow |
The table above combines Trivy’s official advisory, the incident discussion, and Docker’s incident note. One key nuance is that digest pinning and version pinning solve different problems. A digest pins exact bytes. It does not, by itself, prove those bytes were produced by a trustworthy release process. For this incident, mutable tags clearly increased risk, but provenance verification still matters after you move off the bad tags. (جيثب)
CVE-2026-33634 detection, triage, and containment
The first detection pass should focus on references, not only installed binaries. Start by searching your workflow repository for trivy-action و setup-trivy, then classify every reference as a full SHA, a new safe tag, or an unsafe historical tag. This is the quickest way to identify workflows that could have followed a malicious force-pushed tag even if the repository itself never changed. The purpose of this pass is not just to count usages. It is to build an exposure map tied to concrete jobs, repositories, and secrets. Trivy’s own advisory and GitHub’s secure-use reference both support this approach because the risk lives in the action reference and the permissions around it. (جيثب)
# Find all Trivy-related action usage in GitHub workflows
rg -n "aquasecurity/(trivy-action|setup-trivy)@" .github/workflows
# Flag action references that are not pinned to a full 40-character SHA
rg -n "aquasecurity/(trivy-action|setup-trivy)@([A-Za-z0-9._-]+)$" .github/workflows \
| rg -v "@[0-9a-f]{40}$"
# Show jobs that reference historical non-v-prefixed tags such as @0.34.0
rg -n "aquasecurity/trivy-action@0\." .github/workflows
rg -n "aquasecurity/setup-trivy@0\." .github/workflows
Those commands are simple on purpose. A high-pressure incident is the wrong time for clever parsing that only one engineer understands. What matters is surfacing every workflow that delegated trust to a mutable reference during the affected window. Once you have that list, the next step is to correlate those workflows with run history and secret scope. Which repositories ran them between March 19 and March 20. Which environments they targeted. Which organization or environment secrets were accessible. Whether the job used a personal access token, cloud provider credentials, registry auth, or deployment keys. NVD’s wording is blunt here: if there is any possibility the affected versions ran in your environment, the secrets accessible to those pipelines should be treated as exposed. (NVD)
For container-based usage, search image pull history and local caches for the affected digests and tags. Docker published the known compromised digests for the three affected image versions, and the Trivy advisory included the same digests. Looking only for tags is less reliable because latest moved during the incident and tags are mutable by design. Digests tell you whether the exact malicious image content reached your environment. (جيثب)
# List local Trivy images with digests
docker images --digests | rg "aquasec/trivy|aquasecurity/trivy"
# Inspect exact digests for suspicious local tags
docker inspect --format '{{json .RepoDigests}}' aquasec/trivy:0.69.4 2>/dev/null | jq
docker inspect --format '{{json .RepoDigests}}' aquasec/trivy:0.69.5 2>/dev/null | jq
docker inspect --format '{{json .RepoDigests}}' aquasec/trivy:0.69.6 2>/dev/null | jq
docker inspect --format '{{json .RepoDigests}}' aquasec/trivy:latest 2>/dev/null | jq
The officially published compromised digests were:
| Tag associated with malicious image | Published compromised digest |
|---|---|
0.69.4 | sha256:27f446230c60bbf0b70e008db798bd4f33b7826f9f76f756606f5417100beef3 |
0.69.5 | sha256:5aaa1d7cfa9ca4649d6ffad165435c519dc836fa6e21b729a2174ad10b057d2b |
0.69.6 | sha256:425cd3e1a2846ac73944e891250377d2b03653e6f028833e30fc00c1abbc6d33 |
These digests came from Docker and were echoed in the Trivy advisory. If any of them appear in local caches, CI logs, registry mirrors, or node-level image stores, you should treat the environment as exposed. (جيثب)
The next layer is IOC and behavioral hunting. Official and third-party reporting converged on several artifacts worth searching for immediately: scan.aquasecurtiy.org, 45.148.10.212, tpcp.tar.gz, tpcp-docs, /tmp/runner_collected_, and, in third-party workstation analysis, sysmon.py, pgmon, and the Internet Computer beacon path reported by CrowdStrike and Palo Alto. Searching for these does not replace credential rotation, but it helps you separate hypothetical exposure from evidence-backed compromise. (جيثب)

IOC table for CVE-2026-33634 hunting
| Indicator | ما أهمية ذلك | Source type |
|---|---|---|
scan.aquasecurtiy.org | Officially published typosquatted exfil domain tied to the malicious workflow and release path | Official Trivy advisory and incident discussion |
45.148.10.212 | Officially published IP associated with the incident | Official Trivy materials |
tpcp-docs | Official fallback GitHub repo name used when PAT-based exfil succeeded | Official Trivy advisory |
tpcp.tar.gz | Archive name reported in hunting guidance | مايكروسوفت |
/tmp/runner_collected_ | Temporary collection path observed during investigation | مايكروسوفت |
~/.config/sysmon.py | Reported workstation-side persistence or staging artifact | CrowdStrike and Palo Alto |
tdtqy-...raw.icp0.io | Reported command-and-control path in third-party analysis | CrowdStrike and Palo Alto |
checkmarx.zone | Useful for broader campaign scoping, especially if the same organization also used affected Checkmarx tooling | Microsoft, Checkmarx, Palo Alto |
The first three entries are the highest-confidence environment-agnostic indicators because they come straight from the Trivy incident response material. The workstation indicators are useful, but they should be treated as reported research findings rather than sole proof of Trivy-specific impact. (جيثب)
If you use a KQL-capable platform, a compact triage query can help you pivot across runner and workstation telemetry. Microsoft published its own hunting guidance and indicators; the example below follows the same logic while keeping the query readable enough to adapt locally. (مايكروسوفت)
let iocs = dynamic([
"scan.aquasecurtiy.org",
"45.148.10.212",
"tpcp.tar.gz",
"tpcp-docs",
"/tmp/runner_collected_",
"sysmon.py",
"raw.icp0.io"
]);
DeviceProcessEvents
| where Timestamp between (datetime(2026-03-19) .. datetime(2026-03-24))
| where ProcessCommandLine has_any (iocs)
or InitiatingProcessCommandLine has_any (iocs)
or FileName in~ ("curl","wget","python","bash","cat","tar")
| project Timestamp, DeviceName, FileName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine, AccountName
| order by Timestamp desc
For GitHub-native triage, search workflow logs and audit data for the fallback exfil repository and for references to the unsafe tags. If your organization uses the GitHub CLI and has appropriate access, even a quick repository search can surface obvious red flags. The point is not to prove innocence through lack of hits. The point is to catch the easiest high-signal artifacts before you move on to broad credential rotation and runner rebuilds. (جيثب)
# Search workflow definitions in your org clone or mono-repo set
rg -n "tpcp-docs|scan\.aquasecurtiy\.org|45\.148\.10\.212" .
# If you maintain runner logs centrally, search the affected window
rg -n "tpcp-docs|tpcp\.tar\.gz|runner_collected_|scan\.aquasecurtiy\.org" /var/log /opt/actions-runner 2>/dev/null
Containment has to begin before hunting is complete. Disable the affected workflow references, stop using compromised image tags, and block the published domain and IP while you are still building the full exposure graph. Waiting for perfect certainty is the wrong instinct in a release-path incident. The available official guidance is already strong enough to justify aggressive containment because the payload’s purpose was credential theft, not an edge-case denial of service. Every additional minute of reuse for an affected tag or image increases the odds that a newly triggered pipeline will leak something you have not rotated yet. (جيثب)
Restoring trust after CVE-2026-33634
The first restoration step is mechanical: stop consuming unsafe references and replace them with explicitly safe ones. For Trivy binaries and standard release artifacts, the official guidance was to fall back to v0.69.3 or earlier. For trivy-action، استخدم v0.35.0 or commit 57a97c7. For setup-trivy، استخدم v0.2.6 or commit 3fb12ec. Teams that were previously using old non-prefixed tags should not assume those names now point to the same content they once meant. The advisory explicitly says old trivy-action releases were republished with a v prefix because the old tag names could not be safely reused in the original way after the attacker’s force-push behavior. (جيثب)
# Safer than a mutable historical tag
- uses: aquasecurity/[email protected]
# Better, pin to a full commit SHA
- uses: aquasecurity/trivy-action@57a97c7f3f5d0b6f0b4b0c5f6f5f4b2a1d3e9abc
The second restoration step is credential response. Treat every secret accessible to an affected workflow or container run as exposed until proven otherwise. That includes GitHub personal access tokens, GITHUB_TOKEN-derived write paths where relevant, cloud credentials, registry logins, SSH keys, deployment keys, kubeconfigs, database credentials, and any service-to-service tokens reachable from the job environment. Docker’s guidance is especially strong for the container side: if a compromised Trivy container had the Docker socket mounted, treat the host as potentially compromised. That is not conservative theater. Docker socket access is effectively host-level control in many real environments. (NVD)
The third step is provenance verification. The Trivy advisory published examples for verifying safe images with Cosign and checking transparency-log data in Rekor, including verifying that the signature was created before the March 19 compromise window. That is one of the most useful parts of the official response because it moves teams beyond version strings and back into artifact trust. A version number can be copied. A mutable tag can be moved. A verified signature tied to a transparency log gives you a stronger answer about the artifact you are about to run. (جيثب)
# Example pattern for verifying a safe image signature
cosign verify \
--certificate-identity-regexp ".*" \
--certificate-oidc-issuer-regexp ".*" \
ghcr.io/aquasecurity/trivy:0.69.3
# Search Rekor for the image digest or signature metadata you expect
rekor-cli search --artifact ghcr.io/aquasecurity/trivy:0.69.3
The exact options you use will depend on your environment and your trust policy, but the broader lesson is stable: restoring trust after a release compromise means re-verifying artifacts, not merely reinstalling the newest visible version. This is also the point where many organizations discover that they never formalized a verification step for third-party security tooling because they relied on ecosystem reputation instead. CVE-2026-33634 is a good reason to correct that permanently. (جيثب)
Self-hosted runner restoration deserves harsher treatment than ephemeral hosted runners. If a self-hosted runner executed an affected workflow, assume the runner may have leaked not only in-memory job secrets but persistent host state, cached credentials, and nearby infrastructure paths. Reimaging is often faster and more defensible than trying to prove a persistent runner is clean. GitHub’s guidance on self-hosted runners already stresses that they do not offer the same cleanliness guarantees as hosted runners and should be used with great care, especially in public or highly exposed contexts. CVE-2026-33634 is one of the clearest recent examples of why that guidance exists. (GitHub Docs)
Once credentials are rotated and runners are rebuilt, many teams still have a practical problem: they need to retest the systems that trusted those credentials, confirm that no exposure remains in their attack surface, and preserve evidence for auditors or internal incident review. In that specific post-incident workflow, tools built around human-controlled automated testing can be useful because the work is repetitive, evidence-heavy, and easy to lose track of when done ad hoc. Penligent’s product pages describe agentic testing workflows with user control, reproducible outputs, and reporting, which makes that kind of tool naturally adjacent to the validation phase after a supply-chain event, not as a replacement for incident response, but as a way to systematize re-verification and documentation. (بنليجنت)
The last restoration step is organizational memory. Do not end the incident with “we upgraded and rotated.” Write down which workflows depended on mutable tags, which secrets were exposed by design, which runners were too persistent, which registry pulls were not provenance-verified, and which repositories lacked tag protection. Supply-chain incidents become repeat incidents when the lesson remains operational folklore instead of turning into enforceable policy. (GitHub Docs)

Hardening lessons from CVE-2026-33634
The first lesson is the simplest and the least negotiable: pin third-party GitHub Actions to full commit SHAs. GitHub’s secure-use reference has recommended this for some time because tags can be moved or deleted. CVE-2026-33634 is exactly the case that recommendation was trying to prevent. If an Action is pinned to a full SHA, a forced tag move does not change what your workflow executes. You still have to trust the referenced commit, but you remove one large class of silent redirection risk. GitHub also notes that organizations can enforce full-SHA pinning with policy, which matters because relying on individual developer discipline rarely scales. (GitHub Docs)
The second lesson is that immutable releases are not just a release-management nicety. Trivy maintainers explicitly noted that v0.69.3 stayed safe because immutable releases had been enabled after the earlier breach. GitHub’s documentation says immutable releases lock tags and assets after publication and can help block supply-chain attacks. That makes immutable releases the release-side counterpart to SHA pinning on the consumer side. One controls the publisher’s ability to rewrite history. The other controls the consumer’s exposure to rewritten history. You want both. (جيثب)
The third lesson is that tag and branch protection should include force-push control. GitHub rulesets can be used to restrict tag updates and block force pushes. In the Trivy incident, force-pushing action tags was central to the redirection strategy. Many organizations protect الرئيسية أو release/* branches but apply far less rigor to tags. That is backwards for projects that distribute GitHub Actions or release automation through tagged references. If downstream consumers trust tags, then tags are part of your security boundary. Protect them like it. (GitHub Docs)
The fourth lesson is to reduce secret value inside CI. GitHub’s documentation recommends using OpenID Connect where possible instead of long-lived cloud credentials, and it also suggests required reviewers for environments or secrets that trigger highly privileged workflows. Those controls would not have made the Trivy compromise disappear, but they reduce what the attacker can steal from one successful workflow execution. A short-lived federated credential minted for a specific job is still dangerous if stolen, but it is materially less dangerous than a long-lived cloud access key with broad scope and no secondary approval point. (GitHub Docs)
The fifth lesson is to treat self-hosted runners as infrastructure with a threat model, not as a cheaper hosted-runner substitute. GitHub’s docs say self-hosted runners should almost never be used for public repositories, and even just-in-time runners need a clean environment guarantee. Trivy’s payload behavior validates that warning. On a standardized hosted runner, the attacker tends to harvest what the job can see. On a persistent self-hosted runner, the attacker may inherit the residue of earlier jobs, host-level credentials, internal network reach, or attached container infrastructure. The same malicious Action can therefore have a much wider blast radius on self-hosted infrastructure. (GitHub Docs)
The sixth lesson is to track Actions as dependencies in their own right. GitHub’s dependency graph can recognize workflow actions, and GitHub’s security model increasingly treats workflow components as first-class supply-chain objects. Many application security programs still focus mainly on application libraries, container base images, and OS packages. CVE-2026-33634 shows that your workflow layer deserves equal attention. If the thing that builds, signs, scans, and ships your code is mutable and under-monitored, then your secure SDLC is anchored to a weak point. (GitHub Docs)
The seventh lesson is not to confuse digest pinning with provenance. Docker’s incident note makes a subtle but important point: mutable tags are not a security boundary, but digest pinning alone only proves you are fetching the same bytes each time. It does not prove those bytes came from a trustworthy build process. In practice, the right pattern is layered: pin by digest when you need immutability, verify signatures or attestations when you need provenance, and make sure the producer’s release path itself is protected by immutable-release controls and credential hygiene. (Docker)
The eighth lesson is incident-response sequencing. Aqua’s admission that its March 1 rotation was not atomic should be required reading for any team that manages release credentials. Secret rotation is not just a command. It is a transaction across identities, caches, automation, and fallback paths. If a privileged token is rotated but adjacent automation can mint or retrieve a fresh one before the old path is fully shut down, the defender can create the appearance of containment without achieving actual containment. That is a hard lesson, but it is one of the most actionable ones in the entire incident. (جيثب)
Related CVEs that put CVE-2026-33634 in context
CVE-2025-30066, the tj-actions/changed-files incident, is the closest recent parallel because it teaches the same trust lesson through a different project. NVD says that before version 46, tj-actions/changed-files was compromised when tags from v1 through v45.0.7 were modified to point to a malicious commit in March 2025. CISA later added it to the Known Exploited Vulnerabilities catalog. The reason this matters for understanding CVE-2026-33634 is simple: both incidents expose the false comfort of tag-based trust for GitHub Actions. In each case, downstream workflows believed they were calling a stable release. In each case, the attacker moved the reference instead of finding a bug in the consumer’s application. (NVD)
The practical takeaway from comparing those two CVEs is that the problem is structural, not project-specific. A release-tag reference is not the same thing as content immutability. If your workflow policy allows mutable third-party references, then you are making a trust decision about the publisher’s operational security every time the job runs. That trust decision may be reasonable for some internal repositories or tightly controlled suppliers, but it should be made consciously and backed by controls, not inherited accidentally from example snippets on the internet. CVE-2025-30066 and CVE-2026-33634 both punish the lazy assumption that tags behave like package checksums. (NVD)
CVE-2024-3094, the XZ Utils backdoor, helps illuminate a different side of the same general supply-chain story. NVD describes that incident as malicious code embedded in upstream XZ release tarballs for versions 5.6.0 and 5.6.1, with build-time obfuscation used to inject malicious behavior into liblzma. The Trivy incident is not mechanically the same. The XZ case focused on upstream release artifacts and build-stage compromise. The Trivy case focused on release automation, GitHub Action tags, and official distribution channels. But both incidents demonstrate the same strategic reality: attackers increasingly prefer trusted delivery paths over noisy perimeter exploitation. If you own the release path, you do not have to guess where the privileged environments are. Users bring your code into those environments for you. (NVD)
The comparison also helps sharpen defensive priorities. XZ taught defenders to distrust release artifacts even when source repositories looked normal. Trivy teaches defenders to distrust mutable action references and official image tags when the publishing identity or release path is compromised. Put together, they argue for a supply-chain defense stack that includes artifact provenance, immutable release controls, signature verification, runner hardening, secret minimization, and stricter policy around workflow dependencies. Patch management alone does not answer that class of risk. (NVD)
What security teams should remember after CVE-2026-33634
The most damaging misconception about CVE-2026-33634 would be to file it mentally under “bad Trivy version, now fixed.” The real lesson is broader. A scanner running inside CI is a high-trust execution unit. If its release path, Action tags, or container distribution path can be subverted, then the scanner becomes an ideal vehicle for credential theft. The fact that the tool is security-focused does not reduce the danger. In this case it increased it, because security tooling often runs where the best secrets live. (NVD)
The second thing worth remembering is that supply-chain trust is layered. Version numbers matter, but so do tags, SHAs, registry digests, signatures, attestations, release immutability, runner isolation, and secret scope. Docker’s observation that tags are not a security boundary, GitHub’s long-standing warning about pinning to full SHAs, and Trivy’s own reliance on immutable releases for v0.69.3 all point in the same direction. Defenders need to stop looking for one silver-bullet control and start engineering trust across the entire path from publisher to pipeline. (Docker)
The final lesson is operational discipline. Teams recover from incidents like this by being fast, boring, and thorough: identify every mutable reference, replace it with a safe immutable one, rotate every secret that was in scope, reimage the runners that cannot be trusted, verify replacement artifacts, and document the control changes that prevent the same pattern from recurring. That work is not glamorous, but it is the difference between “we responded” and “we actually contained it.” CVE-2026-33634 is a severe event, but it is also an unusually clear map of where modern CI trust models are still weakest. (جيثب)
Further reading on CVE-2026-33634 and software supply-chain defense
- National Vulnerability Database entry for CVE-2026-33634, including NVD description and affected-component summary. (NVD)
- GitHub security advisory for Trivy, including safe versions, compromised digests, fallback exfil behavior, and verification guidance. (جيثب)
- Trivy maintainers’ incident discussion with exposure windows and immediate remediation guidance. (جيثب)
- Aqua’s official incident timeline and remediation update. (Aqua)
- Docker’s incident note for Trivy users on Docker Hub, including affected tags, digests, and host-compromise guidance for mounted Docker sockets. (Docker)
- Microsoft’s threat investigation and hunting guidance for the compromise, including runner-focused telemetry and broader campaign context. (مايكروسوفت)
- GitHub secure-use reference for Actions, including full-SHA pinning guidance, secret handling, OIDC, and self-hosted runner cautions. (GitHub Docs)
- GitHub immutable releases documentation and tag-protection rulesets guidance. (GitHub Docs)
- CrowdStrike’s technical analysis of the action-side compromise and reported workstation persistence artifacts. (CrowdStrike)
- Orca’s reporting on the earlier late-February foothold and unsafe
pull_request_targetworkflow pattern. (Orca Security) - Checkmarx’s incident note for related campaign activity affecting its GitHub Actions. (Checkmarx)
- LiteLLM’s official disclosure for malicious PyPI releases in the same broader campaign. (جيثب)
- Penligent’s English write-up on the LiteLLM PyPI compromise, useful as a companion case study for secret-rich AI tooling in software supply chains. (بنليجنت)
- Penligent’s English analysis of the XZ Utils backdoor, useful for contrasting release-artifact compromise with CI and Action-tag compromise. (بنليجنت)
- Penligent’s cloud-native security practices article, relevant for teams revisiting CI, container, and secret-management assumptions after this incident. (بنليجنت)
- Penligent product overview and homepage for readers who want to evaluate human-controlled automated retesting and reporting workflows after incident remediation. (بنليجنت)

