When the Security Scanner Became the Weapon — A Cyber Kill Chain Analysis of the Trivy Supply Chain Attack
Aqua Security's Trivy was compromised by TeamPCP, cascading into LiteLLM. A 7-phase Cyber Kill Chain and MITRE ATT&CK analysis of how incomplete credential rotation turned a single breach into a five-ecosystem catastrophe.

Key Takeaways
- Aqua Security's Trivy (open-source security scanner) compromised by TeamPCP; 76/77 GitHub Actions tags force-pushed to malicious commits (Feb-Mar 2026)
- Compromised Trivy exfiltrated LiteLLM's PyPI publish token from CI/CD pipelines, enabling publication of malicious versions (1.82.7, 1.82.8)
- .pth file mechanism triggers on every Python interpreter startup — infection without import
- K8s cluster lateral movement, 44 Aqua repositories defaced, 5 ecosystems infiltrated (GitHub Actions, Docker Hub, npm, Open VSX, PyPI)
- Aqua's March 1 credential rotation was incomplete and non-atomic, allowing attacker re-entry
- Root causes: long-lived PAT, unpinned GitHub Actions, absent NHI credential governance
If You Can't Trust Your Security Tools, What Can You Trust?
On March 24, 2026, Trivy was running in CI/CD pipelines around the world, doing exactly what it was supposed to do: scanning container images for vulnerabilities, generating security reports, passing or failing builds. Business as usual.
Except this "security scanner" was no longer a security scanner.
Seventy-six of Trivy's GitHub Actions tags had already been replaced with malicious commits. Every time the scanner ran, after completing its legitimate vulnerability scan, it silently read the GitHub Actions runner's process memory to harvest secrets, encrypted them, and transmitted them to the attacker's server. And the scan results? They displayed normally. So nobody would notice.
The cruelest aspect of this attack is the weaponization of trust. Trivy is an open-source security scanner built by Aqua Security, an industry-standard tool with over 25,000 GitHub stars. The fact that "the tool you run for security" became the entry point for the attack raises fundamental questions about every developer's and security team's threat model.
The attacker: TeamPCP. Active since December 2025, they first breached Trivy in late February 2026 and spent roughly a month conducting a campaign across five ecosystems: GitHub Actions, Docker Hub, npm, Open VSX, and PyPI. Along the way, LiteLLM — an AI proxy package with 3.4 million daily downloads — was infected in a cascade, and a worm that automatically infects Kubernetes clusters was deployed.
There's a Latin saying: "Quis custodiet ipsos custodes?" — Who watches the watchmen? TeamPCP demonstrated the answer: nobody was watching.
This article dissects the month-long campaign through the lens of the Cyber Kill Chain's 7 phases and the MITRE ATT&CK framework.
Timeline: A Month-Long Campaign

Date | Event | Severity
Dec 2025 | TeamPCP begins operations (Docker API exploits, etc.) | Reconnaissance
Late Feb 2026 | Trivy GitHub Actions misconfig exploited; Argon-DevOps-Mgt PAT exfiltrated | Initial Breach
Mar 1, 2026 | Aqua Security attempts credential rotation — incomplete and non-atomic | Failed Response
Mar 19, 17:43 UTC | trivy-action 76/77 tags force-pushed; setup-trivy 7/7 tags replaced | Attack Launch
Mar 20, 2026 | CrowdStrike Linux sensor detects anomalous script execution | Detection
Mar 22, 2026 | Attacker re-establishes access. Malicious Docker images (v0.69.5, v0.69.6) pushed. 44 Aqua repos defaced in 2 minutes | Re-entry
Mar 23, 2026 | CVE-2026-33634 assigned (CVSS 9.4). Checkmarx KICS also confirmed compromised | Escalation
Mar 24, 10:39 UTC | Malicious litellm 1.82.7 published to PyPI | Cascade
Mar 24, 10:52 UTC | Malicious litellm 1.82.8 published (.pth mechanism added) | Escalation
Mar 24, 11:48 UTC | Security researcher Callum McMahon discloses LiteLLM compromise | Disclosure
Mar 24, ~13:38 UTC | PyPI quarantines affected versions (~3 hours of exposure) | Containment
Mar 25, 2026 | Microsoft publishes detection and defense guidance | Follow-up
Note the ~3-week dwell period from initial breach in late February to the active attack on March 19. During this time, the attacker reconnoitered infrastructure, registered domains, and prepared payloads. And even after Aqua's rotation attempt on March 1, the attacker retained valid access paths.
Kill Chain Analysis: 7 Phases

