pip-compile wrapper with CVE awareness
Project description
safe-pip-compile
safe-pip-compile is a drop-in pip-compile wrapper that avoids pinning Python
packages with known CVEs.
pip-compile is excellent at resolving repeatable dependency sets, but it does not
know whether a resolved version has a published vulnerability. safe-pip-compile
adds that missing safety loop: compile, audit against OSV.dev,
constrain vulnerable versions out of the result, and retry until the lock file is
clean or the configured limit is reached.
Why use it?
- Keep the familiar
pip-compileworkflow. - Block vulnerable package versions before they land in
requirements.txt. - Use severity thresholds, allowlists, JSON reports, and CI-friendly exit codes.
- Cache OSV results locally so repeated runs stay fast.
- Pass normal
pip-compileflags through when you need them.
Installation
pip install safe-pip-compile
Project page: https://pypi.org/project/safe-pip-compile/
Quick start
safe-pip-compile requirements.in -o requirements.txt
Input:
django
requests
Output:
# Generated by safe-pip-compile
# Vulnerable versions are excluded when OSV.dev reports a blocking CVE.
django==...
requests==...
How it works
requirements.in
-> pip-compile
-> parse resolved packages
-> check local cache or query OSV.dev
-> filter by severity and allowlist
-> add temporary constraints for vulnerable versions
-> repeat until clean, stuck, or max iterations is reached
-> requirements.txt
When a vulnerable package is found, safe-pip-compile asks the resolver for a safe
alternative by adding constraints such as django>=3.2.25. It keeps the dependency
resolver in charge instead of hand-editing pinned output.
CLI flags
| Flag | Description | Default |
|---|---|---|
-o, --output-file PATH |
Output requirements.txt path |
requirements.txt |
--min-severity LEVEL |
Only block CVEs at this level or above: critical, high, medium, low |
low |
--allow-list PATH |
YAML file of accepted CVEs to skip | none |
--max-iterations INT |
Maximum compile/audit loops before stopping | 10 |
--strict / --no-strict |
Exit with code 1 if unresolved CVEs remain |
--strict |
--dry-run |
Preview actions without writing output files | off |
--json-report PATH |
Write a machine-readable JSON vulnerability report | none |
--cert PATH |
CA bundle for SSL verification behind corporate proxies | auto-detect from env |
--no-cache |
Disable the local CVE cache and always query OSV.dev | cache enabled |
--refresh-cache |
Clear cached data and re-fetch from OSV.dev | off |
-v, --verbose |
Increase output detail. Use -v or -vv |
quiet |
All other flags after -- are passed through to pip-compile.
safe-pip-compile requirements.in -- --generate-hashes --allow-unsafe
Examples
Block only high and critical vulnerabilities:
safe-pip-compile requirements.in --min-severity high
Accept specific CVEs through an allowlist:
safe-pip-compile requirements.in --allow-list cve-allowlist.yaml
Generate a JSON report and fail CI 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
Bypass or refresh the local cache:
safe-pip-compile requirements.in --no-cache
safe-pip-compile requirements.in --refresh-cache
Allowlist format
Create cve-allowlist.yaml when your team has reviewed and accepted a specific
risk:
allowed_cves:
- id: CVE-2024-12345
reason: "Not applicable; we do not use the affected feature"
expires: 2025-06-01
- id: GHSA-xxxx-yyyy-zzzz
reason: "Accepted risk, tracked in JIRA-789"
Allowlist entries are matched against the vulnerability ID and aliases such as CVE, PYSEC, and GHSA identifiers.
pyproject.toml config
[tool.safe-pip-compile]
max-iterations = 10
min-severity = "high"
allowlist = "cve-allowlist.yaml"
strict = true
CLI flags override pyproject.toml values.
Exit codes
| Code | Meaning |
|---|---|
0 |
Clean result: no blocking CVEs found |
1 |
Unresolved CVEs remain in strict mode |
2 |
pip-compile resolution failed |
3 |
Network or configuration error |
Local CVE cache
Vulnerability data is cached in a local SQLite database to avoid repeated OSV.dev API calls.
| Platform | Cache path |
|---|---|
| Linux | ~/.cache/safe-pip-compile/cache.db |
| macOS | ~/Library/Caches/safe-pip-compile/cache.db |
| Windows | C:\Users\Teja\AppData\Local\safe-pip-compile\Cache\cache.db |
Cache behavior:
- Fixed vulnerabilities are cached for 6 months.
- Vulnerabilities without a fix are not cached permanently, so a newly published fix can be picked up on a later run.
- The cache is stored per user and works across virtual environments.
- SQLite WAL mode allows concurrent readers.
Corporate proxy and SSL
If your organization performs SSL inspection, OSV.dev requests may fail with a certificate verification error.
Use a custom CA bundle:
safe-pip-compile requirements.in --cert /path/to/corporate-ca-bundle.pem
Or set one of the standard certificate environment variables:
export SSL_CERT_FILE=/path/to/corporate-ca-bundle.pem
export REQUESTS_CA_BUNDLE=/path/to/corporate-ca-bundle.pem
Lookup order:
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
Author
Built and maintained by N Venkata Sai Teja.
For more projects, writing, and contact details, visit venkatasaiteja.in or connect on LinkedIn.
License
This project is licensed under the MIT License.
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 safe_pip_compile-0.1.3.tar.gz.
File metadata
- Download URL: safe_pip_compile-0.1.3.tar.gz
- Upload date:
- Size: 25.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
44709ca3e1fff966f51e28f97c0ab1f5688ab96003d269495085ac944b40e23d
|
|
| MD5 |
48807744727997c5a1c271937b0f483d
|
|
| BLAKE2b-256 |
a591a7476bcd90101119c29b2c9bb4d835e9086027749d04102d73bafa407021
|
Provenance
The following attestation bundles were made for safe_pip_compile-0.1.3.tar.gz:
Publisher:
publish.yml on sai1027/safe-pip-compile
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
safe_pip_compile-0.1.3.tar.gz -
Subject digest:
44709ca3e1fff966f51e28f97c0ab1f5688ab96003d269495085ac944b40e23d - Sigstore transparency entry: 1432030606
- Sigstore integration time:
-
Permalink:
sai1027/safe-pip-compile@818884b8a1973e0caa6926e620ad5badfac86ab0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/sai1027
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@818884b8a1973e0caa6926e620ad5badfac86ab0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file safe_pip_compile-0.1.3-py3-none-any.whl.
File metadata
- Download URL: safe_pip_compile-0.1.3-py3-none-any.whl
- Upload date:
- Size: 28.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1addbaab70cfb7aa3be4b51e4eaaab7d3780d6ee1d60663843eff891753d61d8
|
|
| MD5 |
a235ac71455fa09861d1b576f30392c5
|
|
| BLAKE2b-256 |
d98fcd3ee652acaabbd0aa0117bf48f2ec2ec065d4c94626a34212b1e8c38c31
|
Provenance
The following attestation bundles were made for safe_pip_compile-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on sai1027/safe-pip-compile
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
safe_pip_compile-0.1.3-py3-none-any.whl -
Subject digest:
1addbaab70cfb7aa3be4b51e4eaaab7d3780d6ee1d60663843eff891753d61d8 - Sigstore transparency entry: 1432030735
- Sigstore integration time:
-
Permalink:
sai1027/safe-pip-compile@818884b8a1973e0caa6926e620ad5badfac86ab0 -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/sai1027
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@818884b8a1973e0caa6926e620ad5badfac86ab0 -
Trigger Event:
push
-
Statement type: