Threat Overview
Attackers compromised LiteLLM's release workflow using developer GitHub CLI OAuth credentials and built a malicious release from an attacker-controlled lookalike source repository. Official PyPI wheels and container tags briefly delivered a credential stealer and a Python backdoor loader. The payload plants cook.pth, cook.py, and sitecustomize.py in site-packages, which can execute when Python starts, even without importing LiteLLM. Datadog documented exfiltration to http://www.litellm.dev/healthcheck and a GitHub-hosted dead-drop reference for the second stage. The release pipeline was contained; this is a supply-chain compromise, not a vulnerability in all LiteLLM versions.
References
LiteLLM incident report — October 21, 2026
Datadog Security Labs — October 21, 2026
BleepingComputer — October 22, 2026
Impacted Systems
Vendor/product: LiteLLM open-source Python package and LiteLLM proxy Docker images; Linux, Windows, and macOS Python environments, containers, CI/CD and AI gateway hosts. Affected PyPI: litellm==1.107.0 (all seven wheels) available October 21, 2026, 11:39:51–13:23 UTC. Affected Docker Hub/GHCR: tags v1.107.0, latest, main-latest, main-stable during approximately 11:46:56–14:20 UTC (GHCR tags unavailable by 13:51 UTC); malicious Docker image index sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e. Unaffected: private LiteLLM enterprise registry; vendor states versions preceding 1.107.0 were not impacted by this incident. Safe rollback: pin to 1.106.2 and rebuild. Prerequisite: install and execute compromised wheel or image; no Internet-facing service required for initial compromise, but outbound access increases exfiltration risk.
Why this matters
LiteLLM commonly holds cloud IAM credentials, LLM provider API keys, database secrets, and developer tokens. A single affected proxy or build agent can expose multiple production systems, even when the malicious artifact was available for only hours.
Exploitation Status
LiteLLM's October 21 incident report confirms compromise of its release pipeline, malicious wheels/images, stolen developer credentials, and removal windows. Datadog's October 21 analysis documents the startup-hook files, exfiltration destination, dead-drop path, marker files, and exact malicious wheel hashes. Datadog reports no observed second-stage payload in the wild at its publication; a RAT loader's presence must not be conflated with confirmed operator execution.
What this hunt looks for
Layered Sentinel hunts cover confirmed indicators, product-scoped activity, and post-compromise behavior. Queries are not customer findings; detection confidence and missing telemetry are described below.
Required logs
CommonSecurityLog; DeviceFileEvents; DeviceFileEvents;DeviceProcessEvents; DeviceNetworkEvents; DeviceProcessEvents
Hunt 1: Confirmed malicious Python startup-file creation
Required tables: DeviceFileEvents | Signal: High. The specific cook.pth/cook.py filenames are confirmed in the October 21 malicious LiteLLM release; validate file content/installation context.
DeviceFileEvents
| where TimeGenerated >= datetime(2026-10-21)
| where FileName in~ ("cook.pth", "cook.py")
| where FolderPath contains "site-packages" or FolderPath contains "dist-packages"
| project TimeGenerated, DeviceName, ActionType, FolderPath, FileName, InitiatingProcessFileName, InitiatingProcessCommandLine, SHA256
| order by TimeGenerated desc
Hunt 2: Confirmed stealer execution marker or backdoor lock
Required tables: DeviceFileEvents | Signal: High. Datadog documented these artifacts. Missing markers do not rule out execution; container cleanup can remove them.
DeviceFileEvents
| where TimeGenerated >= datetime(2026-10-21)
| where FileName in~ (".pc_once_72129118c59f5636c0bb", "remote_code_loader.lock")
| project TimeGenerated, DeviceName, ActionType, FolderPath, FileName, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by TimeGenerated desc
Hunt 3: Malicious LiteLLM wheel SHA-256 indicators
Required tables: DeviceFileEvents | Signal: High. Exact Datadog-published wheel hashes; MDE may not hash all archive files.
let MaliciousHashes=dynamic(["7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86d","0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1a","462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7","668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6","1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00","c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054","12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484"]);
DeviceFileEvents
| where TimeGenerated >= datetime(2026-10-21)
| where isnotempty(SHA256) and set_has_element(MaliciousHashes,tolower(SHA256))
| project TimeGenerated, DeviceName, FileName, FolderPath, SHA256, ActionType, InitiatingProcessFileName
| order by TimeGenerated desc
Hunt 4: Python process connecting to confirmed exfiltration domain
Required tables: DeviceNetworkEvents | Signal: High. Domain litellm.dev is a confirmed exfiltration destination in this incident; legitimate LiteLLM docs use a different domain. DNS/FQDN enrichment required.
DeviceNetworkEvents
| where TimeGenerated >= datetime(2026-10-21)
| where RemoteUrl contains "litellm.dev"
| where InitiatingProcessFileName has_any ("python", "python3", "python.exe", "python3.exe")
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteUrl, RemoteIP, RemotePort, ActionType
| order by TimeGenerated desc
Hunt 5: Firewall or proxy connections to LiteLLM exfiltration domain
Required tables: CommonSecurityLog | Signal: High. CEF fields require URL/FQDN logging; an IP-only firewall feed cannot match this indicator.
CommonSecurityLog
| where TimeGenerated >= datetime(2026-10-21)
| extend Url=tostring(RequestURL), Host=tostring(DestinationHostName), Msg=tostring(Message)
| where Host contains "litellm.dev" or Url contains "litellm.dev" or Msg contains "litellm.dev"
| project TimeGenerated, SourceIP, DestinationIP, DestinationHostName, DestinationPort, RequestURL, DeviceVendor, DeviceProduct, DeviceAction, Message
| order by TimeGenerated desc
Hunt 6: LiteLLM 1.107.0 package installation command
Required tables: DeviceProcessEvents | Signal: High. Strong exposure evidence but an install/pull does not by itself prove malicious code ran. Command-line logs may be absent in containerized deployments.
DeviceProcessEvents
| where TimeGenerated >= datetime(2026-10-21)
| where ProcessCommandLine contains "litellm" and ProcessCommandLine contains "1.107.0"
| where FileName in~ ("pip", "pip3", "pip.exe", "python", "python3", "python.exe", "python3.exe", "uv", "uv.exe", "docker", "docker.exe", "podman")
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine, InitiatingProcessFileName, AccountName
| order by TimeGenerated desc
Hunt 7: Backdoor dead-drop URL in proxy request telemetry
Required tables: CommonSecurityLog | Signal: High. Confirmed backdoor dead-drop path. Requires decrypted/proxy HTTP URL visibility; ordinary firewall IP/hostname records will not contain the path.
CommonSecurityLog
| where TimeGenerated >= datetime(2026-10-21)
| extend Url=tostring(RequestURL), Msg=tostring(Message)
| where Url contains "letters9813/pythonclient-test" or Msg contains "letters9813/pythonclient-test"
| project TimeGenerated, SourceIP, DestinationIP, DestinationHostName, RequestURL, DeviceAction, Message
| order by TimeGenerated desc
Hunt 8: Python process starts after malicious startup-file creation
Required tables: DeviceFileEvents;DeviceProcessEvents | Signal: High. Strong follow-up indicating Python was launched after malicious startup-hook placement. Host-level correlation does not prove it used the same Python environment; confirm installation paths.
let Marker=DeviceFileEvents
| where TimeGenerated >= datetime(2026-10-21)
| where FileName =~ "cook.pth" and (FolderPath contains "site-packages" or FolderPath contains "dist-packages")
| project DeviceId, DeviceName, MarkerTime=TimeGenerated, MarkerPath=FolderPath;
DeviceProcessEvents
| where TimeGenerated >= datetime(2026-10-21)
| where FileName in~ ("python", "python3", "python.exe", "python3.exe", "pip", "pip3", "pip.exe")
| project DeviceId, ExecutionTime=TimeGenerated, FileName, ProcessCommandLine, AccountName
| join kind=inner Marker on DeviceId
| where ExecutionTime between (MarkerTime .. MarkerTime + 24h)
| project MarkerTime, ExecutionTime, DeviceName, MarkerPath, FileName, ProcessCommandLine, AccountName
| order by ExecutionTime desc
Detection Notes
Highest-signal: cook.pth/cook.py in Python site-packages, exact wheel SHA-256, confirmed exfil domain, and run-once marker. sitecustomize.py alone is not malicious. An installation command or wheel download confirms potential exposure but not execution. The marker may disappear with container cleanup; absent markers cannot clear an exposed host. DeviceNetworkEvents may omit FQDN and cannot see HTTP path; CommonSecurityLog may contain only IPs. Cloud IAM misuse after theft requires separate, customer-scoped cloud audit hunts and a known affected principal; generic GetCallerIdentity alerts would be noisy and are intentionally excluded.
Visibility is limited to telemetry actually ingested into Microsoft Sentinel; no customer workspace was queried for this publication.