Phase 1: Reconnaissance
TeamPCP's first move was analyzing Trivy's GitHub Actions workflow configuration.
Trivy's GitHub Actions setup contained a critical misconfiguration: workflows triggered by external pull requests had access to repository secrets. This is one of the most well-documented dangerous patterns in GitHub Actions security. The pull_request_target event combined with excessive permissions is essentially handing secrets to external contributors.
The key asset the attacker discovered was a Personal Access Token (PAT) belonging to a service account called Argon-DevOps-Mgt (GitHub ID 139343333, created July 2023). Critically, this was a long-lived PAT — not a scoped GitHub App token, but a personal access token with broad permissions and no expiration. MFA was not required.
MITRE ATT&CK Mapping
The misconfiguration had existed since October 2025 — approximately 5 months of exposed attack surface that nobody detected or remediated.
Phase 2: Weaponization
With the PAT secured, TeamPCP began building attack infrastructure.
First: typosquatting domain registration. scan.aquasecurtiy.org — did you notice the 'i' and 'y' are transposed in "security"? This subtle typo was crafted to deceive security analysts reviewing logs, making data exfiltration appear to flow to legitimate Aqua Security infrastructure.
Second: the malicious entrypoint.sh. The legitimate Trivy Action's entrypoint.sh is 2,855 bytes. TeamPCP's version: 17,592 bytes. Roughly 6x larger. The additional code was hidden behind the legitimate Trivy scan logic, with error handling deliberately silenced so failures produced no output.
The attacker also hardcoded a 4096-bit RSA public key. All exfiltrated data was encrypted with this key before transmission, making it impossible to inspect payloads even if network traffic was intercepted. The same RSA key was used across the Trivy, KICS (Checkmarx), and LiteLLM compromises — the key forensic link confirming a single campaign.
MITRE ATT&CK Mapping
Phase 3: Delivery

March 19, 2026, 17:43 UTC. TeamPCP executed git push --force using the stolen PAT.
This single command redirected 76 release tags (out of 77) in aquasecurity/trivy-action to malicious commits. All 7 tags in aquasecurity/setup-trivy were also replaced. The only survivor: trivy-action v0.35.0.
This is tag poisoning. Git tags are essentially pointers to specific commits. A git push --force redirects the pointer to a different commit, causing every workflow referencing that tag to execute malicious code.
The sophistication shows here. TeamPCP forged the Git commit metadata — author, commit message, timestamps — to make malicious commits appear as if written by legitimate Aqua Security developers. Timestamps were backdated to July 2024 to hide any trace of recent modification.
This attack is particularly dangerous because of how GitHub Actions references work:
# Dangerous: tag reference (mutable)
- uses: aquasecurity/trivy-action@v0.69.4
# Safe: commit hash reference (immutable)
- uses: aquasecurity/trivy-action@a1234567890abcdef...
Tags are mutable. The same tag can point to entirely different code tomorrow. Commit hashes are immutable. Hash pinning would have rendered this attack impossible.
MITRE ATT&CK Mapping
Phase 4: Exploitation
Once tag poisoning was complete, CI/CD pipelines worldwide began executing malicious Trivy. No developer needed to install anything or click anything. Already-configured workflows automatically fetched and ran the malicious code.
The malicious entrypoint.sh operated in 5 stages:
Stage 1: Process enumeration. Identified processes running on the GitHub Actions runner, specifically targeting Runner.Worker — the process holding workflow environment variables and secrets in memory.
Stage 2: Memory scraping. On GitHub-hosted runners, directly read /proc/{PID}/mem to dump process memory. On self-hosted runners, harvested credentials from the filesystem. Collected: SSH keys, cloud credentials (AWS/GCP/Azure including IMDSv2), Kubernetes secrets and service account tokens, Docker configs, .env files, shell history, and even cryptocurrency wallet seeds (Bitcoin, Ethereum, Solana, Monero).
Stage 3: Encryption and exfiltration. Collected data encrypted with AES-256-CBC, session key wrapped with the hardcoded RSA public key, bundled into tpcp.tar.gz, and transmitted to scan.aquasecurtiy.org.
Stage 4: Dual exfiltration path. A fallback exfiltration channel via GitHub releases was implemented in case HTTPS transmission failed.
Stage 5: Camouflage. The most cunning part: after all malicious activity completed, the legitimate Trivy scan runs normally. Workflow logs show the same scan results as always. Security teams reviewing logs would find nothing unusual.
Among the credentials exfiltrated was LiteLLM's PYPI_PUBLISH token. LiteLLM used Trivy in its CI/CD pipeline for security scanning, referencing an unpinned version.
MITRE ATT&CK Mapping
Phase 5: Installation

