← All hunts high TLP:CLEAR Part 2 of 2

LiteLLM Remote Code Loading and Exfiltration

An adversary is using malicious Python startup hooks in a compromised package to execute a remote code loader and exfiltrate credentials from developer and production environments.

Based on research by Microsoft 2026-10-24 9 steps · 3 queries T1041 T1059.006 T1195.002

Brief

Why hunt for LiteLLM behavior

Microsoft recently detailed a supply chain attack in Inside the LiteLLM 1.107.0 supply chain compromise. The adversary injected malicious startup hooks into the package to facilitate remote code execution and credential exfiltration. While detection rules often target the installation of the package itself, this hunt focuses on the subsequent execution of the payload. Identifying which hosts actually reached the exfiltration stage is critical for response, as it distinguishes between a dormant installation and a successful breach.

How the hunt flows

The hunt begins by narrowing the scope to the vulnerable software. The first step queries the software inventory surface to list every host running LiteLLM version 1.107.0. This provides the primary list of targets for deeper behavioral analysis.

After identifying vulnerable hosts, the hunt pivots to network telemetry. It searches DNS logs for Python or Pip processes resolving specific domains used for exfiltration or loader configuration. This step looks for connections to litellm.dev or GitHub raw content domains that occur outside of standard package management windows.

Simultaneously, the hunt examines file system activity for staging artifacts. The adversary uses specific filenames like data.bin and key.bin, and stages data in hidden directories beginning with .pc_e_. The hunt also looks for a specific lock file used by the remote code loader to prevent multiple executions. These indicators confirm that the malicious hooks successfully activated on the endpoint.

An analyst or automated agent then correlates these signals. A host with both the vulnerable package version and corresponding network or file activity receives a high-confidence verdict for compromise. This allows the team to prioritize these specific systems for isolation and secret rotation.

Blind spots

This hunt has two primary blind spots. First, the payload attempts to delete its temporary staging files and directories after exfiltration. If the file system telemetry does not capture the creation event or lacks deletion records, the on-disk evidence may vanish. Second, short-lived Python processes might initiate lookups and exit before the endpoint collector captures the full process metadata, potentially leaving the DNS activity unattributed to a specific process name.

In this series

Steps

  1. Identify LiteLLM 1.107.0 installations

    Query · scoping

    Locate hosts with the compromised version of LiteLLM to focus the hunt on the most likely points of compromise.

    reads hb_software_inventorysql
    SELECT device_hostname, package_name, package_version, install_path, collected_at FROM hb_software_inventory WHERE LOWER(package_name) = 'litellm' AND package_version = '1.107.0'

    What a hit looks like. A list of hosts running the compromised package. Silence means the specific version was not found in the current inventory snapshot.

  2. Python DNS lookups to C2 infrastructure

    Query · baseline

    Identify Python processes resolving the exfiltration domain or the loader configuration source.

    reads hb_dns_activitysql
    SELECT device_hostname, process_name, query_hostname, COUNT(*) AS count, MIN(time) AS first_seen FROM hb_dns_activity WHERE instr(',' || '{{c2_domains}}' || ',', ',' || LOWER(query_hostname) || ',') > 0 AND (LOWER(process_name) LIKE '%python%' OR LOWER(process_name) LIKE '%pip%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name, query_hostname

    What a hit looks like. Python or pip processes communicating with the domains named in the report. Silence means no such resolutions were logged within the window.

  3. Malicious staging and loader artifacts

    Query · detection candidate

    Find transient files used to stage exfiltrated data or the lock file used by the remote loader.

    reads hb_file_activitysql
    SELECT device_hostname, process_name, file_path, file_name, activity_name, time FROM hb_file_activity WHERE (LOWER(file_path) LIKE '%/.pc_e_%' OR instr(',' || '{{exfil_artifacts}}' || ',', ',' || LOWER(file_name) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. The presence of staging files (data.bin, key.bin, hdr.json) or the loader lock file on disk. Silence is expected if the payload successfully cleaned up or never activated.

  4. Triage compromise signals

    Agent triage

    Analyze the relationship between the vulnerable software installation and the observed behavioral artifacts.

  5. Route on activity verdict

    Decision

    Determine the appropriate response path based on the agent verdict.

  6. Isolate compromised host

    Response action

    Prevent further exfiltration and second-stage loading by isolating the host.

  7. Analyst review

    Analyst task

    Conduct a detailed review of host signals to confirm the compromise and evaluate risk.

  8. Hunt close-out

    Analyst task

    Complete the investigation and document findings.

Coverage

Scenario coverage

StageCoveredHow, or why not
Remote Code Loader Execution
T1059.006
Yes dns-to-c2-infrastructure, staging-and-loader-artifacts
Encrypted Data Exfiltration
T1041
Yes dns-to-c2-infrastructure, staging-and-loader-artifacts
Compromised Package Distribution
T1195
Out of scope Handled by the distribution-focused hunt in this series.
Python Startup Hook Persistence
T1574
Out of scope Handled by the persistence-focused hunt in this series.
Credential and Sensitive Data Collection
T1555 · T1083
Out of scope Belongs to another part of the 'Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks' series.

Blind spots

  • Needs hb_file_activity with deletion records. The payload attempts to remove its temporary staging files and directories (.pc_e_*) after upload, which may leave no persistent on-disk evidence. It would answer whether malicious staging files were created and then deleted.
  • Needs hb_dns_activity with high-frequency capture. A Python process that starts, initiates a thread, and exits quickly may not be captured by snapshot-based telemetry or may exit before the collector finishes its upload. It would answer whether exfiltration attempts occurred in short-lived processes.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
c2_domainslist[domain]www.litellm.dev, litellm.dev, raw.githubusercontent.comKnown domains used for exfiltration and loader configuration.
exfil_artifactslist[string]data.bin, key.bin, hdr.json, remote_code_loader.lockSpecific filenames used by the exfiltration and loader components.
lookback_daysnumber14Days of history to examine.
scope_hostslist[host]—Hosts to scope; leave empty to hunt across the entire estate.

Telemetry

SourceCategoryTelemetry
Endpoint telemetry (hb_ surfaces)endpointendpoint

Source

Download hunt.md Definition (JSON) An open hunt.md file; it runs anywhere that reads the format.
---
analysis: 'This hunt correlates a supply-chain installation with its behavioral consequences:
  processes that are usually local-only (like Python) initiating lookups to configuration
  sources and staging files. A single rule on the C2 domain may fail as infrastructure
  rotates, while this hunt focuses on the persistent behavioral indicators of the
  payload''s lifecycle.'
blind_spots:
- id: transient-artifact-deletion
  question: whether malicious staging files were created and then deleted
  requires: hb_file_activity with deletion records
  risk: The payload attempts to remove its temporary staging files and directories
    (.pc_e_*) after upload, which may leave no persistent on-disk evidence.
  stage: remote-code-loader-execution
- id: short-lived-processes
  question: whether exfiltration attempts occurred in short-lived processes
  requires: hb_dns_activity with high-frequency capture
  risk: A Python process that starts, initiates a thread, and exits quickly may not
    be captured by snapshot-based telemetry or may exit before the collector finishes
    its upload.
  stage: data-exfiltration
coverage:
- stage: remote-code-loader-execution
  status: covered
  steps:
  - dns-to-c2-infrastructure
  - staging-and-loader-artifacts
- stage: data-exfiltration
  status: covered
  steps:
  - dns-to-c2-infrastructure
  - staging-and-loader-artifacts
- reason: Handled by the distribution-focused hunt in this series.
  stage: malicious-package-distribution
  status: out_of_scope
- reason: Handled by the persistence-focused hunt in this series.
  stage: python-startup-hook-persistence
  status: out_of_scope
- reason: 'Belongs to another part of the ''Inside the LiteLLM 1.107.0 supply chain
    compromise: Credential theft through Python startup hooks'' series.'
  stage: credential-harvesting
  status: out_of_scope
guardrails:
  claims: no_unsupported
  evidence: citation_required
  missing_data: not_benign
  telemetry: untrusted
hunt:
  applicability: campaign-specific
  handoff: promote-to-detection
  justification: Supply chain compromises like LiteLLM facilitate direct credential
    theft and provide a remote execution path; identifying where the payload successfully
    exfiltrated data is critical for immediate credential revocation.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An adversary is using malicious Python startup hooks in a compromised
  package to execute a remote code loader and exfiltrate credentials from developer
  and production environments.
labels:
- hunt
- attack.t1041
- attack.t1059.006
- attack.t1195.002
- credential access
- execution
- exfiltration
- initial access
- persistence
name: LiteLLM Remote Code Loading and Exfiltration
parameters:
  c2_domains:
    default:
    - www.litellm.dev
    - litellm.dev
    - raw.githubusercontent.com
    description: Known domains used for exfiltration and loader configuration.
    from:
      kind: article
      observed: '2026-10-23'
      ref: msrc-blog-litellm
    type: list[domain]
  exfil_artifacts:
    default:
    - data.bin
    - key.bin
    - hdr.json
    - remote_code_loader.lock
    description: Specific filenames used by the exfiltration and loader components.
    from:
      kind: article
      observed: '2026-10-23'
      ref: msrc-blog-litellm
    type: list[string]
  lookback_days:
    default: '14'
    description: Days of history to examine.
    type: number
  scope_hosts:
    default: []
    description: Hosts to scope; leave empty to hunt across the entire estate.
    type: list[host]
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://www.microsoft.com/en-us/security/blog/2026/10/23/inside-the-litellm-1-107-0-supply-chain-compromise-credential-theft-through-python-startup-hooks/
    gates:
    - dry-run
    - lint
    model: hb_google/gemini-3-flash-preview
rationale: Focus on developer workstations, CI/CD runners, and production gateway
  hosts identified by the software inventory scan.
references:
- name: 'MSRC Blog: Inside the LiteLLM 1.107.0 supply chain compromise'
  url: https://www.microsoft.com/en-us/security/blog/2026/10/23/inside-the-litellm-1-107-0-supply-chain-compromise-credential-theft-through-python-startup-hooks/
related:
- hunt: litellm-installation-and-startup-persistence
  reason: A sibling hunt that focuses on identifying the distribution and the initial
    persistence hooks.
  relation: precedes
- hunt: litellm-supply-chain-credential-theft
  relation: follows
scenario:
  stages:
  - name: Compromised Package Distribution
    observables:
    - litellm==1.107.0
    - Berri-AI/litellm (lookalike repository)
    slug: malicious-package-distribution
    tactic: initial-access
    techniques:
    - T1195
  - name: Python Startup Hook Persistence
    observables:
    - cook.pth
    - cook.py
    - sitecustomize.py
    - litellm-1.107.0.data/purelib/
    slug: python-startup-hook-persistence
    tactic: persistence
    techniques:
    - T1574
  - name: Credential and Sensitive Data Collection
    observables:
    - PRIVCOLLECT_ACTIVE environment variable
    - /tmp/.pc_once_72129118c59f5636c0bb
    - .aws/credentials
    - .azure/accessTokens.json
    - .kube/config
    - .ssh/id_rsa
    - Prisma database queries against LiteLLM proxy
    slug: credential-harvesting
    tactic: credential-access
    techniques:
    - T1555
    - T1083
  - name: Remote Code Loader Execution
    observables:
    - /tmp/remote_code_loader.lock
    - GitHub domain.txt lookup
    - HTTP GET /codepy
    slug: remote-code-loader-execution
    tactic: execution
    techniques:
    - T1059.006
  - name: Encrypted Data Exfiltration
    observables:
    - .pc_e_ temporary directories
    - data.bin
    - key.bin
    - hdr.json
    - www.litellm.dev/healthcheck
    - X-SHA256 HTTP header
    - application/octet-stream
    slug: data-exfiltration
    tactic: exfiltration
    techniques:
    - T1041
  summary: The LiteLLM 1.107.0 supply chain compromise involved a malicious package
    release that deployed Python startup hooks (.pth files and sitecustomize.py) to
    achieve automatic execution. Once activated, the payload harvested a wide range
    of credentials from cloud providers, developer tools, and browsers, while maintaining
    a remote code loader to execute additional instructions from attacker-controlled
    infrastructure.
series:
  index: 2
  slug: inside-the-litellm-1-107-0-supply-chain-compromise-credential-theft-through-python-startup-hooks
  title: 'Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through
    Python startup hooks'
  total: 2
severity: high
targets:
  analyst:
    name: Tier-2 analyst
    role: analyst
  endpoint:
    category: endpoint
    name: Endpoint telemetry (hb_ surfaces)
    telemetry:
    - endpoint
  hunter:
    agent: true
    name: Hunt agent
tlp: clear
type: investigation
---


# LiteLLM Remote Code Loading and Exfiltration

This hunt identifies the second-stage behavior of the LiteLLM 1.107.0 supply chain compromise. It focuses on the activation of the remote code loader and the exfiltration of encrypted credential archives. The hunt correlates the presence of the compromised software version with network telemetry from DNS lookups and the creation of transient staging artifacts or lock files on the file system.

## identify-vulnerable-installations
<!-- Identify LiteLLM 1.107.0 installations -->
Locate hosts with the compromised version of LiteLLM to focus the hunt on the most likely points of compromise.

```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hosts running the compromised package. Silence means the specific
  version was not found in the current inventory snapshot.
reads:
- device_hostname
- package_name
- package_version
- install_path
- collected_at
silence: not_evidence_of_absence
source: hb_software_inventory
verified: dry-run
verified_at: '2026-10-24'
~~~
SELECT device_hostname, package_name, package_version, install_path, collected_at FROM hb_software_inventory WHERE LOWER(package_name) = 'litellm' AND package_version = '1.107.0'
```

## corroborate-activity
<!-- Corroborate loader and exfiltration activity -->
parallel:
- → dns-to-c2-infrastructure
- → staging-and-loader-artifacts
join: → triage-signals

## dns-to-c2-infrastructure
<!-- Python DNS lookups to C2 infrastructure -->
Identify Python processes resolving the exfiltration domain or the loader configuration source.

```sqlite target=endpoint role=baseline params=(lookback_days=lookback_days, scope_hosts=scope_hosts, c2_domains=c2_domains)
~~~yaml
baseline:
  compare: first_seen
  window: '{{lookback_days}}d'
expected: Python or pip processes communicating with the domains named in the report.
  Silence means no such resolutions were logged within the window.
prevalence:
  by: device_hostname
  key:
  - query_hostname
  rare_below: 3
reads:
- device_hostname
- process_name
- query_hostname
- time
silence: not_evidence_of_absence
source: hb_dns_activity
verified: dry-run
verified_at: '2026-10-24'
~~~
SELECT device_hostname, process_name, query_hostname, COUNT(*) AS count, MIN(time) AS first_seen FROM hb_dns_activity WHERE instr(',' || '{{c2_domains}}' || ',', ',' || LOWER(query_hostname) || ',') > 0 AND (LOWER(process_name) LIKE '%python%' OR LOWER(process_name) LIKE '%pip%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name, query_hostname
```

## staging-and-loader-artifacts
<!-- Malicious staging and loader artifacts -->
Find transient files used to stage exfiltrated data or the lock file used by the remote loader.

```sqlite target=endpoint role=detection-candidate params=(lookback_days=lookback_days, scope_hosts=scope_hosts, exfil_artifacts=exfil_artifacts)
~~~yaml
expected: The presence of staging files (data.bin, key.bin, hdr.json) or the loader
  lock file on disk. Silence is expected if the payload successfully cleaned up or
  never activated.
reads:
- device_hostname
- process_name
- file_path
- file_name
- activity_name
- time
silence: not_evidence_of_absence
source: hb_file_activity
verified: dry-run
verified_at: '2026-10-24'
~~~
SELECT device_hostname, process_name, file_path, file_name, activity_name, time FROM hb_file_activity WHERE (LOWER(file_path) LIKE '%/.pc_e_%' OR instr(',' || '{{exfil_artifacts}}' || ',', ',' || LOWER(file_name) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## triage-signals
<!-- Triage compromise signals -->
```agent target=hunter
cite: required
context:
- identify-vulnerable-installations
- dns-to-c2-infrastructure
- staging-and-loader-artifacts
max_iterations: 5
objective: Determine if any host in scope reached the exfiltration or remote code
  loading stages. Correlate the presence of LiteLLM 1.107.0 with the timing of Python
  DNS requests to C2 domains and the creation of staging file artifacts.
success_criteria: A per-host verdict of malicious | suspicious | benign, citing specific
  DNS and file rows that align with the presence of the compromised package.
tools:
- endpoint
```

## route-on-verdict
<!-- Route on activity verdict -->
if~: "the triage-signals verdict is malicious for at least one host" (confidence: high, judge=hunter)
then: → isolate-host
indeterminate: → analyst-review
unavailable: → analyst-review (blind_spot: transient-artifact-deletion)
else: → analyst-review

## isolate-host
<!-- Isolate compromised host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host immediately. Do not use local Python tools for investigation; perform all forensic collection from a known-clean environment.
```
→ analyst-review

## analyst-review
<!-- Analyst review -->
```manual target=analyst
Review the cited DNS resolutions and file activity. Check for HTTP POST activity to litellm.dev in proxy logs if available. Verify the content of site-packages for unauthorized .pth or .py files.
```
→ close-out

## close-out
<!-- Hunt close-out -->
```manual target=analyst
Record every host where successful exfiltration or loader activity was suspected. Coordinate the rotation of all secrets accessible to the affected systems and ensure affected Python environments are purged.
```
→ end

Run it

Take this hunt into your environment.

Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.

Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.