Detection rules › Splunk

Python PYTHONPATH Modification During Package Installation

Status
production
Severity
medium
Group by
channel, dest, process_id
Author
Onur Mustafa Erdogan, Splunk
Source
github.com/splunk/security_content

The following analytic detects modification of the PYTHONPATH environment variable in conjunction with a package installation process. Python looks up the sys.path variable, which is generated by combining user and site folders with .pth files and the value of the PYTHONPATH environment variable, to determine which directories to use for importing modules. If an adversary is able to control the value of PYTHONPATH, they can point it to an attacker-controlled directory and hijack imported packages, achieving user-level persistence across future Python invocations and new shell sessions. If confirmed malicious, this could result in arbitrary code execution every time Python is invoked by the affected user.

Known false positives

  • Developers and legitimate installers may modify PYTHONPATH as part of normal environment configuration. Investigate the new value and parent process to determine legitimacy.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

name: Python PYTHONPATH Modification During Package Installation
id: 00f01ba4-df01-4caa-90f6-187e4563a516
version: 1
creation_date: '2026-08-21'
modification_date: '2026-08-21'
author: Onur Mustafa Erdogan, Splunk
status: production
type: TTP
description: |-
    The following analytic detects modification of the PYTHONPATH environment variable in conjunction with a package installation process.
    Python looks up the `sys.path` variable, which is generated by combining user and site folders with `.pth` files and the value of the PYTHONPATH environment variable, to determine which directories to use for importing modules.
    If an adversary is able to control the value of PYTHONPATH, they can point it to an attacker-controlled directory and hijack imported packages, achieving user-level persistence across future Python invocations and new shell sessions.
    If confirmed malicious, this could result in arbitrary code execution every time Python is invoked by the affected user.
data_source:
    - Sysmon EventID 1 AND Sysmon EventID 13
search: |-
    `sysmon`
    EventID IN (1,13)
    (
        parent_process="*\\site-packages\\pip\\*"
        OR
        (
            registry_path="*PYTHONPATH"
            action="modified"
        )
    )
    
    | stats count min(_time) as firstTime
                  max(_time) as lastTime
                  values(parent_process_id) as parent_process_id
                  values(parent_process_name) as parent_process_name
                  values(parent_process_path) as parent_process_path
                  values(parent_process) as parent_process
                  values(process_path) as process_path
                  values(process_name) as process_name
                  values(process) as process
                  values(registry_path) as registry_path
                  values(registry_value_data) as registry_value_data
                  dc(EventID) as dc_event_id
    
      by dest source process_id
    
    | search dc_event_id>1
    
    | table firstTime lastTime
            parent_process_id parent_process_path parent_process_name parent_process
            process_id process_path process_name process
            registry_path registry_value_data
            dest source
    
    | `security_content_ctime(firstTime)`
    | `security_content_ctime(lastTime)`
    | `python_pythonpath_modification_during_package_installation_filter`
how_to_implement: |-
    This detection requires Sysmon event logs. Configure your environment to ingest Sysmon process creation (EventID 1)
    and registry modification (EventID 13) events, ensuring that registry modification events are collected for the
    PYTHONPATH environment variable(\Environment\PYTHONPATH). Ingest the data via the appropriate Splunk Technology Add-on
    and normalize field names using the Splunk Common Information Model (CIM).
known_false_positives: |-
    Developers and legitimate installers may modify PYTHONPATH as part of normal environment configuration.
    Investigate the new value and parent process to determine legitimacy.
references:
    - https://blog.talosintelligence.com/the-serpents-tongue-luring-the-python-out-of-its-den/
finding:
    title: The PYTHONPATH environment variable [$registry_path$] was modified to the value of [$registry_value_data$] on [$dest$] during package installation using [$process$].
    entity:
        field: dest
        type: system
        score: 50
threat_objects:
    - field: process
      type: process
    - field: registry_value_data
      type: registry_value_data
analytic_story:
    - Malicious Python Package Installation
    - Compromised Windows Host
    - Windows Persistence Techniques
    - Suspicious Windows Registry Activities
    - Windows Registry Abuse
asset_type: Endpoint
mitre_attack_id:
    - T1574.007
    - T1195.002
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: endpoint
security_domain: endpoint

Stages and Predicates

Stage 1: search

`sysmon`
EventID IN (1,13)
(
    parent_process="*\\site-packages\\pip\\*"
    OR
    (
        registry_path="*PYTHONPATH"
        action="modified"
    )
)

Stage 2: stats

| stats count min(_time) as firstTime
              max(_time) as lastTime
              values(parent_process_id) as parent_process_id
              values(parent_process_name) as parent_process_name
              values(parent_process_path) as parent_process_path
              values(parent_process) as parent_process
              values(process_path) as process_path
              values(process_name) as process_name
              values(process) as process
              values(registry_path) as registry_path
              values(registry_value_data) as registry_value_data
              dc(EventID) as dc_event_id

  by dest source process_id

Stage 3: search

| search dc_event_id>1

Stage 4: table

| table firstTime lastTime
        parent_process_id parent_process_path parent_process_name parent_process
        process_id process_path process_name process
        registry_path registry_value_data
        dest source

Stage 5: search

| `security_content_ctime(firstTime)`

Stage 6: search

| `security_content_ctime(lastTime)`

Stage 7: search

| `python_pythonpath_modification_during_package_installation_filter`

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
EventIDin
  • 1 corpus 242 (splunk 226, kusto 15, elastic 1)
  • 13 corpus 23 (splunk 18, kusto 5)
field:"EventID" kind:in
actioneq
  • "modified"
field:"action" kind:eq
dc_event_idgt
  • 1 corpus 3 (splunk 3)
field:"dc_event_id" kind:gt value:"1"
parent_processeq
  • "*\\site-packages\\pip\\*"
field:"ParentCommandLine" kind:eq
registry_patheq
  • "*PYTHONPATH"
field:"registry_path" kind:eq