Attack technique

Python Startup Hooks: .pth and sitecustomize.py Persistence (T1546.018)

Also known as Python Startup Hooks, .pth file persistence

Python Startup Hooks let an attacker run code every time Python starts.

In short

Python Startup Hooks let an attacker run code every time Python starts. A file dropped into the Python packages folder is processed by the interpreter itself, so the code runs even if the program never imports anything from it. MITRE tracks this as T1546.018.

Profile MapTechnique
  1. Reconnaissance
  2. Resource Development
  3. Initial Access
  4. Execution
  5. Persistence
  6. Privilege Escalation
  7. Stealth
  8. Defense Impairment
  9. Credential Access
  10. Discovery
  11. Lateral Movement
  12. Collection
  13. Command and Control
  14. Exfiltration
  15. Impact
  1. MITRE IDT1546.018ATT&CK technique
  2. Detection4ways to spot itNetwork traffic from Python
  3. Defences4ways to stop itKnow the limit of prevention

How it works

MITRE says adversaries may use Python’s startup mechanisms for persistence. These are path configuration files with the .pth extension, and the sitecustomize.py or usercustomize.py modules. Python processes them automatically when the interpreter initializes, so arbitrary code can run whenever Python is invoked.

MITRE explains that a .pth file placed in a site-packages or dist-packages folder has any line that begins with import executed on every Python run. A sitecustomize.py or usercustomize.py file in the Python path is imported at startup, and the code in it runs. MITRE adds that adversaries may abuse this on systems where Python is widely used, for example for automation or scripting in production.

A real example

MITRE lists the TeamPCP Cloud Stealer, which used .pth files to persist on compromised hosts, and Mini Shai-Hulud, which used Python startup hooks to run through the .pth import mechanism. On 21 October 2026 Socket mapped the malicious LiteLLM 1.107.0 release to this technique. A cook.pth file imported a stealer at every Python start, and a sitecustomize.py file started a background loader. In March 2026, LiteLLM 1.82.8 also carried a .pth file, litellm_init.pth, per a public GitHub issue and the PyPA advisory. See the LiteLLM 1.107.0 incident profile and our LiteLLM 1.107.0 response checklist.

How to detect

  1. New .pth, sitecustomize.py or usercustomize.py files

    MITRE's detection strategy DET0258 looks for unauthorized creation or change of Python hook files in site-packages, dist-packages or user paths.

  2. Python that starts without a user

    MITRE says to correlate those file writes with unexpected interpreter runs, such as python3 starting without user interaction, and with changes in interpreter behavior such as malicious imports.

  3. Network traffic from Python

    MITRE also points to outbound connections started from Python, and to child processes that look out of place, after a hook file was written.

  4. Do not trust the file name alone

    Socket notes that sitecustomize.py can be a legitimate file, so a hit on the name is a reason to read the file, not proof of compromise.

How to defend

  1. Know the limit of prevention

    MITRE says this technique cannot be easily mitigated with preventive controls, because it abuses system features. Detection and package hygiene matter more.

  2. Block the bad package and verify what you install

    Socket's LiteLLM advice is to block the bad version and compare published distributions against the intended source, including data folders and startup files.

  3. Rebuild instead of cleaning in place

    LiteLLM tells affected users not to run pip install first, because Python startup re-runs the malicious files. It recommends rebuilding images and virtual environments from scratch.

  4. Look for hook files after an incident

    List every .pth, sitecustomize.py and usercustomize.py in your site-packages folders and read the ones you did not put there.

Questions

What is a .pth file?

MITRE describes it as a path configuration file that extends Python's module search path. A line that begins with import in such a file is executed when Python starts.

Does the malware run if I never import the package?

Yes, for this technique. MITRE says the hook files run whenever Python is invoked, and SafeDep says the LiteLLM 1.107.0 files ran even on hosts where litellm was never imported.

Is sitecustomize.py always malicious?

No. Socket notes that the file name can be legitimate, so check who created the file and what it contains.

In our research

  1. LiteLLM 1.107.0 Supply Chain Attack: Timeline, Stolen Data and a Response Checklist October 2026

Sources

  1. Event Triggered Execution: Python Startup Hooks, T1546.018 MITRE ATT&CK
  2. Event Triggered Execution, T1546 MITRE ATT&CK
  3. LiteLLM PyPI Package and Docker Images Compromised to Steal Cloud and AI Credentials Socket
  4. Compromised LiteLLM 1.107.0 on PyPI Installs a Credential Stealer and Backdoor SafeDep
  5. Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised LiteLLM (BerriAI)
  6. PYSEC-2026-2 litellm advisory Python Packaging Authority advisory database
  7. SECURITY: litellm 1.82.8 on PyPI contains malicious credential-stealing payload (litellm_init.pth), Issue #24521 BerriAI/litellm on GitHub