"Securing Your Python Dependencies: A Practical Guide"
Python dependencies are the #1 attack vector. Here's how to scan, fix, and prevent vulnerable packages in your Python projects. Covers pip, Poetry, pipenv, and conda.
Every pip install you run brings code you didn't write into your project. Some of that code has known security vulnerabilities. This guide shows you how to find and fix them — across every Python package manager.
Why Python Dependencies Are Risky
Python's package ecosystem is massive:
- 500,000+ packages on PyPI
- Average Python project: 50-200 direct dependencies, 200-500 transitive
- Vulnerability rate: ~5% of popular packages have at least one CVE
- Update lag: Many packages are updated months after vulnerabilities are disclosed
The numbers mean: if you have 100 dependencies, statistically 5 of them have known CVEs right now.
Scanning Dependencies
Method 1: VulnLedger (Recommended)
pip install vulnledger
vulnledger scan .
Checks all dependencies — direct and transitive — against OSV.dev. Works with pip, Poetry, pipenv, and conda.
Method 2: pip-audit
pip install pip-audit
pip-audit
Checks against the Python Packaging Advisory Database. Good for quick checks, but only checks direct dependencies well.
Method 3: Safety
pip install safety
safety check
Checks against the Safety database. Similar to pip-audit.
Why VulnLedger is better: It scans the full transitive tree, generates SBOMs, and provides CI/CD integration. The others are fine for quick checks but miss transitive vulnerabilities.
Fixing Vulnerable Dependencies
Step 1: Identify the Fix Version
vulnledger scan . | grep "fixed_version"
This shows which version to upgrade to.
Step 2: Check for Breaking Changes
Before upgrading, check the changelog:
# Check what changed
pip install --dry-run requests==2.31.0
# Read the changelog
# https://docs.python-requests.org/en/latest/changes/
Step 3: Upgrade
# Direct upgrade
pip install requests==2.31.0
# Upgrade all outdated packages
pip install --upgrade -r requirements.txt
# With Poetry
poetry update requests
# With pipenv
pipenv update requests
Step 4: Test
pytest
Always test after upgrading. Breaking changes can be subtle.
Step 5: Update Lock File
# Poetry
poetry lock
# Pip-tools
pip-compile requirements.in
Package Manager Specific Advice
pip + requirements.txt
# Pin exact versions
pip install requests==2.31.0 -r requirements.txt
# Use pip-tools for lock files
pip install pip-tools
pip-compile requirements.in # Generates requirements.txt with hashes
Poetry
# Poetry automatically handles transitive deps
poetry update requests
# Lock file ensures reproducibility
poetry.lock # Generated automatically
pipenv
# pipenv also handles transitive deps
pipenv update requests
# Lock file
Pipfile.lock # Generated automatically
conda
# Update specific package
conda update requests -n myenv
# Update all
conda update --all -n myenv
Preventing Future Vulnerabilities
1. Pin Dependencies with Hashes
# requirements.txt
requests==2.31.0 --hash=sha256:abc123...
2. Use Lock Files
Lock files pin exact versions of ALL dependencies (direct + transitive). Never deploy without a lock file.
3. Add CI/CD Scanning
- name: Scan dependencies
run: |
pip install vulnledger
vulnledger scan . --ci
4. Monitor for New CVEs
# Daily scan
vulnledger scan . --json --output daily.json
5. Review New Dependencies
Before adding a new dependency:
- Check its GitHub stars and last update date
- Scan it for CVEs: pip install vulnledger && vulnledger scan .
- Check its license
- Check its maintainer activity
Common Python Dependency Mistakes
Mistake 1: Not pinning versions
pip install requests installs the latest version, which may break tomorrow.
Mistake 2: Ignoring transitive dependencies
Your requirements.txt lists 10 packages. Those pull in 200+ transitive deps. Scan them all.
Mistake 3: Not using lock files
Without a lock file, different team members may install different versions.
Mistake 4: Running as root in Docker
Running pip as root in Docker containers can install malicious packages from compromised registries.
Mistake 5: Not scanning dev dependencies
Test frameworks and linters have CVEs too. Scan everything.
How VulnLedger Helps
VulnLedger provides complete Python dependency security:
1. Scans all package managers — pip, Poetry, pipenv, conda
2. Full transitive tree — not just direct dependencies
3. CI/CD integration — fails builds on critical CVEs
4. SBOM generation — compliance-ready dependency inventory
5. Continuous monitoring — catches new CVEs as they're published
pip install vulnledger
vulnledger scan .
Conclusion
Python dependency security is the most impactful thing you can do for your project's security. One scan catches dozens of vulnerabilities. One CI/CD gate prevents them from coming back. The tools are free, the process takes minutes.
Previous: Python Security Best Practices 2026
Next: Python Web App Security: Flask, FastAPI, Django
See also: Dependency Security: How to Scan and Fix Vulnerable Packages