Guidance for detecting, investigating, and defending against the Trivy supply chain compromise

Guidance for detecting, investigating, and defending against the Trivy supply chain compromise

The Trivy supply chain was weaponized on March 19, 2026 when the actor identifying as TeamPCP used previously compromised credentials to inject credential‑stealing malware into official Trivy releases and related GitHub Actions, poisoning CI/CD pipelines and developer environments. Microsoft observed the attack exfiltrating harvested secrets to a typosquatted domain (scan.aquasecurtiy[.]org) and urges immediate remediation steps including pinning actions to immutable SHAs and updating to verified safe versions. #TeamPCP #Trivy

Keypoints

  • On March 19, 2026 TeamPCP used previously obtained credentials to compromise aquasecurity/trivy-action, aquasecurity/setup-trivy, and the Trivy binary distribution, injecting credential‑stealing malware into trusted releases.
  • The attacker force‑pushed 76 of 77 tags in trivy-action and all 7 tags in setup-trivy, redirecting tag references to malicious commits so CI workflows running by tag executed attacker code without visible release metadata changes.
  • The campaign published a malicious Trivy binary (notably v0.69.4) to GitHub Releases and container registries, exposing CI/CD runners and developer machines to secret harvesting and persistence.
  • The malware performed host fingerprinting and broad credential harvesting (cloud IMDS, GCP service account keys, Azure env vars, Kubernetes service accounts and secrets, CI/CD tokens, webhooks, SSH/WireGuard configs, DB strings, and crypto wallet creds).
  • Stolen data was archived as tpcp.tar.gz, encrypted with AES-256-CBC + RSA and exfiltrated via HTTP POST to the typosquatted domain scan.aquasecurtiy[.]org; the malware then cleaned up and executed a legitimate Trivy scan to remain stealthy.
  • Aqua Security maintainers removed malicious artifacts the same day; Microsoft recommends immediate updates to safe versions, pinning actions to commit SHAs, restricting permissions, using ephemeral runners, and protecting secrets with dedicated secret managers.

MITRE Techniques

  • [T1195 ] Supply Chain Compromise – The attacker injected malicious code into trusted Trivy releases and GitHub Actions to weaponize distribution channels (‘inject credential-stealing malware into official releases of Aqua Security’s widely adopted open-source vulnerability scanner, Trivy.’)
  • [T1078 ] Valid Accounts – The campaign leveraged previously compromised credentials with tag write access to force-push and reassign tags in affected repositories (‘Using compromised credentials with tag write access, the attacker force-pushed 76 of 77 version tags…’)
  • [T1057 ] Process Discovery – The malware performed process discovery to locate GitHub runner processes (‘process discovery to locate runner processes (Runner.Worker, Runner.Listener)’)
  • [T1082 ] System Information Discovery – The stealer fingerprinted hosts via commands like hostname, whoami, uname -a and ip addr to profile targets (‘The Python stealer first fingerprinted the host (“hostname”, “whoami”, “uname -a”, “ip addr”)’)
  • [T1059.006 ] Command and Scripting Interpreter: Python – A base64-encoded Python payload was decoded and executed as the credential‑harvesting component (‘A base64-encoded Python payload was then decoded and executed to handle the credential harvesting phase.’)
  • [T1027 ] Obfuscated Files or Information – The attacker used base64 encoding to conceal the payload before execution (‘A base64-encoded Python payload was then decoded and executed…’)
  • [T1552.001 ] Credentials in Files (Unsecured Credentials) – The malware searched environment files and common config formats for tokens and keys (‘.env’, ‘.json’, ‘.yml’, ‘.yaml’) and dumped environment variables (‘dumped all environment variables (via “printenv”)’ and ‘recursive filesystem searches for API keys and tokens in “.env”, “.json”, “.yml”, and “.yaml” files’)
  • [T1560 ] Archive Collected Data – Harvested data was bundled into an archive (tpcp.tar.gz) prior to exfiltration (‘The stolen data was then encrypted … and bundled into a tpcp.tar.gz archive’)
  • [T1041 ] Exfiltration Over C2 Channel – Data was exfiltrated via HTTP POST to a typosquatted domain (scan.aquasecurtiy[.]org) (‘exfiltrated via HTTP POST to the typosquatted domain scan.aquasecurtiy[.]org.’)
  • [T1071.001 ] Application Layer Protocol: Web Protocols – The attacker used HTTP(S) POST for data exfiltration and C2 communications (‘exfiltrated via HTTP POST to the typosquatted domain scan.aquasecurtiy[.]org.’)
  • [T1022 ] Data Encrypted – Collected data was encrypted with OpenSSL (AES-256-CBC + RSA) before transmission (‘The stolen data was then encrypted using a hybrid AES-256-CBC + RSA scheme’)
  • [T1552 ] Unsecured Credentials (Kubernetes Secrets) – The actor enumerated and exfiltrated Kubernetes service-account files and attempted to dump all cluster secrets via kubectl (‘Enumeration and exfiltration of mounted service-account files (under “/run/secrets/kubernetes.io/serviceaccount/”), and an attempt to dump all cluster secrets with Kubernetes CLI (“kubectl get secrets –all-namespaces -o json”)’)

Indicators of Compromise

  • [Domain ] Exfiltration C2 and typosquatting – scan.aquasecurtiy[.]org, aquasecurtiy.org
  • [IP Address ] Identified C2 and network indicators – 45.148.10.212, 45.148.10.122
  • [File name ] Collected archive and artifacts – tpcp.tar.gz, entrypoint.sh (used in detection queries)
  • [Software versions ] Compromised/observed Trivy versions – v0.69.4 (malicious), also observed in telemetry: 0.69.5, 0.69.6
  • [GitHub repositories / Actions ] Poisoned CI components – aquasecurity/trivy-action, aquasecurity/setup-trivy (tags were force-pushed to malicious commits)
  • [Command/URI fragments ] Command-line indicators seen in telemetry – strings like ‘scan.aquasecurtiy.org’, ‘/tmp/runner_collected_’, ‘openssl enc -aes-256-cbc’, and ‘curl –data-binary’


Read more: https://www.microsoft.com/en-us/security/blog/2026/03/24/detecting-investigating-defending-against-trivy-supply-chain-compromise/