auditing-python-dependencies

star 2.3k

Audit a Python project's installed dependencies for known CVEs by wrapping pip-audit (PyPA's official vulnerability auditor) and emitting findings in the canonical penetration-tester schema. Detects vulnerable direct AND transitive packages, normalizes pip-audit's severity output via OSV severity bands, falls back to pip list --outdated when pip-audit isn't installed, and supports requirements.txt, pyproject.toml (PEP 621), Pipfile.lock, and poetry.lock as input sources. Use when: pre-merge gate on a Python project, post-incident sweep after a PyPI compromise (e.g. ctx, request-toolbelt typosquats, ultralytics 8.3.42 compromise), SOC2 evidence collection, or inheriting an unfamiliar Python codebase. Threshold: any HIGH or CRITICAL CVE in the resolved dependency tree. MODERATE / LOW reported informationally. Trigger with: "audit python deps", "pip vulnerability scan", "check pypi packages for CVEs", "pip-audit run".

jeremylongshore By jeremylongshore schedule Updated 6/8/2026

name: auditing-python-dependencies description: | Audit a Python project's installed dependencies for known CVEs by wrapping pip-audit (PyPA's official vulnerability auditor) and emitting findings in the canonical penetration-tester schema. Detects vulnerable direct AND transitive packages, normalizes pip-audit's severity output via OSV severity bands, falls back to pip list --outdated when pip-audit isn't installed, and supports requirements.txt, pyproject.toml (PEP 621), Pipfile.lock, and poetry.lock as input sources. Use when: pre-merge gate on a Python project, post-incident sweep after a PyPI compromise (e.g. ctx, request-toolbelt typosquats, ultralytics 8.3.42 compromise), SOC2 evidence collection, or inheriting an unfamiliar Python codebase. Threshold: any HIGH or CRITICAL CVE in the resolved dependency tree. MODERATE / LOW reported informationally. Trigger with: "audit python deps", "pip vulnerability scan", "check pypi packages for CVEs", "pip-audit run". allowed-tools: - Read - Bash(pip:) - Bash(pip-audit:) - Bash(python3:) - Glob disallowed-tools: - Bash(rm:) - Bash(curl:) - Bash(wget:) - Write(.env) - Edit(.env) - Bash(pip install:) - Bash(pip uninstall:) version: 3.0.0-dev author: Jeremy Longshore jeremy@intentsolutions.io license: MIT compatibility: Designed for Claude Code tags: - security - dependency-audit - python - pypi - cve - pentest

Auditing Python Dependencies

Overview

PyPI hosts north of 500,000 packages, with several thousand new releases every day. The package-install model is identical to npm in the relevant ways: a pip install resolves a transitive graph, runs each package's setup.py (which executes arbitrary Python at install time), and writes the result to your site-packages. The CVE attack surface is therefore the same shape: known vulnerabilities, maintainer-account takeovers, typosquats, and protestware.

