Skip to main content

pkg-doctor

Scan your local projects for known-vulnerable or hijacked dependencies, and get guided, human-approved help rotating any API keys that might be exposed as a result.

pip install pkg-doctor
pkg-doctor --path ./my-project

The problem

Every so often a popular package gets compromised - a maintainer's account is hijacked, or malicious code slips into a new release. When it happens, the advisory that follows always says the same thing: "rotate all your API keys." Nobody actually knows which of their dozen local projects use the affected version, so people either panic-rotate everything or ignore the warning and hope for the best.

pkg-doctor replaces the guessing with one command: it tells you exactly which local projects are affected, and walks you through fixing exactly those - nothing more.


What it does

pkg-doctor --path ~/projects/foo
pkg-doctor --path ~/projects/foo --path ~/projects/bar --include-self
  1. Scans the directories you name for dependency manifests (requirements.txt, package-lock.json)
    • nothing is scanned unless you pass --path.
  2. Checks every pinned package against OSV.dev - a free, public vulnerability database that also ingests the OpenSSF malicious-packages feed, which is exactly the "a package got hijacked" case, not just an ordinary CVE. Results are flagged and clearly distinguished: MALICIOUS PACKAGE vs. VULNERABLE.
  3. If a project is flagged, it checks that project's .env/config files - not by guessing at variable names (anyone can name a credential anything), but by surfacing every assignment for you to judge. A value matching a known shape (OpenAI, Anthropic, Google, AWS, GitHub) gets a precise high-confidence label; everything else is still surfaced, just marked low-confidence. Values are only ever shown masked (sk-ab12...wx9y), never logged or transmitted anywhere.
  4. For each possible exposed key, it asks you first. Nothing is ever rotated automatically. Say yes, and it opens the provider's key-management dashboard in your browser and walks you through revoking the old key and generating a new one - then waits for your confirmation before moving on.

No API key, no LLM, no account required. It never sends anything more than a package name, ecosystem, and version to OSV.dev - never file contents, paths, or secret values.


Install

pip install pkg-doctor

Works on Windows, macOS, and Linux - Python 3.10+, only two dependencies (click, requests).


Usage

# Scan one project
pkg-doctor --path ./my-project

# Scan several at once
pkg-doctor --path ~/dev/billing-service --path ~/dev/auth-service

# Also audit pkg-doctor's own installed dependencies
pkg-doctor --path ./my-project --include-self

# Skip the config-file scan entirely (vulnerability check only)
pkg-doctor --path ./my-project --skip-secrets

Example output:

~/dev/billing-service
  MALICIOUS PACKAGE: some-lib==2.1.0 (MAL-2026-4821)
    https://osv.dev/vulnerability/MAL-2026-4821

  Possible exposed secret (high confidence)
    Provider: OpenAI
    File:     ~/dev/billing-service/.env
    Value:    sk-ab12...wx9y
  Rotate this key now? [y/N]:

What it deliberately does not do

  • Never rotates anything without your explicit y - no automation, no "trust me" mode.
  • Never touches secrets managers (HashiCorp Vault, AWS Secrets Manager, etc.) - it only reads local flat files (.env, .env.local, .env.production, .env.development, config.json, secrets.json, credentials.json, .npmrc). If your secrets already live in a real vault, this tool has nothing to say about them - but the dependency-vulnerability check still applies regardless of where secrets live.
  • Never scans anything you didn't name - no default-scan-your-whole-drive behavior.
  • Never calls an LLM - this is plain text/JSON/TOML/YAML parsing plus one REST API call to OSV.dev. Nothing here reads or transmits your files through a language model.

Supported manifests

Ecosystem File Notes
Python (pip) requirements.txt Exact-pinned name==version lines only - unpinned lines are reported separately, not silently skipped
Python (Poetry) poetry.lock
Node (npm) package-lock.json Lockfile v1/v2/v3
Node (Yarn) yarn.lock Classic (v1) and Berry (v2+)
Node (pnpm) pnpm-lock.yaml lockfileVersion 5/6/9 key formats
Go go.sum
Java/Kotlin (Gradle) gradle.lockfile Modern single-file dependency locking (opt-in via dependencyLocking)
Java (Maven) pom.xml Only literally-pinned <version> tags - versions from a parent POM/BOM, a ${property}, or a range are reported as unverifiable, not guessed at (Maven has no resolved-lockfile equivalent)

Other manifests found (Pipfile.lock, Gemfile.lock, build.gradle, build.gradle.kts) are reported as "found but not yet supported" rather than silently ignored - build.gradle/.kts are executable scripts, not data, so they aren't parsed; enable Gradle dependency locking for accurate scanning instead.


License

MIT - see LICENSE

Release files for pkg-doctor 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pkg-doctor 0.1.1
File Size Uploaded
pkg_doctor-0.1.1.tar.gz 15.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pkg-doctor 0.1.1
File Interpreter ABI Platform
pkg_doctor-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 29.9 kB

Release files / pkg_doctor-0.1.1.tar.gz

Download URL pkg_doctor-0.1.1.tar.gz
Size 15.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9dbd8dcd04c98b14231ecd29627e2e934f9ec31979826a87f5a36ee182207e0b
BLAKE2b-256 checksum
How to use checksums
dffdf2cbe7148ceb9a0584bafd86e736ebe528618ced8d4bfc73e146e5d47924
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.11

Release files / pkg_doctor-0.1.1-py3-none-any.whl

Download URL pkg_doctor-0.1.1-py3-none-any.whl
Size 14.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
49d92900da70c8c99248134d94efea18acd7d709fc037a3741c4a85ce5c429df
BLAKE2b-256 checksum
How to use checksums
56895cea94160806991ffafc56896e5259cc5fabbe1e32636f3f299bb4ed98a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.11

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page