Supply chain attack scanner for PyPI packages โ static AST + dynamic sandbox analysis before install
Project description
depsentinel ๐ก๏ธ
Supply chain attack scanner for PyPI packages.
Most vulnerability scanners only check against known CVE databases โ reactive by nature. depsentinel catches what they miss: malicious install hooks, obfuscated payloads, data exfiltration, CPU bombs, and dependency confusion attacks, before the package ever runs on your system.
Install
pip install depsentinel
Usage
# Drop-in replacement for pip install
depsentinel pip install requests
depsentinel pip install numpy pandas
# View scan history
depsentinel audit
How It Works
Two phases run in sequence before any package is installed:
Phase 1 โ Static Analysis
Downloads the package without installing it, then inspects:
- Typosquatting โ Levenshtein distance check against the top 5000 PyPI packages (
requets,djano, etc.) - Provenance โ package age, download count, missing source repository
- AST scan โ parses every
.pyfile in the package for:exec()/eval()with dynamic arguments at module levelbase64.b64decodeโexecchains (obfuscated payloads)subprocess,os.system,os.popencalls- Network calls at module level (
requests.get,socket.connect, etc.) - Reads of sensitive files (
.ssh/,.aws/credentials,.m2/settings.xml) - Environment variable harvesting (
SECRET,TOKEN,API_KEY, etc.) - High-entropy string literals (encrypted/encoded payloads)
sys.pathmutation (path poisoning)
- Metadata anomalies โ compiled binaries with no source, git URLs in dependencies
Phase 2 โ Dynamic Sandbox
Imports the package inside an isolated subprocess with:
- CPU time limit (10s hard cap via
RLIMIT_CPU) - Memory cap (512MB via
RLIMIT_AS) - Process limit (no fork bombs via
RLIMIT_NPROC) - Network fully blocked (socket.connect patched)
- Subprocess execution blocked
- Sensitive file reads intercepted
Reports on:
- Import time (infinite loop / CPU bomb detection)
- Background threads spawned on import (crypto miners, C2 beacons)
- Network connection attempts
- Subprocess execution attempts
- Sensitive file access attempts
- Memory growth on import (OOM bomb detection)
Output
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Scanning: requets
โ requets v0.0.1
[STATIC]
โ Likely typosquat of 'requests' (edit distance 1)
โ Published 2 days ago
โ Very low downloads: 14/month
โ setup.py calls subprocess.run at module level
โ base64 import + exec() = obfuscated payload pattern
๐ซ Risk: CRITICAL
๐ซ Install blocked: requets
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Scanning: requests
โ requests v2.33.1
[STATIC]
โ Risk: LOW
[DYNAMIC]
โ Import time OK (0.509s)
โ No unexpected threads spawned
โ No network attempts detected
โ No subprocess calls detected
โ No sensitive file access detected
โ Memory growth OK (+0MB)
โ Risk: OK
โ All packages passed. Proceeding with install...
Risk Levels
| Level | Action |
|---|---|
| OK / LOW | Proceeds automatically |
| MEDIUM | Proceeds with warning logged to audit |
| HIGH | Prompts for confirmation before Phase 2 |
| CRITICAL | Hard block โ install does not proceed |
Audit Log
Every scan is appended to ~/.depsentinel_audit.jsonl:
depsentinel audit
# 2025-04-13T10:22:01 LOW requests
# 2025-04-13T10:23:44 CRITICAL requets
Attack Types Detected
| Attack | Static | Dynamic |
|---|---|---|
| Malicious install hooks | โ | โ |
| Obfuscated payload (base64+exec) | โ | โ |
| Credential harvesting | โ | โ |
| Network exfiltration | โ | โ |
| Typosquatting | โ | โ |
| Dependency confusion | โ | โ |
| CPU bomb / infinite loop | โ ๏ธ partial | โ |
| OOM bomb | โ | โ |
| Thread spawning (miner/C2) | โ | โ |
| Fork bomb | โ | โ |
| Monkey patching | โ ๏ธ partial | โ |
Limitations
- Dynamic sandbox uses
setrlimitโ full isolation requires Linux (unshare --net). On macOS/Windows, network blocking is applied via socket patching only. - Transitive dependency scanning (sub-deps) is on the roadmap.
- Maven/Gradle support coming soon.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file depsentinel-0.1.1.tar.gz.
File metadata
- Download URL: depsentinel-0.1.1.tar.gz
- Upload date:
- Size: 12.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cbe71640a651ac66a1608976a14378ea081ee585dc4540d843f113ec16974e9f
|
|
| MD5 |
fcc507585be5bc92accb7b2adcd195dc
|
|
| BLAKE2b-256 |
769cd9a6fadf1349a1487997c4c985259a3405bdd77775d18dfedd1c07189902
|
File details
Details for the file depsentinel-0.1.1-py3-none-any.whl.
File metadata
- Download URL: depsentinel-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5aed866508c3b8a720921eabea8b735b768e2f9a748f3272a1c7895fa11a5aaa
|
|
| MD5 |
24a4f856efbfba0a535b8249376a6c2b
|
|
| BLAKE2b-256 |
1f61b82f60c9fc0b2cb1c10a52f42c341aa5c041f1421dd73ee9ec0ef230614c
|