Skip to main content

Supply chain attack defense for pip, npm, cargo, go, gem, and Docker

Project description

safe-install

PyPI version Python 3.9+ License: MIT Zero Dependencies

Install-time hardening for package managers. Reduces credential exposure during pip install, npm install, and other package operations by isolating builds in Docker containers and scanning source for exfiltration patterns.

Status: Alpha (v0.1.x). pip and npm ecosystems are the most mature. Cargo, Go, Gem, and Docker adapters are experimental. See the maturity table below.

The Problem

Every time you run pip install or npm install, any package in the dependency tree can execute arbitrary code during the build/install phase. That code runs with your full user permissions and can read SSH keys, cloud credentials, API tokens, browser passwords, and anything else accessible to your account.

This is not theoretical. Real-world attacks exploiting install-time code execution include compromised maintainer accounts, typosquatting campaigns, and dependency confusion attacks across pip, npm, cargo, and gem ecosystems.

What safe-install Does

safe-install interposes between you and your package manager. Its primary defense is Docker-based build isolation: packages are downloaded and built inside a locked-down container with no access to your filesystem, credentials, or environment variables. The resulting artifacts (wheels, tarballs) are copied out and installed locally without executing any code.

When Docker is unavailable, safe-install falls back to a credential vault that temporarily hides sensitive files and clears sensitive environment variables during the install.

Additionally, safe-install runs heuristic source inspection that scans package source code for patterns commonly associated with exfiltration (HTTP requests in setup.py, environment variable access in build scripts, etc.).

What This Does NOT Protect You From

  • Import-time attacks: The sandbox protects install-time only. A malicious __init__.py still runs when you import the_package in your real environment.
  • Obfuscated payloads: Source inspection uses pattern matching. Encrypted payloads, steganography, and multi-stage loaders can evade it.
  • Compiled native extensions: Binary code in wheels (.so, .dll) can contain anything. Source inspection cannot analyze compiled code.
  • Build tool compromise: If pip, npm, or cargo themselves are compromised, safe-install cannot help.
  • Registry infrastructure attacks: If PyPI or npm registry infrastructure is compromised at the server level.
  • Complete protection: This tool reduces exposure and adds friction to attacks. It is not a guarantee.

Why Docker-First Matters

The Docker sandbox is the only defense layer that does not depend on detecting malicious behavior. It works by removing the attack surface entirely: the container has nothing to steal, regardless of how sophisticated or obfuscated the malicious code is.

Your machine                          Docker container
+------------------+                  +------------------+
| ~/.ssh/          |                  | (empty)          |
| ~/.aws/          |  -- INVISIBLE -> | No home dir      |
| ~/.gitconfig     |                  | No env vars      |
| $GITHUB_TOKEN    |                  | No volume mounts |
| Chrome passwords |                  | --cap-drop=ALL   |
+------------------+                  | --read-only      |
                                      | --memory=2g      |
        pip install pkg               | --no-new-priv    |
              |                       +------------------+
              v                              |
     Download + build in container           |
              |                              |
     Copy .whl files out <-------------------+
              |
     pip install --no-deps *.whl  (just unzips, no code runs)

Docker isolation is strong but not absolute. Theoretical risks include container escapes (mitigated by --cap-drop=ALL and --security-opt=no-new-privileges), DNS-based exfiltration from within the container, and resource exhaustion despite limits.

Security Philosophy

  • Reduce exposure: Minimize what malicious code can access during install.
  • Contain risk: Isolate builds so that even successful exploitation has limited impact.
  • Add friction and visibility: Make attacks harder and more detectable, not impossible.
  • Defense in depth: Multiple independent layers, each with known limitations.
  • Not a guarantee: No security tool can promise complete protection. safe-install shifts the odds.

Install

pip install safe-install

Or via the installer script

curl -sSL https://raw.githubusercontent.com/Khaeldur/safe-install/main/install.sh | bash

Note: piping curl to bash has its own supply chain risks. Consider cloning the repo and reviewing the script first.

Ecosystem Maturity

Ecosystem Dep Resolution Source Scan Docker Sandbox Local Install Overall
pip Full tree via --dry-run --report Python patterns (comprehensive) Builds wheels in container pip install --no-deps *.whl Strong
npm Direct deps via npm view JS patterns (comprehensive) npm pack in container npm install --ignore-scripts Strong
cargo Top-level only (no transitive) Rust patterns (basic) cargo fetch in container Manual (prints instructions) Experimental
go Top-level module only Go patterns (basic) go mod download in container Manual (prints instructions) Experimental
gem Direct deps only Ruby patterns (basic) gem fetch in container gem install --local (still runs extconf.rb) Experimental
docker Image layers only Dockerfile patterns (not wired in) N/A (is Docker) docker load Experimental

"Experimental" means: code exists and may provide some protection, but has not been tested against adversarial inputs, has incomplete dependency resolution, and may have non-functional code paths.

Threat Model

What safe-install reduces (install-time)

