Skip to main content
cybersecurity

LiteLLM 1.107.0 Supply Chain Attack: Microsoft Reveals Python-Based Credential Theft

Microsoft details how a compromised LiteLLM 1.107.0 release used Python startup hooks to launch credential-stealing code. The investigation covers exposed data, detection methods, indicators of compromise, and recovery steps.

Xcademia Team

Oct 24, 202614 min read1 views
Share:
LiteLLM 1.107.0 Supply Chain Attack: Microsoft Reveals Python-Based Credential Theft

Microsoft Security Research has published a technical analysis of a software supply-chain compromise involving LiteLLM version 1.107.0, which was published to the Python Package Index (PyPI) and distributed through official container images on October 21, 2026.


The compromised release included malicious Python startup files designed to run during normal interpreter initialisation. This meant an application did not need to import LiteLLM or actively use its AI gateway functionality for the malicious code to run. Starting Python in an affected environment could be enough.


Microsoft recovered a credential collector designed to gather sensitive information from developer tools, AI applications, cloud environments, browsers, and infrastructure. The code encrypted the collected data and tried to send it to an attacker-controlled endpoint. A separate loader was also designed to retrieve and execute additional Python code on Unix-based systems, although Microsoft did not confirm that this second-stage activity occurred.


The investigation also found endpoint activity on Windows and macOS consistent with the recovered collector's discovery, encryption, and outbound-connection behavior. In one Windows example, a routine Python command used to install an unrelated dependency activated the collector.


Microsoft warns that removing the LiteLLM application directory or deleting a release tag is not sufficient recovery. Organizations need to identify affected environments, investigate them without launching the potentially compromised interpreter, rebuild from verified artifacts, and rotate credentials that may have been accessible.


What Happened in the LiteLLM Supply Chain Attack?

LiteLLM is commonly deployed as a gateway between applications and model providers. Depending on its role and configuration, it may have access to model-provider API keys, database connection strings, workload identities, routing configuration, and tenant policy data.


The package is also used in developer workstations, build agents, test environments, and containers. This widened the potential exposure beyond organizations operating a production LiteLLM gateway.


According to the LiteLLM maintainers, stolen developer GitHub credentials were used to alter the release workflow and redirect it to the lookalike repository Berri-AI/litellm instead of the legitimate BerriAI/litellm repository. A credential associated with another developer account was then used to satisfy a production approval step.


Microsoft stated that it had not independently determined how the attacker initially accessed the upstream environment or obtained the credentials involved.


The compromised release introduced three malicious files:

  • cook.pth

  • cook.py

  • sitecustomize.py

These files were packaged under litellm-1.107.0.data/purelib/ in the compromised wheel. During installation, they were relocated into the Python environment's library directory, outside the normal LiteLLM application directory.

This location allowed the files to take advantage of Python's normal site initialization process. Python processes executable import statements in .pth files and, where applicable, attempts to import sitecustomize.

As a result, the malicious code could execute when Python started, even if the application did not directly import LiteLLM.

info-1

Two Malicious Execution Paths

Microsoft analyzed two execution paths in the affected package. One focused on collecting credentials and sensitive data. The other provided a separate mechanism for retrieving and executing additional code on Unix-based systems.


1. Credential collection through
cook.pth and cook.py

The first path began with a single executable line in cook.pth:

import cook

This imported cook.py, whose wrapper Base64-decoded and zlib-decompressed an embedded Python program before executing the recovered source. The program identified itself as PRIVCOLLECT and performed credential collection in a daemon thread.


Before starting the thread, the collector checked the inherited PRIVCOLLECT_ACTIVE environment variable. If the variable was nonempty, the collector returned without starting another collection run. Otherwise, it set the flag to limit duplicate collection in descendant processes.


After an upload returned HTTP 200, the code attempted to write a marker file:

/tmp/.pc_once_72129118c59f5636c0bb

These mechanisms were intended to limit repeated execution and record successful upload activity. They were not security containment measures.


Microsoft cautioned that the presence of the startup code alone did not prove that collection or upload had completed. A short-lived process could exit before the background thread finished. Failed marker-file writes or changes to temporary storage could also leave the marker absent.


2. A separate loader through sitecustomize.py

The second execution path used sitecustomize.py and was designed for Unix-based systems.

The loader attempted to acquire an exclusive lock at:

/tmp/remote_code_loader.lock

This limited concurrent instances on a host. The loader then detached into the background and periodically read a GitHub-hosted domain.txt file that acted as a pointer to an attacker-controlled server.