March 24, 2026, 10:39 UTC. TeamPCP used the stolen PyPI token to publish litellm 1.82.7. Thirteen minutes later at 10:52 UTC, 1.82.8 followed. The two versions used different infection mechanisms, demonstrating how methodically the attacker operated.
litellm 1.82.7 — Source Code Injection
A double-base64 encoded payload was inserted into litellm/proxy/proxy_server.py. It executed when running litellm --proxy or importing litellm.proxy.proxy_server. A conditional trigger — only developers using LiteLLM's proxy feature were infected.
litellm 1.82.8 — .pth File Escalation
The second version, released 13 minutes later, was far more aggressive. A litellm_init.pth file was added. .pth files in Python's site-packages directory execute automatically on every Python interpreter startup. No import needed. It even runs during pip install operations. This is a vastly more effective infection mechanism than traditional import-based triggers.
Three-stage malware payload:
Stage 1 — Credential harvesting: SSH keys, cloud tokens (AWS/GCP/Azure), K8s secrets and service account tokens, Docker configs, Git credentials, .env files, shell history, cryptocurrency wallet seeds (Bitcoin, Ethereum, Solana, Monero).
Stage 2 — Encryption and exfiltration: 32-byte AES-256-CBC session key generated, data encrypted, session key wrapped with RSA-OAEP, bundled into tpcp.tar.gz, POSTed to models.litellm.cloud.
Stage 3 — Persistence and lateral movement: Backdoor installed at ~/.config/sysmon/sysmon.py with a systemd user service polling checkmarx.zone/raw every 5 minutes for additional payloads. Notably, a kill switch was built in that aborted execution if URLs contained youtube.com.
MITRE ATT&CK Mapping
Phase 6: Command and Control
TeamPCP's C2 infrastructure went beyond simple HTTP callbacks. They used the Internet Computer Protocol (ICP) blockchain as a C2 channel.
The advantages of blockchain-based C2 are clear. Traditional C2 servers can be neutralized through domain blocking or IP blacklisting. But C2 endpoints hosted on a blockchain are nearly impossible to take down — it requires breaking the consensus of a distributed network.
The mechanism, called CanisterWorm, stored commands in ICP blockchain canisters (smart contracts), with the sysmon.service on infected machines polling periodically.
A traditional C2 path was maintained in parallel: polling checkmarx.zone/raw every 50 minutes to download additional payloads. The "checkmarx" domain name was deliberate — Checkmarx's KICS GitHub Action was also compromised in the same campaign.
MITRE ATT&CK Mapping
Phase 7: Actions on Objectives