Threat Docker Sandbox Credential Vault Source Scan
Credential theft in setup.py/postinstall Isolated Hidden Detected (if not obfuscated)
Cryptominer during build Isolated (resource-limited) N/A Detected (heuristic)
RAM/CPU bomb Limited (--memory, --cpus) N/A N/A
Environment variable exfiltration Isolated (no env vars in container) Cleared Detected (heuristic)

What safe-install detects heuristically

  • Typosquatting via edit-distance comparison against popular package names
  • Suspicious patterns in build scripts (HTTP requests, env access, file reads)
  • Unexpected network connections during install
  • Young packages, recent maintainer changes, low download counts

What remains possible despite safe-install

  • Import-time code execution (__init__.py, conftest.py)
  • Compiled native extensions with embedded payloads
  • Obfuscated or encrypted malicious code that evades pattern matching
  • Time-delayed payloads that activate long after install
  • Attacks through the package manager itself

Defense Layers

Layer Method Confidence Notes
Docker Sandbox OS-level container isolation High Primary defense. No host access.
Binary-only mode Wheels only, no setup.py High (pip) Some packages lack wheels.
Hash lockfile SHA256 verification High (when lockfile exists) Lockfile generation not yet implemented.
Typosquat detection Edit distance + popularity DB Moderate Unvalidated accuracy.
Package intelligence Registry metadata analysis Moderate Queries real APIs. No malicious-package DB.
Source inspection Regex pattern matching Low-Moderate Bypassable via obfuscation. Useful as early warning.
Credential vault Temporarily hide files/env vars Moderate Fallback when Docker unavailable. Known bypasses exist.
Network monitor Connection polling during install Low-Moderate 1s polling interval. Fast exfil can slip through.

Quick Start

# Check what's exposed on your machine right now
safe-install check-env

# Install a package with full protection
safe-install install requests

# Audit a package without installing
safe-install audit litellm

# Scan a local project for suspicious patterns
safe-install scan ./my-project/

Usage

# Auto-detects ecosystem from package name
safe-install install requests                    # pip
safe-install install -e npm express              # explicit ecosystem
safe-install install -e cargo serde              # experimental
safe-install install -e go github.com/gin-gonic/gin  # experimental

# Docker sandbox (default if Docker is available)
safe-install install flask

# Binary-only (refuse source distributions)
safe-install install flask --binary-only

# Fallback to credential vault (when Docker unavailable)
safe-install install flask --no-sandbox

# Dry run (audit everything, install nothing)
safe-install install flask --dry-run

# Audit
safe-install audit requests
safe-install audit -e npm lodash
safe-install audit flask --deep  # includes intelligence + binary analysis

Configuration

Create ~/.config/safe-install/config.toml (global) or ./safe-install.toml (per-project):

[sandbox]
enabled = true
memory_limit = "2g"
cpu_limit = "2"
timeout = 600

[vault]
extra_paths = [
    "~/.custom-secrets",
]
extra_env_vars = [
    "MY_SECRET_API_KEY",
]

[network]
allowed_hosts = [
    "my-private-registry.com",
]

Limitations

  1. Import-time attacks: The sandbox protects install-time. A malicious __init__.py still runs when you import the_package. Mitigation: use virtual environments, consider the safe-install guard command (experimental).

  2. Obfuscated code: Source inspection uses pattern matching. Sophisticated obfuscation evades it. The Docker sandbox does not care about obfuscation, but it only protects install-time.

  3. Without Docker: The credential vault fallback is imperfect. An attacker who knows about safe-install could look for the vault temp directory, or access paths not in the sensitive list.

  4. Compiled extensions: Native C/C++ extensions in wheels can contain anything. Source inspection cannot analyze compiled code.

  5. Experimental ecosystems: cargo, go, gem, and docker adapters have incomplete dependency resolution and may have non-functional code paths. Do not rely on them for security-critical workflows.

Contributing

See CONTRIBUTING.md.

Security Policy

See SECURITY.md.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

safe_install-0.1.1.tar.gz (69.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

safe_install-0.1.1-py3-none-any.whl (77.7 kB view details)

Uploaded Python 3

File details

Details for the file safe_install-0.1.1.tar.gz.

File metadata

  • Download URL: safe_install-0.1.1.tar.gz
  • Upload date:
  • Size: 69.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for safe_install-0.1.1.tar.gz
Algorithm Hash digest
SHA256 133801c56326c4ea9a1a59c7c1c4f04eb40c9c994c4a2562fe384ac59ca2071e
MD5 960c44a2931e80e2762b31b0b40a63a5
BLAKE2b-256 d7f0111371e7618acbf6ceb9c43024d1cfb08b603fca2763a9185c01d8d52741

See more details on using hashes here.

File details

Details for the file safe_install-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: safe_install-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 77.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for safe_install-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 af333996c656a205c27d1afe6e7655d97202eae684d1268389a155941682da1c
MD5 826bfbd8952147e2592c920459bf97d9
BLAKE2b-256 2b56ba233960047e3b9e2e84bccc482c33abb0c883e63b7b735c340643dcaa4d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page