If the loader obtained a valid server address and resolved it successfully, it was designed to request /codepy, compile the returned content, and execute it as Python code within the affected environment.


This approach could let an attacker change the second-stage payload without publishing another compromised LiteLLM package.


However, Microsoft reported that the domain.txt file was empty when researchers examined it. They did not confirm second-stage retrieval or execution.


The distinction matters: the recovered loader contained the mechanism to retrieve and execute remote code, but the available evidence did not establish that this activity occurred successfully.


What Information Could the Credential Collector Access?

The recovered collector was designed to gather sensitive information across developer tools, AI applications, cloud services, browsers, and infrastructure. Its modules ran sequentially with independent error handling, allowing other collection attempts to continue when individual targets were unavailable or inaccessible.


The presence of a target in the recovered code does not establish that the collector successfully accessed or exfiltrated that information.

Target area

Data the recovered code was designed to access

Developer and AI tools

Selected authentication and configuration files for AI assistants, integrated development environments, GitHub Copilot, VS Code, and Model Context Protocol integrations.

Source control and package ecosystems

Git credentials, package-manager configuration, selected .env files, and files with private-key extensions.

Cloud and workload credentials

AWS and Azure CLI configuration, Google Cloud credential caches, Kubernetes service-account files, Docker configuration, mounted secrets, and attempts to retrieve AWS and Google Cloud metadata credentials.

Browsers and user histories

Credential-related data and browsing history from Chromium-family browsers and Firefox, plus shell, database-client, and interactive-tool histories. Password decryption depended on the operating system and data format.

Process environments

The collector's own environment and, on Linux, other process environments readable through procfs. This could expose secrets beyond variables explicitly configured for the LiteLLM process.

Private keys and infrastructure

Readable SSH material and selected GPG, TLS, CI/CD, Vault, and infrastructure-tool configuration.

LiteLLM proxy data

Selected credential and model-configuration records from two proxy database tables, subject to the collector's prerequisites.


LiteLLM proxy database collection

The recovered code included a separate database-collection module. When its prerequisites were satisfied, it launched a Python child process using Prisma to query selected fields from two LiteLLM proxy database tables.


The tables and fields included:

  • LiteLLM_CredentialsTable and credential_values

  • LiteLLM_ProxyModelTable and litellm_params

Each query was limited to 500 rows.


This behavior could be significant for organizations using LiteLLM proxy deployments with stored provider credentials or model configuration. Microsoft recommended that affected proxy hosts consider the exposure of stored provider credentials and the DATABASE_URL value when rotating accessible secrets.


The source does not establish that every compromised environment contained these tables, met the module's prerequisites, or successfully returned database records.


How the Payload Encrypted and Attempted to Exfiltrate Data

After collecting information, the payload serialized module results and host metadata as JSON. It then used a combination of symmetric and public-key encryption before attempting to transmit the resulting archive.


Microsoft's analysis identified the following process:

  1. The collector generated a 32-byte AES key and a 16-byte initialization vector.

  2. It encrypted the collection document using AES-256-CBC.

  3. It wrapped the AES key with an embedded 4,096-bit RSA public key using OAEP.

  4. The OpenSSL path attempted SHA-256 and then SHA-1 for OAEP, recording the selected digest in the resulting metadata.

  5. It packaged the encrypted data and metadata in a gzip-compressed tar archive.

  6. It attempted to send the archive through an HTTP POST request.

The archive contained three members:

Archive member

Contents

data.bin

Initialization vector and encrypted collection

key.bin

RSA-wrapped AES key

hdr.json

Plaintext envelope metadata

The upload routine attempted to send the archive to this defanged URL:

hxxp://www[.]litellm[.]dev/healthcheck

The request used application/octet-stream, a fixed browser-like User-Agent, and an X-SHA256 header containing a checksum of the request body. The routine retried requests and treated HTTP 200 as success.


For its OpenSSL operations, the collector created temporary directories beginning with .pc_e_, staged input and output files, and removed them after use.


These details provide investigators with potential evidence to correlate, including network activity, process execution, temporary cryptographic staging directories, file hashes, and activity associated with affected identities.

info-2

Microsoft's Incident Response and Recovery Guidance

Microsoft recommends a response that covers affected package artifacts, Python environments, running processes, credentials, and outbound network activity.


1. Find every affected copy

Search for LiteLLM 1.107.0 across:

  • Installed Python environments.

  • uv and pip caches.

  • Internal package mirrors and lock files.

  • Build outputs and container images.

  • Mutable container tags and relevant exposure windows.

