TeamPCP’s LiteLLM Supply-Chain Attack Targets Credentials and Kubernetes Clusters

Summary
A technical investigation details how trojanized LiteLLM packages 1.82.7 and 1.82.8 steal credentials, can compromise Kubernetes clusters, and use AdaptixC2 and Havoc infrastructure. Researchers counted 33,688 internet-facing deployments, not all confirmed compromised.
Key points
- TeamPCP published trojanized LiteLLM versions 1.82.7 and 1.82.8 to PyPI on March 24; both versions were later removed.
- The malware harvests credentials from files and environment variables, including cloud, SSH, Kubernetes, database, CI/CD, and API secrets; it can also query AWS IMDS for IAM role credentials.
- In Kubernetes environments, stolen service-account tokens let the malware dump secrets across namespaces and deploy privileged pods across cluster nodes.
- A persistent systemd service polls checkmarx[.]zone for payloads; the investigation linked the operation to AdaptixC2 at 83.142.209[.]11 and Havoc at 45.148.10[.]212.
- Encrypted stolen data is sent to models.litellm[.]cloud; researchers identified 33,688 internet-facing LiteLLM deployments, though not all were confirmed to have installed the compromised versions.
- The investigation recommends checking for the listed persistence files, Kubernetes pods, and network indicators; if compromised, rotate credentials accessible to the affected host and review package controls and cloud permissions.
Article Details
- Attack Vectors
- Two trojanized Python package releases, versions 1.82.7 and 1.82.8, executed an obfuscated payload during installation. Both releases were subsequently removed from the package registry.
- An injected Python statement launched a base64-encoded payload in a detached subprocess, allowing installation to finish while malicious execution continued.
- The payload collected sensitive files, environment variables, shell histories, private keys, cloud credentials, database connections, wallet configurations, and CI/CD secrets.
- The malware retrieved instance role credentials through IMDSv2 and used authenticated cloud API requests to enumerate secret stores.
- Stolen service account tokens enabled cluster-wide secret collection and deployment of privileged pods on every node. Host filesystem mounts and chroot allowed the backdoor to be installed on the underlying hosts.
- A persistent user service polled an attacker endpoint approximately every 50 minutes, downloaded replacement binaries, and launched them as detached processes.
- Collected information was encrypted, bundled, and uploaded using an HTTPS POST disguised as an AI model API request.
- The researchers counted 33,688 internet-facing deployments, but explicitly cautioned that public exposure did not establish that every deployment installed a compromised release.
- Defensive Notes
- Check for ~/.config/sysmon/sysmon.py and ~/.config/systemd/user/sysmon.service as persistence artifacts.
- Check for /tmp/pglog, /tmp/.pg_state, and /tmp/tpcp.tar.gz as downloaded-agent, loader-state, and encrypted-exfiltration artifacts.
- Audit the kube-system namespace for privileged pods matching node-setup-*. The article advises treating every cluster node as compromised if these pods are found.
- Review network logs against the reported exfiltration, polling, and C2 indicators.
- If compromise artifacts are present, or either trojanized release was installed, rotate all credentials accessible to the host, including private keys, cloud tokens, database passwords, service account credentials, and API keys.
- Pin package versions and verify package hashes rather than automatically installing the latest release.
- Restrict outbound connectivity from build environments and CI/CD runners.
- Apply least privilege to instance roles and cluster service accounts.
- Require IMDSv2 with a hop limit of 1 on EC2 instances.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| DOMAIN | checkmarx[.]zone | TeamPCP polling domain used by the persistent loader to obtain payload download URLs. |
| DOMAIN | models[.]litellm[.]cloud | Attacker exfiltration domain receiving encrypted credentials and other collected data. |
| IPV4 | 45[.]148[.]10[.]212 | Havoc C2 TeamServer used by the attack's Demon agent. |
| IPV4 | 46[.]151[.]182[.]203 | Server linked by certificate to the exfiltration domain; researchers assess it as an exfiltration node or possible backup infrastructure. |
| IPV4 | 83[.]142[.]209[.]11 | AdaptixC2 TeamServer identified by Hunt.io and used by agents in the attack. |
| SHA256 | 71e35aef03099cd1f2d6446734273025a163597de93912df321ef118bf135238 | File hash explicitly listed in the investigation's IOC table; the associated file is not identified. |
| SHA256 | 95a13f33699558f2bbe3afb631900076f84dd6de60c656a1d0ada2b9bae9c4c8 | Redacted HTTP response-header fingerprint used to link the primary C2 server with additional suspected infrastructure; not a malware file hash. |
| URL | hxxps[:]//models[.]litellm[.]cloud/ | HTTPS POST destination for the encrypted exfiltration bundle. |
MITRE ATT&CK
T1005 · Data from Local SystemThe collector read sensitive local files and gathered their contents for exfiltration.T1016 · System Network Configuration DiscoveryThe malware ran ip addr and ip route to collect interface and routing information.T1027 · Obfuscated Files or InformationThe initial malicious statement concealed its first-stage payload using base64 encoding.T1033 · System Owner/User DiscoveryThe malware ran whoami to identify the account under which it was executing.T1036.005 · Match Legitimate Resource Name or LocationThe service description 'System Telemetry Service' and node-setup pod names were chosen to resemble legitimate infrastructure.T1048 · Exfiltration Over Alternative ProtocolThe encrypted bundle was uploaded by curl POST to a dedicated HTTPS exfiltration endpoint separate from the loader's polling domain.T1059.006 · PythonInjected Python code executed the credential collector and persistent sysmon.py loader.T1071.001 · Web ProtocolsThe loader used an HTTP polling resource, while the AdaptixC2 agent communicated over HTTPS on port 443.T1078.004 · Cloud AccountsAWS credentials found in environment variables enabled authenticated cloud API abuse using the malware's custom request-signing implementation.T1082 · System Information DiscoveryThe malware ran hostname and uname -a to fingerprint the compromised host.T1083 · File and Directory DiscoveryThe walk() helper recursively searched directories for sensitive files matching selected names or extensions.T1105 · Ingress Tool TransferThe persistent loader retrieved payload URLs, downloaded new binaries to /tmp/pglog, and launched them.T1140 · Deobfuscate/Decode Files or InformationThe encoded first-stage payload was unpacked into a Python wrapper that continued execution.T1195.001 · Compromise Software Dependencies and Development ToolsTeamPCP published trojanized LiteLLM dependency releases 1.82.7 and 1.82.8 to PyPI.T1543.002 · Systemd ServiceThe malware created and enabled sysmon.service as a persistent systemd user service with automatic restart.T1550.001 · Application Access TokenA stolen Kubernetes service account token authenticated the malware's direct requests to the cluster API.T1552.001 · Credentials In FilesThe collector read cloud configuration files, environment files, database connection files, registry authentication files, and CI/CD secrets.T1552.003 · Shell HistoryThe collector harvested shell command histories that could contain credentials or connection strings.T1552.004 · Private KeysThe collector stole SSH private keys, SSH host keys, and TLS private keys.T1552.005 · Cloud Instance Metadata APIThe malware requested an IMDSv2 session token and retrieved temporary credentials for the instance's IAM role.T1552.007 · Container APIUsing a service account token, the malware queried the Kubernetes API and dumped secrets across all namespaces.T1560.001 · Archive via UtilityCollected data was packaged into a tar bundle before exfiltration.T1560.003 · Archive via Custom MethodThe malware encrypted collected data with AES-256-CBC and wrapped the session key with an embedded RSA-4096 public key.T1610 · Deploy ContainerThe malware deployed privileged node-setup-{hostname} pods to every cluster node, including control plane nodes.T1611 · Escape to HostPrivileged pods mounted the host root filesystem and used chroot to install the backdoor on the underlying host.T1613 · Container and Resource DiscoveryThe Kubernetes module enumerated cluster nodes before deploying malicious pods to them.
Threat Actors
Vendors
Aqua Securitycommunity flagged it fast. This was the third supply chain target from TeamPCP in March, following Aqua Security's Trivy and Checkmarx's GitHub Actions.Checkmarxfast. This was the third supply chain target from TeamPCP in March, following Aqua Security's Trivy and Checkmarx's GitHub Actions.Ghosty Networks LLCFigure 21: Hunt.io analysis of 83.142.209[.]11 showing Ghosty Networks LLC hosting, open ports, and AdaptixC2 detection on port 443.The primary AdaptixC2 server sits at 83.142.209[.]11, hosted by Ghosty Networks LLC inSpaceship, Inc.2026, just one day before the malicious packages appeared on PyPI. The domain was registered through Spaceship, Inc. and uses their default nameservers. The timing of registration closely aligns with the attackTECHOFF SRV LIMITEDFigure 23: Association tab for 83.142.209[.]11 revealing a linked IOC at 45.148.10[.]212 hosted by TECHOFF SRV LIMITED in the Netherlands.The Associations tab for 83.142.209[.]11 surfaces a critical connection. Our
Products
EC209: Custom AWS Signature V4 request signing implementation embedded in the malware.The first target is the EC2 Instance Metadata Service (IMDS). The malware requests a session token from the IMDSv2, then uses it toGitHub Actionsthe third supply chain target from TeamPCP in March, following Aqua Security's Trivy and Checkmarx's GitHub Actions.Kubernetesat the time of our scan. This report covers the malware's execution flow from initial install to Kubernetes cluster takeover, the dual C2 setup running AdaptixC2 and Havoc, and the infrastructure pivots thatLiteLLMOn March 24, a threat actor tracked as TeamPCP published two trojanized versions of the LiteLLM Python package (1.82.7 and 1.82.8) to the PyPI repository. The community flagged it fast. This was the third supply chainPyPIas TeamPCP published two trojanized versions of the LiteLLM Python package (1.82.7 and 1.82.8) to the PyPI repository. The community flagged it fast. This was the third supply chain target from TeamPCP in March,Secrets ManagerOn AWS hosts, it also queries IMDS for IAM role credentials and enumerates Secrets Manager and SSM Parameter Store.SSM Parameter StoreOn AWS hosts, it also queries IMDS for IAM role credentials and enumerates Secrets Manager and SSM Parameter Store.Trivyflagged it fast. This was the third supply chain target from TeamPCP in March, following Aqua Security's Trivy and Checkmarx's GitHub Actions.
Tools
AdaptixC2malware's execution flow from initial install to Kubernetes cluster takeover, the dual C2 setup running AdaptixC2 and Havoc, and the infrastructure pivots that revealed a third server tied to the exfiltration domain.curlRSA-4096 public key and the encryption wrapper that packages stolen data.The encrypted bundle is sent via curl POST to https://models.litellm[.]cloud/, with headers mimicking an API call to an AI model endpoint. TheHavocflow from initial install to Kubernetes cluster takeover, the dual C2 setup running AdaptixC2 and Havoc, and the infrastructure pivots that revealed a third server tied to the exfiltration domain.OpenSSLmalware encrypts everything before sending it out. It generates a random 32-byte AES session key using OpenSSL, encrypts the collected data with AES-256-CBC, then encrypts the session key itself with an RSA-4096
Countries
LuxembourgA persistent systemd service polls checkmarx[.]zone every 50 minutes for new payloads, feeding two independent C2 frameworks: AdaptixC2 (83.142.209[.]11, Luxembourg) and Havoc (45.148.10[.]212, Netherlands).NetherlandsA persistent systemd service polls checkmarx[.]zone every 50 minutes for new payloads, feeding two independent C2 frameworks: AdaptixC2 (83.142.209[.]11, Luxembourg) and Havoc (45.148.10[.]212, Netherlands).