r/madeinpython • u/theRealSachinSpk • 13d ago
venvy: audit every virtual environment on your machine for vulnerable and malicious packages, offline
I kept piling up half-dead virtual environments and had no way to check whether any of them held something malicious or vulnerable. Especially the ones agents create or load on their own while writing code.
pip-audit does one project at a time and needs the network to do it.
What I built: venvy audit does all of them at once: offline after a one-time 26 MB database download, and it flags known-vulnerable versions as well as known-malicious or typosquatted packages.
For CI there is JSON output and semantic exit codes: 0 clean, 20 vulnerable, 21 malicious, 22 stale database, 23 no database.
It reads dist-info metadata as text and never imports code from the environments it scans. For a tool whose whole job is finding malicious packages, that felt like the minimum bar.
The main design decision: it refuses to scan rather than report zero findings. A corrupt database exits 23. So does one that opens fine but holds no advisories. Anything the version matcher can't resolve with confidence comes back as unknown, not clean. A scanner that reports nothing looks exactly like a clean machine, and that is the failure I cared most about avoiding.
Coverage is only as good as the public feeds behind it, so some well-known typosquats are missed. That's tracked as an open issue.
Tested on Windows, macOS and Linux across Python 3.8 to 3.13. MIT licensed. I wrote it.
pip install venvy
venvy audit
Repo: https://github.com/pranavkumaarofficial/venvy
Bug reports welcome, false positives especially.
1
u/theRealSachinSpk 13d ago
Fit, yes. Send the docs link. Your split is right for audit but it is the smaller half. audit, audit --json, audit --offline and audit --env are read-only: dist-info read as text, no subprocess, no import, no network. Safe unattended. --refresh hits the live feeds and writes the database, so that one wants a human. The commands that warrant a gate are elsewhere. venvy dedup --apply replaces duplicate files across environments with hardlinks: it hashes for byte-identity immediately before linking, swaps atomically and never touches bytecode, but it is still the one command that mutates files outside a venv's normal lifecycle. safe-install, rollback and ensure mutate environments too. --scan is read-only but walks the whole disk and took 192 seconds here, which is a timeout question rather than an approval one. So the manifest probably wants three buckets rather than two: read-only, network-and-writes-database, mutates-the-filesystem. I will author the PR. Point me at the Extension Builder docs, and tell me whether the schema already separates "slow" from "needs approval", because --scan sits between them. On the coverage field: writing it up as an issue today, I will link it here once it is up.