Compare artifacts with the hashes published in Microsoft's indicators of compromise. Where possible, use container image digests rather than mutable tags because digests identify specific image content.


2. Do not run Python or pip in a suspected environment

Microsoft specifically warns against invoking the potentially compromised interpreter during investigation.


Starting Python could activate the malicious startup files, and running pip may invoke Python as well. A routine package operation could therefore trigger the payload before the investigation establishes what is present.


Isolate affected developer workstations, build agents, test systems, containers, and AI gateway hosts. Where operationally safe, stop running Python processes and prevent automation from restarting them.

Inspect the environment using trusted tools from a known-clean system.


3. Rebuild from verified artifacts

Microsoft recommends rebuilding affected environments from verified artifacts rather than assuming that deleting the LiteLLM application directory is enough.


Confirm that the following files have been removed from the Python environment's library path:

  • cook.pth

  • cook.py

  • sitecustomize.py

Because these files were installed outside the normal LiteLLM application directory, removing only the application files could leave malicious startup components behind.


4. Rotate accessible credentials and revoke sessions

From a known-clean machine, rotate or revoke credentials that may have been accessible to the compromised identity.


Microsoft identifies the following areas for review:

  • Model-provider API keys.

  • Cloud and workload credentials.

  • CI/CD secrets.

  • Source-control and registry tokens.

  • SSH and GPG keys.

  • AI coding-tool tokens.

  • Browser sessions.

  • Stored provider credentials and DATABASE_URL values on affected proxy hosts.

Revoke affected identity sessions as well. Rotating a password or key does not necessarily invalidate every active token or application session immediately.


5. Correlate evidence before declaring compromise

Microsoft advises against treating package presence or a generic filename as sufficient proof of malicious activity.


Investigators should correlate multiple signals, including:

  • Known file hashes.

  • Python process ancestry.

  • .pc_e_ cryptographic staging activity.

  • Network connections to the identified destination.

  • Workload identity activity.

  • Subsequent cloud or identity use.

The presence of the compromised package can indicate potential exposure. Correlated behavioral evidence can help establish whether malicious activity occurred.


6. Strengthen dependency and artifact controls

Microsoft recommends hash-pinned lock files, package and image provenance verification, immutable container digests, and reviewing packages before admitting them into internal mirrors.


These measures help organizations validate the artifacts they deploy and reduce reliance on mutable package references or unreviewed dependencies.


7. Restrict outbound network access

Developer workstations, build agents, test environments, containers, and AI gateway hosts should not have unrestricted outbound HTTP access unless required.


Microsoft recommends managed egress controls, denying unnecessary destinations, and allowlisting required services.


8. Enable endpoint protection

Microsoft recommends onboarding supported developer workstations, build agents, and AI gateway servers to Microsoft Defender for Endpoint.


It also advises enabling Microsoft Defender Antivirus real-time and cloud-delivered protection where supported.


Microsoft Defender Detection Coverage

As of October 22, 2026, Microsoft reported detection coverage for activity associated with the compromised LiteLLM release. Detection names and availability may change as protections are updated.


Microsoft Defender Antivirus

Microsoft listed the following signatures for malicious components associated with the compromised package:

  • Trojan:PyPI/Stealer.SA

  • Trojan:PyPI/LiteLlmSupplyChain.A

  • Trojan:PyPI/LiteLlmSupplyChain.B

  • Backdoor:PyPI/LiteLlmSupplyChain.C


Microsoft Defender for Endpoint

Related alerts included:

  • Suspicious script launched.

  • Suspicious network connection observed.

  • Possible theft of passwords and other sensitive web browser information.

  • Suspicious OpenSSL command launch.


Microsoft Defender for Cloud

Microsoft listed related detections for activity in Azure App Service and Kubernetes workloads:

  • OpenSSL activity associated with a possible LiteLLM compromise.

  • DNS lookup of a known malicious domain.


Microsoft Defender Vulnerability Management

Potentially exposed devices were surfaced in the Microsoft Defender portal under:

TVM-2026-0003

Microsoft also published a threat analytics report covering the incident. Its advanced hunting queries can help defenders investigate possible connections, startup-file hashes, database collection, cryptographic staging, and potential exposure.


Advanced Hunting Queries for Investigation

The following queries are from Microsoft's report. They are investigation leads, not standalone proof of compromise. Use an appropriate lookback period and correlate results with process, identity, and environment evidence.


1. Search for connections to the collector domain

This query normalizes URL and hostname observations before matching the domain. Microsoft notes that matches still require process and workload context.

