pip-audit: Python dependency checks explained

pip-audit checks Python requirement files against published advisories; DevFlow passes it every requirements*.txt file it finds, in 1 call, and keeps one finding per package and advisory.

What the tool is

pip-audit is a command-line auditor for Python environments and requirement files, maintained under the Python Packaging Authority. It resolves the dependencies a requirement file names and checks every resolved version against advisory data from PyPI and OSV.

How DevFlow finds the files

DevFlow's Python scanner walks the repository tree for names that start with requirements and end in .txt, so requirements.txt, requirements-dev.txt and similar files are all picked up. The walk skips .git, node_modules, virtual environments, caches and build output, and it stops after 500 matches.

Python layouts often nest a requirement file under src/ or keep one per service, which is why the walk goes beyond the root.

One call for every file

Everything found goes into a single call, with JSON output, the progress spinner off and one -r flag per path. Because each path's full dependency tree is resolved, a vulnerability in a transitive package surfaces even when only top-level packages are pinned.

The same package and advisory can appear through several paths, so DevFlow keeps one finding per package and advisory id. pip-audit exits with status 1 when it finds vulnerabilities, which DevFlow treats as normal as long as JSON came back.

What each finding records

  • the advisory id, often a PYSEC or GHSA id;
  • the package name;
  • a title cut from the first sentence of the advisory description, at most 160 characters long;
  • every fix version, joined in one field;
  • a link to the GitHub advisory page when the id or one of its aliases is a GHSA id, and to osv.dev otherwise.

Reading the fix versions

A package with several maintained release lines can list more than one fixed release, for example one per line. Pick the release on the line you already use, which is usually the smallest change, and let the next scan confirm that the finding is gone.

A worked example

Suppose a repository has requirements.txt at the root and services/api/requirements.txt below it, and both pin the same web framework release with one advisory. pip-audit sees that package twice, once per path. The report holds it once, with every listed fix version.

Limits worth knowing

Resolving dependencies can need the network, and the whole call shares the 300-second default limit of every scanner. A timeout records an error for the Python scanner while the others still report their results.

Where results go

Findings are listed by name in the task's scan report, and the merge evidence section of the pull request counts them by severity for each repository. The recurring vulnerability poll runs the same scan on the default branch, every 12 hours by default.

FAQ

Does DevFlow run pip-audit on a project with only a pyproject.toml?

No. DevFlow's Python scanner, which drives pip-audit, needs at least one requirements*.txt file; a project that ships only pyproject.toml or poetry.lock is skipped, because checking it would mean building it in the shared scanner container.

Why do pip-audit findings in DevFlow have unknown severity?

The JSON output of pip-audit carries no severity, so DevFlow records every such finding as unknown instead of guessing a level.