pysentry — dependency vulnerability scanner
What it is
- PySentry audits a Python project’s dependencies for known vulnerabilities by reading dependency/lock files and cross-referencing multiple vulnerability sources (PyPA advisory DB, PyPI JSON API, OSV).
- It’s written in Rust and emphasizes speed + caching.
- It supports multiple input formats (including
uv.lock,poetry.lock,Pipfile.lock,requirements.txt,pyproject.toml).
Key value (why teams adopt it)
- Enforces a repeatable “dependency risk check” in dev/CI without relying on ad-hoc manual audits.
- Especially useful when:
- you have multiple dependency sources (poetry + requirements files)
- you want SARIF output to integrate with code scanning tooling.
Installation and command naming (pitfall: there are two names)
PySentry exposes different command names depending on install method:
- Rust binary (cargo / release binaries):
pysentry - Python package (pip / uvx):
pysentry-rs(alsopython -m pysentry)
Practical advice:
- In docs/scripts, prefer invoking the installed entrypoint explicitly (e.g.
pysentry-rs) to avoid confusion across environments.
What files it scans and precedence rules
PySentry auto-detects project type by looking for these files (typical precedence/priority):
uv.lockpoetry.lockPipfile.lockpyproject.tomlPipfilerequirements.txt
Best practice:
- Prefer lockfiles (
uv.lock/poetry.lock/Pipfile.lock) for deterministic results. - Treat “constraints-only” inputs (
requirements.txtwith ranges) as higher-noise unless you also use a resolver ( below).
Resolver model (critical to understand for requirements.txt)
Why a resolver is needed
- Vulnerability checking needs concrete versions.
- If you only have version constraints (e.g.
flask>=2,<3), PySentry must resolve them into exact versions before scanning.
Supported resolvers and selection
- PySentry integrates with external resolvers:
uv(preferred; Rust-based)pip-tools(alternative)
- Auto-detection prefers:
uv>pip-tools. - Without a resolver present, it can still scan lockfiles like
uv.lockandpoetry.lock, butrequirements.txtscanning will fail or be limited.
Common pitfall:
- Running PySentry in an environment where
uv/pip-toolsis not installed (e.g., slim CI image) → “No dependency resolver found”.
Core CLI options you’ll actually use
Target path
- Scan current directory or a given path:
pysentry /path/to/project
Force a specific resolver
pysentry --resolver uv /path/to/projectpysentry --resolver pip-tools /path/to/project
Scope control (extras/dev deps)
pysentry --exclude-extra- Interprets as “main only” dependencies (exclude optional/extras/dev-ish scopes).
Pitfall:
- Teams sometimes unknowingly scan only main deps and miss risk in build/test tooling that is still present in many environments. Decide explicitly.
Severity filtering
pysentry --severity high(example: show only high/critical).
Best practice:
- Use severity filters primarily for “human output”; keep the raw report unfiltered for auditing/triage workflows.
Output formats and files
- Output formats include: human-readable, JSON, SARIF, Markdown.
- Example:
pysentry --format json --output audit-results.jsonpysentry --format sarif --output security-report.sarifpysentry --format markdown --output security-report.md
Vulnerability sources
- Uses multiple data sources by default (PyPA, PyPI, OSV).
- Can select sources explicitly via repeated
--sources:--sources pypa --sources osv
Best practices
Make dependency representation deterministic
- Prefer:
uv.lock/poetry.lock/Pipfile.lock
- Avoid relying on constraint-only
requirements.txtunless:- you resolve pins as part of the workflow, and/or
- you accept that “resolved today” may differ from “resolved tomorrow”.
Separate “reporting” from “gating”
- Reporting run (full output, SARIF/JSON) for triage.
- Gating run (stricter) for release branches:
- typically only fail on high/critical, or on fixable known-bad packages (team policy decision).
Treat “transitive vuln” as a workflow problem, not only a scanning problem
- If most findings are transitive:
- track upgrade paths (which top-level dep bumps fix it)
- consider constraints/overrides policy (careful: can break runtime compatibility)
Common pitfalls and how to handle them
Confusing PySentry with “Sentry (error monitoring)”
- PySentry is a dependency vulnerability scanner.
- Sentry is application error/performance monitoring (different product/tooling).
“No lock file or pyproject.toml found”
- Ensure you run it in the project directory or pass the path.
“No dependency resolver found”
- Install
uvorpip-toolsin the environment where you run PySentry. - In CI, don’t assume your runtime image has it.
Barrel imports / multiple requirements files
- If you split requirements files, PySentry can include multiple requirements inputs via repeated flags:
pysentry --requirements requirements-dev.txt --requirements requirements-test.txt
- Pitfall: you think you scanned “everything” but only scanned the default detected file.
Performance and caching
PySentry uses caching and provides cache controls; when things look “stuck” or inconsistent:
- Clear all caches (manual paths vary by OS)
- Or use CLI:
pysentry --clear-resolution-cache
- Debug:
pysentry --verbose
- Isolate:
pysentry --no-cache
Best practice:
- If you run it frequently, keep caching enabled; only disable when debugging.
Minimal “starter commands” to memorize
- Default scan:
pysentry .
- Deterministic, lockfile-first workflow:
- ensure
uv.lockorpoetry.lockis present, thenpysentry .
- ensure
- Requirements workflow (resolver explicitly pinned):
pysentry --resolver uv .
- CI-friendly artifacts:
pysentry --format sarif --output security-report.sarif .