DeviceNetworkEvents
| extend UrlForParsing = iff(RemoteUrl contains "://",
    RemoteUrl, strcat("http://", RemoteUrl))
| extend RemoteHost = trim_end(@"\.",
    tolower(tostring(parse_url(UrlForParsing).Host)))
| where RemoteHost in ("www.litellm.dev", "litellm.dev")
| project Timestamp, DeviceId, DeviceName, ActionType,
    RemoteUrl, RemoteIP, RemotePort, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId


2. Search for known startup-file hashes

Microsoft supplied hashes covering line-ending variants of the startup files. A missing SHA-256 field limits this hunt, and a generic filename is not an equivalent match.

DeviceFileEvents
| where SHA256 in~ (
    "9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25",
    "03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea",
    "34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa",
    "b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465",
    "7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb",
    "84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d")
| project Timestamp, DeviceId, DeviceName, ActionType,
    FileName, FolderPath, SHA256, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId


3. Search for the inline database-collection program

This query looks for combinations of sensitive table and field names, the query API, serialization, and output-suppression patterns. Microsoft notes that legitimate exports may overlap and that the recovered parent process's /proc prerequisite limits applicability.

DeviceProcessEvents
| where FileName startswith "python" or FileName startswith "platform-python"
| where strlen(ProcessCommandLine) <= 4096
| where ProcessCommandLine contains_cs "-c "
| where (ProcessCommandLine contains_cs "LiteLLM_CredentialsTable"
        and ProcessCommandLine contains_cs "credential_values")
    or (ProcessCommandLine contains_cs "LiteLLM_ProxyModelTable"
        and ProcessCommandLine contains_cs "litellm_params")
| where ProcessCommandLine contains_cs "query_raw"
| where ProcessCommandLine contains_cs "json.dumps("
    or ProcessCommandLine contains_cs "json.dump("
| where ProcessCommandLine contains_cs "os.devnull"
    and ProcessCommandLine contains_cs "os.dup2"
| project Timestamp, DeviceId, DeviceName, FileName,
    ProcessId, ProcessCreationTime, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId


4. Search for collector-like encryption staging

The staging prefix and encryption operations provide a behavioral lead. Microsoft cautions that these indicators alone do not prove an upload or uniquely identify malicious OpenSSL activity.

DeviceProcessEvents
| where FileName in~ ("openssl", "openssl.exe")
| where ProcessCommandLine contains_cs ".pc_e_"
| where (ProcessCommandLine contains_cs " enc "
        and ProcessCommandLine contains_cs "-aes-256-cbc")
    or ProcessCommandLine contains_cs " pkeyutl "
    or ProcessCommandLine contains_cs " rsautl "
| extend CryptoOperation = iff(
    ProcessCommandLine contains_cs " enc ", "AES packaging", "RSA wrapping")
| project Timestamp, DeviceId, DeviceName, FileName, CryptoOperation,
    ProcessId, ProcessCreationTime, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId


5. Identify potentially exposed devices

This query searches for devices associated with Microsoft's exposure identifier. A match indicates potential exposure, not confirmed exploitation or compromise.

DeviceTvmSoftwareVulnerabilities
| where CveId == "TVM-2026-0003"


6. Search cloud process events for encryption before possible exfiltration

This query identifies OpenSSL public-key encryption involving temporary staging paths in cloud process telemetry.

CloudProcessEvents
| where ProcessName == 'openssl' and ProcessCurrentWorkingDirectory has_any ('/runner/','/app','/tmp/')
    and ProcessCommandLine has_all ('pkeyutl','-encrypt','-pubin') and ProcessCommandLine contains '/tmp/.pc_'


MITRE ATT&CK Techniques Identified by Microsoft

Microsoft mapped the recovered code and observed activity to several MITRE ATT&CK techniques. The mappings describe behaviors identified in the analysis, not proof that every technique succeeded in every affected environment.

Tactic

Technique

Relevance to the incident

Initial Access

T1195.001, Compromise Software Dependencies and Development Tools

Malicious files were shipped in LiteLLM 1.107.0 wheels and images.

Persistence

T1546.018, Event Triggered Execution: Python Startup Hooks

cook.pth and sitecustomize.py executed during Python site initialization.

Execution

T1059.006, Command and Scripting Interpreter: Python

The collector ran in Python, including a child process used for database queries.

Defense Evasion

T1027.013, Encrypted/Encoded File

Collector source was embedded as Base64-encoded, zlib-compressed content.

