l0lsec/snitch

GitHub: l0lsec/snitch

Stars: 0 | Forks: 0

# snitch `snitch` is a defensive CLI that inventories every package, tool, extension, and binary you've installed and cross-references each one against advisory databases, IOC feeds, heuristic rules, and static-analysis checks. It runs locally, caches its intel, and produces a ranked report so you can decide what to remove. ## Status Alpha. The MVP scans `pip`, `npm`, Homebrew, Go binaries, Cursor/VS Code extensions, GitHub-cloned repos, and arbitrary binaries on `$PATH`. ## Install pipx install . # or, for development uv pip install -e ".[dev,ast]" ## Quickstart snitch update # refresh advisory + malicious-package mirrors snitch scan # scan every supported ecosystem snitch scan --ecosystem pip,npm --deep snitch inspect pip:requests@2.31.0 snitch report --format md --out report.md ## What it checks - **Advisories** — OSV.dev (covers GHSA, PyPA, npm, Go, RubyGems, crates.io). - **Known malicious packages** — local mirror of [`ossf/malicious-packages`](https://github.com/ossf/malicious-packages). - **Heuristics** — install/postinstall scripts, recent publishes, sole-maintainer flips, repo-URL mismatches, typosquats. - **Static analysis** — JS (tree-sitter) and Python (`ast`) rules for `eval`, `child_process`, `subprocess`, base64+exec, dynamic require/import, etc. - **Binaries** — SHA-256 + codesign + (opt-in) VirusTotal hash lookup. No file uploads. ## Configuration `snitch` keeps all its data in a single hidden directory so multiple checkouts can't poison each other. Each run it picks the best location automatically: 1. **App-local (default)** — `/.snitch/`, next to the `pyproject.toml` of the installed snitch package. Used when that directory is discoverable and writable. The `.snitch/` dir is `.gitignore`'d. 2. **XDG fallback** — `~/Library/Caches/snitch/` and `~/Library/Application Support/snitch/` on macOS (or `$XDG_CACHE_HOME` / `$XDG_CONFIG_HOME` on Linux). Used when there's no project root — typically a `pipx install snitch` into site-packages. Inside the chosen directory: - `snitch.db` — SQLite cache (advisories, malicious-package index, VT hashes, scan history). - `malicious-packages/` — local clone of [`ossf/malicious-packages`](https://github.com/ossf/malicious-packages). - `ignore.toml` — your allow-list. If you previously ran an older snitch and have data in XDG, the first run after this change migrates it automatically into the app-local directory so you don't have to re-download the 200k-entry mirror. snitch where # print the resolved data dir and whether legacy data exists snitch migrate # explicitly move XDG data into the app-local directory snitch ignore path # print the allow-list path Optional environment variables: - `SNITCH_VT_API_KEY` — VirusTotal API key for binary hash lookups. ## Adding a heuristic Drop a new rule in `src/snitch/heuristics/` that returns `Finding`s. Register it in the orchestrator. See `heuristics/npm_rules.py` for examples. ## License MIT