TeamPCP's endgame was multi-layered.
Kubernetes worm: Using stolen K8s service account tokens, the worm enumerated all namespace secrets across the cluster, then deployed privileged pods named node-setup-{node_name} into the kube-system namespace on each node. These pods mounted the host filesystem and used chroot to directly access the node OS and install backdoors. Notably, Iranian clusters received a wiper component deploying privileged DaemonSets with a container named "kamikaze," while non-Iranian nodes received CanisterWorm.
44 repository defacement: March 22, 2026, 20:31:07–20:32:26 UTC. In exactly 79 seconds, 44 repositories in the aquasec-com GitHub organization were automatically defaced by script. All repositories were renamed with a "tpcp-docs-" prefix. This exposed source code for Tracee (runtime security tool), internal Trivy forks, CI/CD pipeline configurations, and K8s operators.
Five-ecosystem infiltration: From a single entry point (Trivy), the campaign spread across five software ecosystems:
- GitHub Actions — trivy-action, setup-trivy tag poisoning
- Docker Hub — malicious Trivy images (v0.69.5, v0.69.6)
- npm — 44 compromised packages, CanisterWorm distribution
- Open VSX — VS Code extensions
- PyPI — LiteLLM backdoor
For LiteLLM specifically, Wiz's analysis found it present in 36% of all cloud environments. Even with a ~3-hour exposure window, given its 3.4 million daily download volume, the potential blast radius was enormous.
MITRE ATT&CK Mapping
Incomplete Rotation — The Decision That Turned a Breach Into a Campaign
The most painful lesson from this incident isn't a technical vulnerability. It's a failure of response.
On March 1, 2026, Aqua Security detected the breach and attempted credential rotation. On the surface, this was the right response. Revoking compromised credentials and issuing new ones is incident response 101.
The problem: the rotation was incomplete and non-atomic.
"Non-atomic" means not all credentials were rotated simultaneously. Some credentials were revoked, but other access paths remained open. The attacker used still-valid credentials to re-establish access, launching a second wave on March 22 that pushed malicious Docker images and defaced 44 repositories.
GitGuardian's analysis captured it precisely: "What turned one breach into a campaign was the incomplete rotation."
This is the core problem of NHI (Non-Human Identity) governance. The Argon-DevOps-Mgt PAT was:
- Created in July 2023 — used for nearly 3 years without rotation
- Excessively scoped — capable of repository tag manipulation, Docker image pushes, and organization settings changes
- No MFA required — a single token granted full access
- No usage monitoring — abnormal usage patterns (e.g., 76 simultaneous tag force-pushes) went undetected
As GitGuardian put it: "The hard problem is no longer finding a secret after it leaks. The hard problem is stopping that secret from becoming the attacker's next foothold."
Why Existing Defenses Failed
This incident exposes structural weaknesses in current software supply chain security at multiple levels.
Unpinned GitHub Actions
Most projects reference GitHub Actions by tag (@v1, @v0.69.4). Tags are mutable — a single git push --force makes the same tag point to entirely different code. Commit hash pinning (@a1b2c3d...) would have made this attack impossible, but most teams use tags for convenience. Post-incident, GitHub has begun recommending tag pinning more strongly, and Dependabot now supports hash pinning updates.
The Danger of Long-lived PATs
GitHub App tokens have limited scope, short lifetimes, and installation-level permission management. PATs carry broad user-level permissions with no default expiration. Had Argon-DevOps-Mgt's PAT been a GitHub App token:
- Scoped to specific repositories and permissions, likely preventing tag force-push
- Short-lived, so a late-February theft would have produced an expired token by March 19
- More detailed usage logs enabling anomaly detection
"Nobody Scans the Security Scanner"
This is the most fundamental problem. Organizations use security tools to validate the security of source code, container images, and dependencies. But almost no one validates the security of the security tools themselves. When adding Trivy to CI/CD, how many teams reviewed its GitHub Actions workflow security configuration? Most rely on an implicit trust: "Aqua Security built it, so it must be safe."
This implicit trust is the core attack surface of supply chain attacks.
Rebuilding the Defense Line: The Cremit Perspective