Defense Evasion

T1140, Deobfuscate/Decode Files or Information

cook.py decoded and decompressed the collector at runtime.

Credential Access

T1552.001, Unsecured Credentials: Credentials in Files

The code read authentication and configuration files for developer, AI, and cloud tools.

Credential Access

T1552.004, Unsecured Credentials: Private Keys

The collector targeted selected SSH, GPG, and TLS key material.

Credential Access

T1552.005, Unsecured Credentials: Cloud Instance Metadata API

It requested AWS and Google Cloud credentials from metadata services. Returned credentials were not confirmed in Microsoft's telemetry.

Credential Access

T1555.003, Credentials from Password Stores: Credentials from Web Browsers

The code copied browser databases and supported selected Chromium password recovery on Windows.

Discovery

T1082, System Information Discovery

systeminfo was launched by Python in an observed Windows sequence.

Discovery

T1016, System Network Configuration Discovery

ipconfig, route, arp, and netstat were launched by the same Python process.

Collection

T1005, Data from Local System

The collector targeted local histories, environment variables, and configuration.

Command and Control

T1102.001, Web Service: Dead Drop Resolver

The loader read a server address from a specific GitHub-hosted file.

Command and Control

T1105, Ingress Tool Transfer

The loader could retrieve Python code from /codepy, but retrieval and execution were not confirmed.


Indicators of Compromise

Microsoft published the following defanged network indicators, file paths, and SHA-256 hashes. Use them alongside endpoint, process, identity, and network evidence rather than treating an individual match as a complete verdict.


Network indicators

Indicator

Type

Reported role

www[.]litellm[.]dev

Domain

Exfiltration domain

hxxp://www[.]litellm[.]dev/healthcheck

URL

Exfiltration URL

hxxps://raw[.]githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txt

URL

Command-and-control dead-drop URL

The second-stage loader's retrieval and execution were not confirmed. Microsoft reported that the referenced domain.txt file was empty when researchers examined it.


Startup-file hashes

File

SHA-256

cook.py variant

9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25

cook.py Windows wheel variant

03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea

sitecustomize.py variant

34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa

sitecustomize.py Windows wheel variant

b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465

cook.pth

7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb

cook.pth variant

84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d


Compromised LiteLLM wheel hashes

Package artifact

SHA-256

litellm-1.107.0-cp310-abi3-macosx_10_12_x86_64.whl

7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86d

litellm-1.107.0-cp310-abi3-macosx_11_0_arm64.whl

0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1a

litellm-1.107.0-cp310-abi3-manylinux_2_28_aarch64.whl

668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6

litellm-1.107.0-cp310-abi3-manylinux_2_28_x86_64.whl

462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7

litellm-1.107.0-cp310-abi3-musllinux_1_2_aarch64.whl

c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054

litellm-1.107.0-cp310-abi3-musllinux_1_2_x86_64.whl

1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00

litellm-1.107.0-cp310-abi3-win_amd64.whl

12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484


Additional file indicators

File path

Reported role

/tmp/remote_code_loader.lock

Lock file created by the background loader

/tmp/.pc_once_72129118c59f5636c0bb

Marker file attempted after stolen data was sent


Conclusion: The Risk Extended Beyond Active LiteLLM Deployments

The LiteLLM 1.107.0 incident demonstrates how a compromised software package can create exposure beyond the application it was designed to support. By using Python startup hooks, the malicious release could activate during interpreter initialization in an affected environment, including systems where LiteLLM itself was never imported.


Microsoft recovered a credential collector designed to target sensitive information across developer tools, AI applications, cloud environments, browsers, and infrastructure. It also identified a separate loader capable of retrieving and executing additional Python code, although that second-stage activity was not confirmed.


Organizations that installed, mirrored, or built images containing the affected release should investigate more than the application directory. They need to identify affected artifacts, avoid starting the potentially compromised interpreter, correlate available evidence, rebuild from verified sources, and rotate credentials that may have been accessible.


The incident also highlights the importance of dependency verification, package provenance, immutable image references, and controlled outbound network access. These controls cannot eliminate every supply-chain risk, but they can help organizations identify what they deploy and respond more effectively when a dependency is compromised.

#Cybersecurity#SupplyChainAttack#LiteLLM#PythonSecurity#CredentialTheft#ThreatIntelligence#AISecurity#MicrosoftSecurity

About the Author

X
Xcademia Team
Share:
Learn to stop attacks like this oneCybersecurity Engineer Bootcamp: live cohorts enrolling now, with optional Career+ support.