The PyPA-blessed auditor is pip-audit. It queries the Open Source Vulnerabilities (OSV) database (which mirrors PyPA's advisory feed plus aggregated CVE / GHSA records) and reports per-package vulnerable versions. pip-audit integrates with requirements.txt, pyproject.toml, Pipfile.lock, and poetry.lock, so most Python project layouts are first-class.

This skill wraps pip-audit, normalizes its severity vocabulary to the shared Severity enum, and emits Findings in the canonical penetration-tester schema. If pip-audit isn't installed on the host, the skill falls back to pip list --outdated and emits INFO-level findings recommending the operator install pip-audit for accurate vulnerability detection.

When the skill produces findings

Finding Severity Threshold Affected control
Critical CVE in installed package CRITICAL OSV severity band corresponds to CVSS ≥ 9.0 CWE-1104
High CVE in installed package HIGH OSV severity band corresponds to CVSS 7.0–8.9 CWE-1104
Medium CVE in installed package MEDIUM OSV severity band corresponds to CVSS 4.0–6.9 CWE-1104
Low CVE in installed package LOW OSV severity band corresponds to CVSS 0.1–3.9 CWE-1104
Vulnerable package with no patch HIGH finding has no fix_versions and severity ≥ medium CWE-1395
Outdated package (no CVE) INFO pip list --outdated reports a newer version (operational)
pip-audit not installed INFO binary not on PATH; scanner fell back to pip list (operational)
Audit DB unreachable INFO pip-audit network error reaching OSV (operational)

OSV is the upstream of record. pip-audit also consults the PyPA advisory database for Python-specific records that may not yet have a CVE assigned.

Prerequisites

  • Python 3.9+
  • pip-audit installed (pip install pip-audit); skill falls back to pip list --outdated if absent
  • Target project containing at minimum one of: requirements.txt, pyproject.toml, Pipfile.lock, poetry.lock
  • Network access to OSV (api.osv.dev) and PyPI (pypi.org)

Instructions

Step 1 — Identify the scan target

Locate the project directory. The scanner auto-detects requirement files in order of preference:

  1. poetry.lock (most precise — exact resolved tree)
  2. Pipfile.lock
  3. requirements.txt (and requirements-*.txt siblings)
  4. pyproject.toml (PEP 621 dependencies)
  5. Installed environment via pip list (last resort)

Step 2 — Run the audit

python3 ./scripts/audit_python.py /path/to/python-project

Options:

Usage: audit_python.py PATH [OPTIONS]

Options:
  --output FILE      Write findings to FILE (default: stdout)
  --format FMT       json | jsonl | markdown (default: markdown)
  --min-severity SEV (default: info)
  --requirement FILE Override auto-detection; specify a particular
                     requirements file (repeatable)
  --include-dev      Include development dependencies (default: prod
                     only when project layout allows the distinction)
  --strict           Treat pip-audit warnings as errors

Step 3 — Interpret findings

CRITICAL / HIGH = block release.

MEDIUM / LOW = track but don't block; many Python advisories report edge-case theoretical issues that don't apply to your usage.

INFO = log only; e.g. "outdated but no known CVE" is information for your release cadence, not a security action.

Step 4 — Remediation

For a vulnerable package with fix_versions:

  1. Bump the version pin in your requirements file:

    - requests==2.20.0
    + requests==2.31.0
    
  2. Run pip install -r requirements.txt --upgrade (or poetry lock --no-update && poetry update <pkg>).

  3. Run the test suite. CVE fixes occasionally include behavioral changes you didn't expect.

  4. Commit the lock file diff alongside the requirements bump.

For a vulnerable transitive dep (one you didn't declare directly):

  1. Find the parent: pip show <vulnerable-package> lists the parents in its "Required-by" line.

  2. Check whether bumping the parent picks up the fix. pip index versions <parent> lists available versions.

  3. If parent doesn't have a newer release that floors the vulnerable dep above the fix version, pin the transitive dep yourself in your requirements file. pip will use the more specific pin.

For a vulnerable package with NO fix available:

  1. Subscribe to PyPA advisory notifications for that package.

  2. If the vulnerability is exploitable in your usage, either replace the package or vendor + patch locally.

  3. Document the exception in your security register with a re-evaluation date.

Examples

Example 1 — Pre-merge gate

python3 ./scripts/audit_python.py . --min-severity high --format json --output audit.json
jq -e '. == []' audit.json || { echo "High/critical Python CVE — fix before merge"; exit 1; }

Example 2 — CI scan on every push

- name: pip-audit
  run: pip install pip-audit
- name: Run audit
  run: |
    python3 plugins/security/penetration-tester/skills/auditing-python-dependencies/scripts/audit_python.py \
        . --min-severity high --format markdown --output py-audit.md

Example 3 — SOC2 evidence collection

mkdir -p evidence/CC7/
python3 ./scripts/audit_python.py . --include-dev --format json \
    --output evidence/CC7/py-audit-$(date +%Y%m%d).json

--include-dev for SOC2: include dev/test deps so auditors see the full surface, not just production.

Output

JSON / JSONL / Markdown per lib/report.py. Exit codes: 0 clean, 1 high/critical, 2 error.

Each Finding includes:

  • id — synthesized as pypi-audit::<cve-id> (or pypi-audit::<ghsa> / pypi-audit::<pypa-id> when no CVE)
  • severity — CRITICAL / HIGH / MEDIUM / LOW / INFO
  • categorydependency-vulnerability
  • summary — short CVE / GHSA title
  • evidence — affected package, affected version, fix versions, advisory ID
  • references — OSV URL, CVE URL, PyPA advisory URL

Error Handling

  • pip-audit not installed → falls back to pip list --outdated, emits an INFO Finding flagging the degraded scan, and proceeds.
  • No requirement file found → emits an INFO Finding "no Python project structure recognized" and exits 2.
  • OSV API unreachable → emits an INFO Finding documenting the outage and exits 0 (no actionable security finding).
  • pip-audit returns malformed JSON → emits an INFO Finding with the raw output truncated to 500 chars and exits 2.

Resources

  • references/THEORY.md — PyPI supply-chain history, OSV vs NVD vs PyPA advisory scopes, why ecosystem-specific severity matters, Python-specific install-time risks (setup.py execution, eager dependency resolution), pip-audit vs Safety vs Snyk trade-offs
  • references/PLAYBOOK.md — Per-toolchain remediation patterns (pip + requirements.txt, poetry, pipenv, uv, conda), monorepo / workspace scanning, override-equivalent patterns in Python ecosystem, GitHub Dependabot ecosystem mapping, SOC2 evidence retention
Install via CLI
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill auditing-python-dependencies
Repository Details
star Stars 2,344
call_split Forks 332
navigation Branch main
article Path SKILL.md
More from Creator
jeremylongshore
jeremylongshore Explore all skills →