LiteLLM 1.107.0 Supply-Chain Credential Theft — Sentinel Threat Hunts

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.

Leave a Reply