Python Dependency Vulnerability Scanning — Core Concepts

The Supply Chain Problem

Modern Python applications don’t exist in isolation. A Django web app might directly depend on 15 packages, but after resolving transitive dependencies, it installs 80+. Each package is maintained independently, with its own release cycle, security practices, and vulnerability history.

The Open Source Vulnerabilities database (OSV) tracks thousands of Python package vulnerabilities. In 2023 alone, over 500 new CVEs were filed against PyPI packages. Many affected widely-used libraries with millions of downloads.

The Scanning Tools

pip-audit

Maintained by the Python Packaging Authority (PyPA), pip-audit checks installed packages against the OSV database — the same database Google uses for its vulnerability management.

It works with virtual environments, requirements.txt, and pyproject.toml. It can output JSON for CI pipeline consumption and supports automatic fix suggestions.

safety

The safety tool checks against Safety’s own curated vulnerability database. It parses requirements.txt directly (no installation needed) and offers a commercial tier with additional features.

Dependabot (GitHub)

GitHub’s built-in dependency scanner monitors your repository’s dependency files and automatically creates pull requests when vulnerabilities are discovered. It works with requirements.txt, Pipfile.lock, poetry.lock, and pyproject.toml.

Snyk

A commercial tool (with a free tier) that provides deeper analysis including reachability analysis — determining whether your code actually calls the vulnerable function, not just whether the vulnerable package is installed.

Vulnerability Databases

DatabaseMaintained ByCoverageUpdate Frequency
OSVGoogleBroad, multi-ecosystemContinuous
NVD (CVE)NISTComprehensiveDaily
GitHub AdvisoryGitHubCurated, high qualityContinuous
Safety DBSafety/SnykPython-focusedRegular
PyPI AdvisoryPyPIOfficial PythonAs reported

Tools often cross-reference multiple databases. pip-audit uses OSV by default but can also query PyPI’s advisory database.

Understanding Severity

Vulnerabilities are rated using CVSS (Common Vulnerability Scoring System), scored 0.0–10.0:

  • Critical (9.0–10.0): Remote code execution, complete system compromise. Drop everything and fix immediately.
  • High (7.0–8.9): Significant impact — data leaks, privilege escalation. Fix within days.
  • Medium (4.0–6.9): Conditional exploitation, limited impact. Schedule a fix.
  • Low (0.1–3.9): Minimal impact. Fix when convenient, often during regular updates.

Not all vulnerabilities affect you equally. A SQL injection vulnerability in a database driver matters if you use that driver. A denial-of-service vulnerability in a parsing library matters only if you parse untrusted input.

CI/CD Integration

The most effective approach runs scans on every pull request and on a daily schedule against the main branch. PR scans catch new vulnerabilities introduced by dependency changes. Daily scans catch newly disclosed vulnerabilities in existing dependencies.

A typical workflow: scan runs automatically, blocks the PR if critical or high vulnerabilities are found, and sends alerts for medium-severity findings. Low-severity findings are logged but don’t block deployment.

Response Workflow

When a vulnerability is discovered:

  1. Assess relevance. Does your code use the affected function? Is the vulnerability exploitable in your deployment context?
  2. Check for a patch. Is there a fixed version? Can you upgrade without breaking changes?
  3. Apply the fix. Upgrade the package, run your test suite, and deploy.
  4. If no fix exists: Apply a workaround (disable the affected feature, add input validation, use an alternative package), and monitor for a patch.
  5. Document the decision. If you accept the risk (the vulnerability doesn’t apply to your use case), document why so future auditors understand the reasoning.

Common Misconception

“Pinning dependencies protects you from vulnerabilities.” Pinning ensures reproducible builds, but it also ensures you keep running vulnerable versions unless you actively update. Pinning without scanning creates a false sense of security. You need both: pinning for reproducibility and scanning for security awareness.

Transitive Dependency Risk

Your direct dependencies are packages you chose deliberately. Transitive dependencies are packages your dependencies depend on — and you might not even know they exist. A vulnerability in a transitive dependency is just as dangerous, but harder to track.

Tools like pipdeptree visualize the dependency tree, showing exactly why each package is installed. When pip-audit reports a vulnerability in a package you don’t recognize, pipdeptree tells you which of your direct dependencies pulled it in.

The one thing to remember: vulnerability scanning isn’t a one-time audit — it’s a continuous process that must run automatically, because new vulnerabilities are discovered in already-released packages every single day.

pythonsecuritydevops

See Also

  • Python Certificate Pinning Why your Python app should remember which ID card a server uses — and refuse impostors even if they have official-looking badges.
  • Python Cryptography Library Understand Python Cryptography Library with a vivid mental model so secure Python choices feel obvious, not scary.
  • Python Hashlib Hashing How Python turns any data into a unique fingerprint — and why that fingerprint can never be reversed.
  • Python Hmac Authentication How Python proves a message wasn't tampered with — using a secret handshake only you and the receiver know.
  • Python Owasp Top Ten The ten most common ways hackers break into web apps — and how Python developers can stop every single one.