On March 24, 2026, two malicious versions of LiteLLM were published to PyPI. Versions 1.82.7 and 1.82.8 contained a multi-stage credential stealer that harvested cloud credentials, SSH keys, Kubernetes configs, and cryptocurrency wallet data from every system that installed them. The exposure window was roughly 2 to 5 hours, but with approximately 3.4 million daily downloads, the blast radius was significant.
This was not a vulnerability in LiteLLM’s code. It was the result of a cascading supply chain attack by a threat actor known as TeamPCP, who pivoted through Aqua Security’s compromised Trivy GitHub Actions to reach LiteLLM’s CI/CD pipeline. This post covers the full attack chain, the 3-layer payload architecture, indicators of compromise, and what you should check in your environments.
Timeline of events
| Date | Event |
|---|---|
| March 1 | Initial TeamPCP supply chain campaign begins targeting developer infrastructure |
| March 19 | Aqua Security’s Trivy GitHub Actions compromised; attacker force-pushes 76 of 77 release tags to malicious commits |
| March 23 | Checkmarx KICS GitHub Actions and VS Code extensions compromised via the same campaign |
| March 24 | LiteLLM v1.82.7 and v1.82.8 published to PyPI with malicious payload (10:39 to 16:00 UTC) |
| March 25 | Callum McMahon (FutureSearch) discovers the payload after it causes system degradation; GitGuardian publishes analysis |
| March 26 | LiteLLM team adds indicators of compromise to their security advisory |
The entire chain, from the initial Trivy compromise on March 19 to malicious PyPI packages on March 24, took five days. LiteLLM was a downstream casualty, not the original target.
How the attack chain worked
The attack exploited trust relationships between open-source security tooling and CI/CD infrastructure. Here is the full chain as documented by Trend Micro and GitGuardian.
Step 1: Exploiting pull_request_target in Trivy. Aqua Security’s Trivy repository used a GitHub Actions workflow triggered by pull_request_target. This trigger runs in the context of the base repository (not the fork), which means it has access to repository secrets. The attacker, operating under the GitHub handle MegaGame10418, submitted a pull request that exploited this misconfiguration to exfiltrate the aqua-bot Personal Access Token.
Step 2: Force-pushing release tags. With the stolen PAT, the attacker force-pushed 76 of 77 release tags in the trivy-action repository to point at malicious commits. They similarly compromised all seven tags in the setup-trivy repository. Any CI/CD pipeline referencing these actions by tag (rather than by commit SHA) would now pull attacker-controlled code.
Step 3: LiteLLM’s CI/CD runs the compromised scanner. LiteLLM’s pipeline referenced Trivy by tag for security scanning. When it ran, the compromised Trivy action executed in LiteLLM’s CI/CD environment and exfiltrated the environment’s secrets, including a PyPI publish token and a GitHub Personal Access Token.
Step 4: Publishing malicious packages. The attacker used the stolen PyPI token to publish versions 1.82.7 and 1.82.8 with embedded credential-stealing malware. The stolen GitHub PAT was used to deface the maintainer’s profile and modify personal repositories.
graph TD A["Trivy Scanner Compromised<br/><small>pull_request_target exploit on GitHub Actions</small>"] --> B["Release Tags Force-Pushed<br/><small>76 of 77 trivy-action tags replaced</small>"] B --> C["LiteLLM CI/CD Executes Trivy<br/><small>Compromised scanner runs in pipeline</small>"] C --> D["CI/CD Secrets Exfiltrated<br/><small>PyPI publish token + GitHub PAT stolen</small>"] D --> E["Malicious PyPI Publish<br/><small>v1.82.7 and v1.82.8 with credential stealer</small>"] D --> F["GitHub PAT Abused<br/><small>Maintainer profile defaced, repos modified</small>"] E --> G["Downstream Installations<br/><small>~3.4M daily downloads exposed</small>"] style A fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style B fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style C fill:#92400e,stroke:#78350f,color:#fef3c7 style D fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style E fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style F fill:#5b21b6,stroke:#4c1d95,color:#ede9fe style G fill:#5b21b6,stroke:#4c1d95,color:#ede9fe
The critical failure was not just the misconfiguration. Aqua Security’s remediation after the initial compromise on March 1 was, as Trend Micro described it, “not atomic.” There was a multi-day window during credential rotation where the attacker retained valid credentials. That gap enabled the March 19 force-push attack and everything that followed.
The 3-layer payload
The malicious code embedded in versions 1.82.7 and 1.82.8 was not a simple backdoor. It was a structured, 3-layer attack designed for maximum credential extraction and long-term persistence, as analyzed by Ox Security and BleepingComputer.
graph TD INSTALL["pip install litellm==1.82.7 or 1.82.8<br/><small>Malicious package installed</small>"] --> L1 L1["Layer 1: Encrypted Launcher<br/><small>AES-256-CBC payload, RSA key wrapping</small>"] --> L2 L2["Layer 2: Credential Harvester<br/><small>Comprehensive system enumeration</small>"] --> TARGETS L2 --> L3["Layer 3: Persistence<br/><small>systemd service + C2 polling</small>"] TARGETS["SSH Keys / Git Credentials<br/>AWS / GCP / Azure Credentials<br/>Kubernetes Configs / DB Passwords<br/>Crypto Wallets / TLS Private Keys"] TARGETS --> EXFIL["Encrypted Exfiltration<br/><small>tpcp.tar.gz sent to models.litellm.cloud</small>"] L3 --> BACKDOOR["Backdoor: ~/.config/sysmon/sysmon.py<br/><small>Polls checkmarx.zone every 50 minutes</small>"] style INSTALL fill:#92400e,stroke:#78350f,color:#fef3c7 style L1 fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style L2 fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style TARGETS fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style EXFIL fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style L3 fill:#5b21b6,stroke:#4c1d95,color:#ede9fe style BACKDOOR fill:#5b21b6,stroke:#4c1d95,color:#ede9fe
Layer 1 (Launcher): The initial code decrypts an embedded payload using AES-256-CBC. The session key is wrapped with an RSA public key hardcoded in the package, meaning only the attacker can decrypt captured data. The decrypted payload bootstraps the next two layers.
Layer 2 (Credential Harvester): The harvester performs comprehensive system enumeration, targeting:
- SSH keys and configurations from
~/.ssh/ - Git credentials from
~/.git/configand credential stores - Cloud provider credentials: AWS IAM keys and temporary tokens, GCP service account keys, Azure connection strings and service principals
- Kubernetes configuration files and service account tokens
- Database credentials from environment files and configuration directories
- Cryptocurrency wallet data, including private keys
- TLS private keys from system certificate stores
The harvester did not just collect stored credentials. It actively used discovered credentials to query cloud APIs and access Kubernetes secrets, amplifying the impact beyond what was stored on disk. All collected data was encrypted and packaged into a tpcp.tar.gz archive, then exfiltrated to models.litellm.cloud.
Layer 3 (Persistence): The malware installed a systemd user service disguised as “System Telemetry Service” and wrote a backdoor to ~/.config/sysmon/sysmon.py. This backdoor polled checkmarx.zone every 50 minutes for additional payload downloads. On Kubernetes clusters, the malware deployed privileged pods named node-setup-* to maintain access.
Why v1.82.8 was more dangerous
The .pth file mechanism in v1.82.8 deserves special attention because its blast radius extends far beyond LiteLLM usage.
Python loads .pth files from site-packages during interpreter initialization, before any user code runs. This means v1.82.8’s payload executed on every Python process on the infected system: web servers, data pipelines, CI/CD runners, developer tools, Jupyter notebooks, anything using the same Python installation.
For MSPs managing client environments with Python workloads, this distinction matters. A developer workstation that installed v1.82.8 would execute the malware every time any Python script ran, even if that script had nothing to do with LiteLLM. The same applies to CI/CD runners, production servers running Django or Flask applications, and any containerized Python workload sharing the same base image.
Package removal alone did not clean up the .pth file. Systems that installed v1.82.8 required manual inspection of site-packages for litellm_init.pth and verification that the persistence mechanisms (systemd service, sysmon.py backdoor) were also removed.
Indicators of compromise
If any system in your environment installed LiteLLM between March 24 10:39 UTC and 16:00 UTC, check for these artifacts.
Command and control infrastructure:
models.litellm.cloud(primary exfiltration endpoint)checkmarx.zone/83.142.209.11(payload download, C2 polling)scan.aquasecurity.org/45.148.10.212
Filesystem artifacts:
~/.config/sysmon/sysmon.py(backdoor)litellm_init.pthin anysite-packagesdirectory (v1.82.8 persistence)/tmp/pglogand/tmp/.pg_state(temporary staging files)tpcp.tar.gz(encrypted exfiltration archive)
Kubernetes indicators:
- Privileged pods named
node-setup-*that were not created by your team - Unauthorized service accounts created after March 24
Systemd persistence:
- User service named “System Telemetry Service”
What to do now
Immediate: check for exposure
- Verify whether any system installed LiteLLM v1.82.7 or v1.82.8 between March 24 10:39 UTC and 16:00 UTC. Check
pip freezeoutput,requirements.txthistory, Docker image layers, and CI/CD build logs. - Search for the filesystem artifacts listed above on all potentially affected hosts
- Review DNS logs for connections to the three C2 domains
- Inspect Kubernetes clusters for
node-setup-*pods or unauthorized service accounts - Check AWS CloudTrail, GCP Audit Logs, and Azure Activity Log for unexpected API calls from affected systems
Short-term: contain and remediate
- If any IOCs are found, treat the host as fully compromised. The credential harvester was comprehensive, and the malware actively used discovered credentials to probe cloud APIs and Kubernetes secrets.
- Rotate all credentials that were present on affected systems: SSH keys, cloud provider access keys, database passwords, API tokens, and any secrets stored in environment variables or configuration files
- Revoke and reissue TLS certificates whose private keys were on affected hosts
- Remove
litellm_init.pthfrom allsite-packagesdirectories and delete~/.config/sysmon/entirely - Pin LiteLLM to v1.82.6 or earlier (confirmed safe) and verify package checksums
- Rebuild Docker images from scratch with clean dependencies rather than patching existing containers
Ongoing: harden your supply chain
- Pin GitHub Actions to commit SHAs, not mutable version tags. This single change would have prevented the Trivy tag-replacement attack from propagating downstream.
- Scope PyPI tokens to specific packages using Trusted Publishers where possible
- Enable
pip --require-hashesfor production deployments to verify package integrity - Audit all CI/CD workflows for
pull_request_targetusage and ensure they do not expose secrets to untrusted code - Implement artifact verification using Sigstore or cosign where available
- Subscribe to security advisories for your critical dependencies
The bigger picture for MSPs
LiteLLM is an open-source AI gateway that provides a unified interface for calling multiple LLM providers (OpenAI, Anthropic, Cohere, Azure, and others) through a single API. It typically sits directly between applications and AI service providers, which means it has access to API keys and configuration for every connected model.
That positioning made it a high-value target. Compromising LiteLLM potentially exposed not just the host system’s credentials, but every AI provider API key routed through it.
For MSPs, this incident reinforces several realities:
AI tooling is now a supply chain risk. As AI integration accelerates across client environments, packages like LiteLLM, LangChain, and similar middleware become critical infrastructure components. LiteLLM sits between applications and multiple AI providers, so a single compromise exposed API keys for every connected model. These packages need the same dependency governance and monitoring as your core application frameworks.
Your CI/CD trust chain is only as strong as its weakest dependency. The attacker never found a code bug in LiteLLM. They exploited a misconfigured GitHub Actions trigger in Trivy, used the stolen credentials to compromise release tags, and pivoted through the CI/CD trust chain to reach the PyPI publishing token. Every link in that chain was a legitimate trust relationship operating as designed.
Speed of detection determines blast radius. Two to five hours of availability on a package with 3.4 million daily downloads means hundreds of thousands of potentially affected installations. Automated dependency monitoring and rapid incident response are the difference between a contained event and a full credential rotation across your client base.
Key takeaways
- Pin GitHub Actions to commit SHAs, not version tags. This single change would have broken the attack chain. Mutable tags allowed the attacker to silently replace Trivy with a malicious version. If you maintain CI/CD pipelines, audit this today.
- The
.pthpersistence mechanism is system-wide. Version 1.82.8 did not just compromise LiteLLM processes. It installed a hook that runs on every Python interpreter startup, turning the entire system into a backdoor regardless of what code is actually running. - Package removal is not sufficient remediation. The
.pthfile, systemd service, and sysmon.py backdoor all persist after uninstalling LiteLLM. Systems that installed the affected versions require manual IOC sweeps and, if compromised, full credential rotation. - Treat AI middleware as critical infrastructure. LiteLLM had access to every API key routed through it. As AI tooling becomes embedded in client environments, apply the same supply chain governance you would to your core frameworks.
- Non-atomic credential rotation creates attack windows. Aqua Security’s remediation after the initial Trivy compromise left a multi-day gap where the attacker retained valid credentials. When rotating secrets after an incident, ensure the rotation is complete and immediate.
Related reading
Huntress 2026 Cyber Threat Report: Key Findings for MSPs
Analysis of the Huntress 2026 Cyber Threat Report covering identity compromise, RMM abuse, ClickFix loaders, ransomware timelines, and a 30-day action plan.
Huntress Blocks Device Code Phishing from Railway
Huntress deployed a conditional access policy across ITDR-protected tenants to block device code phishing from Railway infrastructure using AI-generated lures.