A minimal-dependency CLI that calls the MistEye threat intelligence API to scan project dependencies and globally installed packages for known malicious packages and versions.
Important: DepScan only uploads package names and their version numbers (e.g.
requests==2.32.3,lodash@4.17.21) to the MistEye API for threat lookup.It does not collect or transmit your source code, file contents, project paths, environment variables, API keys, credentials, or any other private data. Dependency discovery and manifest parsing run entirely on your machine.
- Minimal runtime dependencies (Python 3.10+;
tomliis installed automatically on 3.10 forpyproject.tomlparsing) - Simple commands:
scan/global/check - Multi-ecosystem manifest and lock parsing: npm, PyPI, Rust, Go, RubyGems
- Global scanning for system Python, Node globals (npm/pnpm/yarn/nvm), Rust
cargo install, and Gogo installbinaries - Output: terminal table / JSON / SARIF
- API rate limiting (10 req/s)
- Per-package progress during scans; save full reports with
-o
git clone <your-repo-url>
cd MisteyeDepscan
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
# Scan current project
depscan scan .
# Scan globally installed packages (system Python, Node globals)
depscan globalAfter installing in a virtual environment, depscan is available in that environment’s bin directory (e.g. .venv/bin/depscan) while the venv is activated.
depscan global scans npm -g, pnpm -g, yarn global, and packages under nvm / fnm / volta version directories (not only the active npm root -g).
| Tool | Typical root | Installed npm packages |
|---|---|---|
| nvm | ~/.nvm (or $NVM_DIR) |
~/.nvm/versions/node/v<version>/lib/node_modules/ |
| pnpm global | Varies by install | Run pnpm root -g; on macOS often ~/Library/pnpm, on Linux often ~/.local/share/pnpm |
- For a custom directory tree, use
depscan scan <path> --depth 0.
You can also run without relying on depscan on PATH:
python -m misteye_depscan scan .pip install creates the depscan script, but the install location depends on your Python and OS and may not be on PATH. If pip prints The script depscan is installed in '...' which is not on PATH, use that path, or find the user scripts directory:
python3 -m site --user-base
# Scripts are usually at: <output>/binTo use it globally, add that bin directory to your shell config (paths vary by Python version—do not hardcode 3.10):
export PATH="$(python3 -m site --user-base)/bin:$PATH"Add to ~/.zshrc or ~/.bashrc and open a new terminal. Using a venv (above) is still the most reliable approach for development.
Registered in pyproject.toml:
[project.scripts]
depscan = "misteye_depscan.cli:main"Install generates a depscan entry point that calls main() in src/misteye_depscan/cli.py. Module entry: src/misteye_depscan/__main__.py.
Create a free API key at app.misteye.io/api-keys.
Either:
export MISTEYE_API_KEY="your-api-key"Or save to a config file (must be mode 600):
mkdir -p ~/.config/misteye
printf '%s' "$MISTEYE_API_KEY" > ~/.config/misteye/api_key
chmod 600 ~/.config/misteye/api_keyOn first interactive run without a key, the tool prompts you to enter and save one.
# Scan current project
depscan scan .
# Scan a specific project
depscan scan /path/to/project
# Scan Mac system-level global environments (default)
# - Python: Homebrew /usr/local / system Framework paths (excludes project .venv)
# - Node: npm -g, pnpm -g, yarn global, nvm/fnm/volta per-version globals
depscan global
# Python or Node global only
depscan global --python-only
depscan global --node-only
# Check a single package
depscan check requests==2.32.3 --pypi
depscan check lodash@4.17.21 --npm
# JSON / SARIF (CI-friendly)
depscan scan . --json
depscan scan . --sarif
depscan global --json
# Save full report to a file
depscan scan . -o report.json
depscan global -o global-report.json
# Control scan depth (default: 10 levels)
depscan scan . --depth 20 # deeper
depscan scan . --depth 1 # only root level
depscan scan . --depth 0 # unlimited (full recursive)Every scan queries the MistEye API (no local result cache). This ensures newly discovered threats are never missed.
Each completed package prints one line (concurrent scan; order may differ from the dependency list):
[1/120] requests==2.32.3 → No threat record
[2/120] lodash@4.17.21 → No threat record
[3/120] evil-pkg@1.0.0 → Threat detected · critical
API status: unknown is shown as No threat record (green), not the raw word unknown; this does not mean the package is guaranteed safe.
Save full report: depscan scan . -o report.json or depscan global -o global-report.json.
Quiet mode: --quiet. Disable colors: depscan --no-color scan . or NO_COLOR=1.
Aligned with MistEye: npm, PyPI, Rust, Go, and RubyGems auto-detect and scan.
| Ecosystem | Marker files | Status |
|---|---|---|
| npm | package.json, package-lock.json, yarn.lock, pnpm-lock.yaml |
Supported |
| PyPI | pyproject.toml, requirements*.txt, Pipfile, Pipfile.lock, poetry.lock, uv.lock, setup.py, setup.cfg |
Supported |
| Rust | Cargo.toml, Cargo.lock (workspace prefers root Cargo.lock) |
Supported |
| Go | go.mod, go.sum (prefer go.sum when present) |
Supported |
| RubyGems | Gemfile, Gemfile.lock |
Supported |
Auto-detect rules
- Finds marker files under the project tree, skipping
node_modules/,vendor/,.venv/,venv/,.tox/,site-packages/,dist/,build/, etc. - Skipping those dirs only affects where manifests are discovered; installed packages under
node_modules/are still scanned (each package’spackage.json).
Override auto-detect
depscan scan . --ecosystem=npm
depscan scan . --ecosystem=pypi
depscan scan . --ecosystem=rust
depscan scan . --ecosystem=go
depscan scan . --ecosystem=rubygems
depscan scan . --ecosystem=all
depscan scan . --ecosystem=npm,pypi,rust,go,rubygems # default when omitted = auto-detect
# Manifest/lock only (skip node_modules installed tree)
depscan scan . --no-node-modulesDefault (auto-detect npm / PyPI / Rust / Go / RubyGems)
- PyPI:
requirements*.txt,pyproject.toml(PEP 621 + Poetry[tool.poetry]includinggroup.*.dependencies),Pipfile,Pipfile.lock,poetry.lock,uv.lock,setup.py,setup.cfg - npm:
package.json,package-lock.json,pnpm-lock.yaml,yarn.lock, andnode_modules/**/package.json - Rust:
Cargo.lock(preferred in workspaces; falls back toCargo.tomlwhen needed) - Go:
go.sum(preferred over same-modulego.mod) - RubyGems:
GemfileandGemfile.lock
Java / Maven is not supported. The MistEye Detect API does not yet expose a
package:maventype, so Java coordinates are intentionally not scanned to avoid false positives.
MistEye Detect API uses status:
{ "status": "malicious", "matches": [...] }
{ "status": "unknown", "matches": [] }API status |
Meaning |
|---|---|
malicious |
Matched known threat intelligence |
unknown |
No match in the database (shown as No threat record; not guaranteed safe) |
Exit codes
| Code | Meaning |
|---|---|
| 0 | Scan finished; no malicious packages (includes unknown items) |
| 1 | Malicious package or version found |
| 2 | Incomplete scan (API/network/coverage) |
| 3 | Configuration error (bad path, missing API key) |
PyPI uses name==version; npm and other ecosystems use name@version for both display and API requests. Cross-ecosystem matches (e.g. an npm-only threat indicator returned for a PyPI scan) are ignored to avoid false positives caused by same-name packages across ecosystems.
- MistEye API docs: https://app.misteye.io/api-docs
- MistEye API keys: https://app.misteye.io/api-keys
- MistEye Security Gate: https://github.com/slowmist/misteye-skills
MIT