Skip to main content

pip-compile wrapper with CVE awareness

Project description

safe-pip-compile

A drop-in pip-compile wrapper that avoids pinning packages with known CVEs.

pip-compile resolves dependencies without vulnerability awareness — it will happily pin a version with critical CVEs. safe-pip-compile automates the compile → audit → fix loop by querying OSV.dev and iteratively constraining vulnerable versions out of the resolution.

Installation

pip install -e .

Quick start

# Drop-in replacement for pip-compile
safe-pip-compile requirements.in -o requirements.txt

CLI flags

Flag Description Default
-o, --output-file PATH Output requirements.txt path <input_basename>.txt
--min-severity LEVEL Only block CVEs at this level or above (critical, high, medium, low) all (blocks everything)
--allow-list PATH YAML file of accepted CVEs to skip none
--max-iterations INT Max compile→audit loops before giving up 10
--strict / --no-strict Exit code 1 if unresolved CVEs remain --strict
--dry-run Show what would happen, write nothing off
--json-report PATH Write machine-readable JSON vulnerability report none
--cert PATH CA bundle for SSL verification (corporate proxies) auto-detect from env
--no-cache Disable local CVE cache, always query OSV.dev cache enabled
--refresh-cache Wipe cached data and re-fetch from OSV.dev off
-v, --verbose Increase output detail (-v, -vv) quiet

All other flags pass through to pip-compile (e.g. --generate-hashes, --allow-unsafe).

Examples

# Only block high and critical CVEs
safe-pip-compile requirements.in --min-severity high

# Accept specific CVEs via allowlist
safe-pip-compile requirements.in --allow-list cve-allowlist.yaml

# Pass pip-compile flags through
safe-pip-compile requirements.in -- --generate-hashes --allow-unsafe

# CI: generate JSON report and fail on unresolved CVEs
safe-pip-compile requirements.in --json-report audit.json --strict

# Preview without writing files
safe-pip-compile requirements.in --dry-run -v

# Skip cache, always query OSV.dev fresh
safe-pip-compile requirements.in --no-cache

# Wipe cache and re-fetch everything
safe-pip-compile requirements.in --refresh-cache

Allowlist format

Create a cve-allowlist.yaml to accept specific CVEs:

allowed_cves:
  - id: CVE-2024-12345
    reason: "Not applicable  we don't use the affected feature"
    expires: 2025-06-01  # optional, re-blocks after this date

  - id: GHSA-xxxx-yyyy-zzzz
    reason: "Accepted risk, tracked in JIRA-789"

Matches against vuln ID and all aliases (CVE, PYSEC, GHSA).

pyproject.toml config

[tool.safe-pip-compile]
max-iterations = 10
min-severity = "high"
allowlist = "cve-allowlist.yaml"
strict = true

CLI flags override these values.

Exit codes

Code Meaning
0 Clean — no blocking CVEs
1 Unresolved CVEs remain (strict mode)
2 pip-compile resolution failed
3 Network or configuration error

How it works

requirements.in
     │
     ▼
┌─ LOOP (max N iterations) ──────────────────────────┐
│  1. pip-compile (with accumulated constraints)      │
│  2. Parse resolved packages                         │
│  3. Check local cache → on miss, query OSV.dev       │
│  4. Filter by severity + allowlist                  │
│  5. Generate constraints (e.g. django>=3.2.25)      │
│  6. Clean? → done. Stuck? → report. Else → loop.   │
└─────────────────────────────────────────────────────┘
     │
     ▼
requirements.txt (CVE-free)

Local CVE cache

Vulnerability data is cached in a local SQLite database to avoid repeated OSV.dev API calls.

  • Location: ~/.cache/safe-pip-compile/cache.db (Linux), ~/Library/Caches/safe-pip-compile/cache.db (macOS), %LOCALAPPDATA%\safe-pip-compile\Cache\cache.db (Windows)
  • TTL: 6 months — "django 3.2.1 has CVE-X, fix is 3.2.25" doesn't change
  • No-fix vulns are never cached — they get re-checked every run in case a fix is published
  • Works across virtualenvs — stored in user cache dir, not inside any venv
  • Concurrent-safe — SQLite WAL mode allows parallel readers

Corporate proxy / SSL issues

If you're behind a corporate proxy that does SSL inspection, you may see:

OSV.dev error: Cannot reach OSV.dev API: [SSL: CERTIFICATE_VERIFY_FAILED]

Three ways to fix this:

Option 1: --cert flag

safe-pip-compile requirements.in --cert /path/to/corporate-ca-bundle.pem

Option 2: Environment variable (auto-detected, no flag needed)

# Set any of these — same vars that pip, requests, and httpx respect
export SSL_CERT_FILE=/path/to/corporate-ca-bundle.pem
# or
export REQUESTS_CA_BUNDLE=/path/to/corporate-ca-bundle.pem

safe-pip-compile requirements.in

Option 3: Find your org's CA cert

# Check if pip already knows where it is
python -m pip config get global.cert

# On Windows, export from certificate store:
# certmgr.msc → Trusted Root CAs → find your org's proxy cert → export as .pem

Lookup order: --cert flag > SSL_CERT_FILE > REQUESTS_CA_BUNDLE > CURL_CA_BUNDLE > system default.

Development

pip install -e ".[dev]"
python -m pytest tests/ -v

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_pip_compile-0.1.2.tar.gz (23.7 kB view details)

Uploaded Source

Built Distribution

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

safe_pip_compile-0.1.2-py3-none-any.whl (26.5 kB view details)

Uploaded Python 3

File details

Details for the file safe_pip_compile-0.1.2.tar.gz.

File metadata

  • Download URL: safe_pip_compile-0.1.2.tar.gz
  • Upload date:
  • Size: 23.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for safe_pip_compile-0.1.2.tar.gz
Algorithm Hash digest
SHA256 616c8e292ab20d6d9af10aca00a068b06a955fb3f0a32873e50c5e4ed103c381
MD5 6c0462fd046c9ad773f429c48a56e181
BLAKE2b-256 e24bc98e046cdbfbb92241e77931b9791c1fffb58cf48b754fc7bc0c098294ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for safe_pip_compile-0.1.2.tar.gz:

Publisher: publish.yml on sai1027/safe-pip-compile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file safe_pip_compile-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for safe_pip_compile-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3220abc0d73f0ba5266d220eca2625fb61ed94c10aa3fa6fdfb3831e0cfe4aa2
MD5 a0bdc51f824931194a5e2c2ef6a2b1ad
BLAKE2b-256 c24cb1fc797130fdc26b8cff0080eebdb9e5c4ffec8ce5c3bc7455561f6d3642

See more details on using hashes here.

Provenance

The following attestation bundles were made for safe_pip_compile-0.1.2-py3-none-any.whl:

Publisher: publish.yml on sai1027/safe-pip-compile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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