Trivy Supply Chain Compromise
Security advisory · March 22, 2026
Drydock is not affected by this breach
We have audited our entire CI/CD pipeline, dependency tree, and runtime integrations. Drydock does not use the compromised GitHub Actions, did not pull the backdoored binary, and all workflow actions are pinned by immutable commit SHA. No user action is required for Drydock itself.
What happened
On March 19, 2026, a threat actor known as TeamPCP used compromised credentials to execute a multi-stage supply chain attack against Aqua Security's Trivy, a widely-used vulnerability scanner for containers, Kubernetes, and infrastructure-as-code.
The attack compromised three components:
- trivy-action — 76 of 77 release tags were force-pushed to malicious commits containing a credential-stealing payload
- setup-trivy — all 7 existing tags were replaced with malicious versions
- Trivy binary v0.69.4 — a backdoored release was published via the official release pipeline
Exposure windows
| Component | Start (UTC) | End (UTC) | Duration |
|---|---|---|---|
| trivy v0.69.4 | Mar 19 18:22 | Mar 19 ~21:42 | ~3 hours |
| trivy-action | Mar 19 ~17:43 | Mar 20 ~05:40 | ~12 hours |
| setup-trivy | Mar 19 ~17:43 | Mar 19 ~21:44 | ~4 hours |
How the attack worked
The root cause was a continuation of an earlier supply chain attack from late February 2026. Aqua Security rotated credentials but the process was not atomic — the attacker was able to exfiltrate newly rotated secrets during the rotation window, retaining write access to the repositories.
The attacker used Git's mutable tag mechanism to silently replace trusted code:
git tag -f 0.24.0 <malicious-commit>
git push -f origin refs/tags/0.24.0Since GitHub's release page doesn't visually change when a tag is repointed, any workflow referencing these actions by version tag (e.g., @0.24.0) would silently execute the malicious payload on its next run.
Payload behavior
The malicious entrypoint.sh prepended ~105 lines of attack code before the legitimate Trivy scanner. It executed a multi-stage credential theft operation:
- Runner process discovery — enumerated GitHub Actions runner PIDs and scraped
/proc/<PID>/environfor secrets - Memory scraping — on GitHub-hosted runners, read
Runner.Workerprocess memory via/proc/<PID>/memlooking for JSON structures matching"name":{"value":"...","isSecret":true} - Filesystem harvesting — on self-hosted runners, swept 50+ paths for SSH keys, cloud credentials (AWS, GCP, Azure), Kubernetes tokens, database configs,
.envfiles, TLS private keys, and cryptocurrency wallets - Encrypted exfiltration — data was AES-256-CBC encrypted with an RSA-4096 wrapped session key and POSTed to a typosquatted domain (
scan.aquasecurtiy[.]org) - Fallback exfiltration — if the primary channel failed and a GitHub PAT was available, the payload created a public
tpcp-docsrepository on the victim's account and uploaded the stolen data as a release asset - Cleanup — all temporary files were removed and the legitimate Trivy scanner ran normally, making the compromise invisible in workflow logs
Why Drydock is not affected
We audited every potential exposure vector:
1. No use of compromised GitHub Actions
Drydock does not use aquasecurity/trivy-action or aquasecurity/setup-trivy in any GitHub Actions workflow. Our CI/CD pipeline was never exposed to the compromised entrypoint scripts.
2. Bundled Trivy binary is a safe version
Drydock's Docker image includes Trivy and cosign binaries for local vulnerability scanning and image signature verification. The Trivy binary is installed from Alpine's package repository and pinned at v0.69.3-r1 in the Dockerfile, which predates the compromised v0.69.4 release. Aqua Security has confirmed that v0.69.3 is safe and protected by GitHub's immutable releases feature.
# From Drydock's Dockerfile — Trivy pinned to safe version
apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/testing trivy=0.69.3-r1Correction (March 22): Our initial audit stated the Dockerfile pinned Trivy, but the main branch Dockerfile did not include an explicit version constraint for the Trivy APK package at the time of publication. This does not change the outcome: no Docker image builds ran during the exposure window, the Alpine repository was serving v0.69.3 (safe), and even if a compromised Trivy binary had been installed, it would only be used to scan container images for CVEs — it has no access to CI runner secrets, SSH keys, process memory, or any of the targets the GitHub Actions payload exploited. The QA test compose file also referenced aquasec/trivy:latest, but that environment only runs on developer machines, never in CI or production. As a defense-in-depth measure, we have pinned both: trivy=0.69.3-r1 in the Dockerfile and aquasec/trivy:0.69.3 in the QA compose.
Additionally, our CI/CD linting uses Trivy through Qlty, which also has v0.69.3 cached locally.
3. All GitHub Actions pinned by commit SHA
Every third-party action in Drydock's workflows is pinned by full, immutable commit SHA — not by mutable version tags. This is the primary defense against the tag repointing attack described in CrowdStrike's analysis:
# Drydock workflow example — all actions SHA-pinned
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.04. Additional CI security layers
- StepSecurity Harden Runner — every CI job runs
step-security/harden-runnerfor runtime security monitoring on GitHub Actions runners - OpenSSF Scorecard — automated security health checks on every push
- Dependency review —
actions/dependency-review-actionaudits dependency changes on every PR - Cosign image signing — all published Docker images are signed with Sigstore cosign and include build provenance attestations
Verifying your Drydock installation
Drydock bundles Trivy and cosign in its Docker image for local vulnerability scanning and image signature verification. All official Drydock releases pin Trivy at v0.69.3-r1, which is confirmed safe. You can verify your running instance:
# Check the Trivy version inside your Drydock container
docker exec drydock trivy --version
# Safe versions: v0.69.2 or v0.69.3
# Compromised version: v0.69.4If you use an external Trivy server via DD_SECURITY_TRIVY_SERVER, verify that server independently as well.
Recommendations for Drydock users
If you use trivy-action in your own CI pipelines
Check whether your workflows ran between March 19–20, 2026. If they did, treat all secrets accessible to those runners as compromised. Rotate credentials immediately and follow Aqua Security's remediation guidance.
If you self-host a Trivy server
Verify your Trivy version is not v0.69.4. Update to v0.69.3 or wait for the next clean release. Check for the persistence mechanism: look for ~/.config/systemd/user/sysmon.py on systems where Trivy was installed.
Search for exfiltration artifacts
Look for repositories named tpcp-docs in your GitHub organization. The presence of such a repository indicates that the fallback exfiltration mechanism was triggered.
Pin all GitHub Actions by commit SHA
This is the single most effective defense against tag repointing attacks. Git tags are mutable pointers — they can be silently redirected to malicious commits without any visible change on the release page. SHA pins are immutable.
# Vulnerable: mutable tag reference
uses: aquasecurity/trivy-action@0.24.0
# Safe: immutable SHA reference
uses: aquasecurity/trivy-action@<full-commit-sha> # 0.24.0References
- Aqua Security Advisory — GHSA-69fq-xp46-6x23
- Aqua Security Disclosure — GitHub Discussion
- CrowdStrike — From Scanner to Stealer: Inside the trivy-action Supply Chain Compromise
- BleepingComputer — Trivy Vulnerability Scanner Breach
- Drydock Community Discussion #197
Timeline
| Date (UTC) | Event |
|---|---|
| Late Feb 2026 | Initial compromise of Aqua Security credentials |
| Mar 1, 2026 | Aqua Security discloses initial incident, begins credential rotation |
| Mar 19, 17:43 | Attacker force-pushes 76 trivy-action tags and 7 setup-trivy tags to malicious commits |
| Mar 19, 18:22 | Backdoored trivy v0.69.4 binary published via release pipeline |
| Mar 19, ~21:42 | Malicious trivy v0.69.4 release pulled (~3 hour window) |
| Mar 20, ~05:40 | Malicious trivy-action tags remediated (~12 hour window) |
| Mar 20 | CrowdStrike publishes technical analysis after discovering the attack via Falcon detections |
| Mar 21 | Aqua Security publishes GHSA-69fq-xp46-6x23 |
| Mar 22 | Drydock completes audit, publishes this advisory and community response |
| Mar 22 (update) | Post-publication audit found Dockerfile lacked explicit Trivy version pin; hardened Dockerfile and QA compose to pin safe versions |