Tracing this incident to its root cause leads to one conclusion: absent NHI (Non-Human Identity) governance.
1. NHI Inventory and Visibility
The Argon-DevOps-Mgt PAT existed unmanaged for 3 years. This is the norm, not the exception. In most organizations, NHI credentials — service accounts, PATs, API keys, OAuth tokens — are not tracked after issuance.
Cremit's NHI management provides a complete inventory of all non-human credentials across the organization. Which tokens are used where, when they were last accessed, and what permissions they hold — all visible at a glance. Had Aqua had this visibility, the excessive permissions and extended inactivity of the Argon-DevOps-Mgt PAT could have been identified and remediated proactively.
2. Real-time Credential Leak Detection
The moment TeamPCP scraped credentials from GitHub Actions memory, Cremit's secret detection engine can capture abnormal credential access patterns. It monitors credential exfiltration in CI/CD pipelines in real time, matching against known leak patterns (memory dumps, environment variable collection) to provide immediate alerts.
3. Rotation Verification and Completeness
Aqua's biggest mistake was incomplete rotation. Cremit verifies that all associated access paths are simultaneously revoked during credential rotation. If a single PAT is used across multiple systems, rotation remains flagged as "incomplete" until replacement is confirmed at every usage point.
4. CI/CD Pipeline Credential Monitoring
Cremit monitors access patterns for secrets used in CI/CD environments (GitHub Actions, Jenkins, GitLab CI). Anomalies like "a PyPI deployment token normally used once per week suddenly accessed from an external IP" are detected, potentially blocking the stolen PYPI_PUBLISH token before it could be used to publish malicious packages.
Five Things to Check Tomorrow
An actionable checklist from the lessons of this incident.
1. GitHub Actions Hash Pinning
Change all third-party GitHub Action references from tags to commit hashes. Configure Dependabot or Renovate to receive automatic updates even with hash pinning.
# Before (vulnerable)
- uses: aquasecurity/trivy-action@v0.69.4
# After (safe)
- uses: aquasecurity/trivy-action@a1234567890abcdef1234567890abcdef12345678
2. PAT to GitHub App Migration
Migrate all automation using long-lived PATs to GitHub App-based authentication. GitHub App tokens are scoped, short-lived (1 hour), and offer installation-level granular permission management.
3. Credential Inventory
Conduct an inventory of all NHI credentials in use across your organization (PATs, service account keys, API tokens, OAuth apps). Identify each credential's creation date, last used date, permission scope, and owner. Flag excessive permissions and long-unused credentials.
4. Rotation Procedure Verification
Verify that credential rotation procedures are atomic. When one credential is used across multiple systems, all usage points must be rotated simultaneously. As Aqua's failure demonstrated, rotating some while leaving others active hands the attacker a re-entry path.
5. "Security of Security Tools" Review
Review the security configuration of security tools used in your CI/CD pipeline (Trivy, Snyk, SonarQube, etc.). What permissions do they run with? What secrets can they access? Are their GitHub Actions workflow configurations secure?
TeamPCP declared on Telegram: "Many of your favourite security tools and open-source projects will be targeted in the months to come." Whether this threat is bluster or reality remains to be seen. But one thing is certain: the era of blindly trusting security tools is over.
Quis custodiet ipsos custodes? — The answer now depends on your NHI governance.
Related posts:
- Git Secret Scanning: Complete Guide for 2026
- How a Single GitHub Issue Title Compromised 4,000 Developer Machines
References:
- CrowdStrike: From Scanner to Stealer — Inside the trivy-action Supply Chain Compromise
- Aqua Security: Trivy Supply Chain Attack — What You Need to Know
- GitGuardian: Trivy's March Supply Chain Attack Shows Where Secret Exposure Hurts Most
- Wiz: Trivy Compromised by TeamPCP
- Snyk: How a Poisoned Security Scanner Became the Key to Backdooring LiteLLM
- Microsoft Security: Detecting and Defending Against the Trivy Compromise
- MITRE ATT&CK Framework
