Skip to content

About

Dependency vulnerability checker for AI assistants: a CLI, an MCP server and a local dashboard. Scans Rust, JS/TS, PHP, Go and Python lockfiles against OSV, ranked by CISA KEV and EPSS.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

opencraysec — current vulnerability data for your coding agents

ci audit license: MIT release

A model's training data is months old. Advisories are published every day. opencraysec gives your AI assistant (or you, on the command line) a fast way to check a project's dependencies against today's public advisories, rank what matters, say whether your own code uses the vulnerable package, and prove a fix worked. Every scan, fix and verification is logged, so you can see what the assistant changed, and why, in a dashboard.

One static binary. An MCP server and a CLI. No account, no API key, and your source code never leaves your machine.

What you get

  • Many languages: Rust, JavaScript/TypeScript, PHP, Go and Python lockfiles, and the GitHub Actions your workflows use.
  • Current, public data only: OSV (which aggregates GitHub Advisories, RustSec, the Go vulnerability database and more), the CISA Known Exploited Vulnerabilities list, FIRST EPSS scores, the MITRE CWE catalog and NVD scores. CVE ids, CWE weakness classes and CVSS come with the advisories. See docs/DATA-SOURCES.md.
  • Malicious packages: reports from the OpenSSF Malicious Packages project (through OSV) are flagged and listed first, with "remove it" instead of an upgrade command.
  • Install-time code: lists the npm packages whose lockfile says an install script runs code on install, and names the lockfiles that cannot say (it is not a vulnerability, and never fails a gate).
  • Ranked, not just listed: malicious first, then exploited in the wild, then likely to be exploited, then CVSS.
  • Is it actually used? Usage evidence per finding from your own source: for Rust and Go down to the affected function. Findings your code does not import sink in the ranking (never hidden).
  • Fix, verify, record: plan_fix gives the exact upgrade commands, verify_fix re-scans and tells you which advisories are gone, record_fix logs what was changed and why, like a commit message. An id is resolved only when an earlier scan of the same path reported it; an id no earlier scan reported is unknown, and that proves nothing.
  • The runtime underneath too: scan-runtime checks PHP, nginx, Node.js, databases and similar products that no lockfile lists, and says whether their release line is end of life or behind its newest patch, the day a fix ships. With --nvd it also lists the CVEs NVD records for that exact version, which is how a flaw in PHP itself shows up.
  • Your CI too: the actions a workflow uses are checked against the same advisory data (a full release tag is matched; a commit SHA, a floating tag or a branch is listed as not checked, never dropped), and scan-code flags dangerous workflow patterns: text an outsider controls pasted into a run: script, a pull_request_target workflow that checks out the pull request, an unpinned action and a token with every permission, each with the guidance it rests on (docs/LANGUAGES.md).
  • Your own code too: scan-code flags suspected hard-coded secrets, injection patterns, disabled TLS verification and unsafe deserialization, each with a CWE, and can run gitleaks or semgrep. For code that calls an AI model it also looks for provider keys (Anthropic, Hugging Face, Google), a model's answer passed to eval, a shell, SQL or HTML, and a prompt built from a request's input, with the OWASP LLM Top 10 entry behind each rule.
  • The files that steer your assistant: scan-agent-config reads rule files (CLAUDE.md, AGENTS.md, .cursorrules, ...), MCP server settings, hooks, auto-run tasks and skills (a folder with a SKILL.md: its text, scripts and dependencies) for invisible characters, injected instructions, commands that download and run code, unpinned packages, compiled files and secrets, and checks the packages an MCP server or a skill starts or lists against the same advisory and malicious-package data. Every rule names its CWE and the OWASP entry behind it (docs/AGENT-CONFIG.md).
  • A report people can read: a read-only dashboard with charts, the vulnerability list and the history of fixes with references, or the same report as one HTML file.
  • Honest: every result says what was scanned, what was not, and how old the data is. A clean result means no known advisory matched, not secure.

See it in action

The opencraysec report: counts of open, critical, malicious, exploited and used-by-your-code findings, packages that run code at install, assistant configuration and code issues, runtime products to review, severity over time, the riskiest packages and whether the code uses them

What was changed, and why: each fix with the assistant's reason, the measured lockfile change, the commands and the advisories with their references, and the vulnerabilities a re-scan confirmed gone

The AI assistant configuration panel (rule files, MCP server settings, hooks, tasks and skills, each finding with its CWE and what to do) and the suspected code issues for code that calls an AI model

The images come from a scratch project (/tmp/shop-api) written for the demonstration, with real advisory data: the findings and numbers are what opencraysec reported. One package in it is a real entry from the public malicious-package data. The fix history was recorded by a script standing in for an assistant: it edited the lockfile and then ran record-fix and verify-fix, which is why the client is shown as cli. No customer data or personal paths are shown.

Install in 30 seconds

curl -fsSL https://raw.githubusercontent.com/amgio38/opencraysec/main/scripts/install.sh | sh
opencraysec update --for .          # download advisories for the ecosystems in this project
opencraysec scan .                  # and check it
claude mcp add opencraysec -- opencraysec mcp
Platform How
Linux x86-64, aarch64 The command above downloads a prebuilt static binary and checks its SHA-256. No Rust needed.
macOS, Apple Silicon and Intel The same command downloads a prebuilt native binary and checks its SHA-256. No Rust or Xcode needed.
Other Linux CPUs The same command builds from source (Rust 1.95+ and a C compiler).
Windows Run it inside WSL2 (below). The installer refuses native Windows shells.

A prebuilt binary for every supported platform is attached to each release, with a .sha256 file beside it; docs/INSTALL.md shows how to verify a download by hand.

The first line installs opencraysec into ~/.local/bin. Other clients (Cursor, opencode, Codex), system-wide installs and uninstalling are in docs/INSTALL.md and docs/CLIENTS.md.

To teach the assistant the workflow, install the bundled Agent Skill: copy it once for every project, or into this project only.

cp -r skills/opencraysec ~/.claude/skills/   # every project
cp -r skills/opencraysec .claude/skills/     # this project only

Windows (WSL2)

From PowerShell, once (this installs Ubuntu and asks for a reboot):

wsl --install -d Ubuntu

Then open the Ubuntu app and install exactly as on Linux:

curl -fsSL https://raw.githubusercontent.com/amgio38/opencraysec/main/scripts/install.sh | sh

Run your coding agent inside WSL as well, and keep your projects on the Linux side (~/projects, not /mnt/c/...): the lockfiles are then read at native speed, and the paths the tools report match what the agent sees.

Use it

opencraysec scan .                       # human-readable report, most urgent first
opencraysec scan . --format sarif -o out.sarif      # also: json, cyclonedx (SBOM)
opencraysec scan bom.json                # a CycloneDX or SPDX SBOM: an image's inventory, another machine's list
opencraysec scan . --fail-on high        # exit 1 in CI if anything is high or worse, 3 if nothing was checked
opencraysec scan . --enrich-nvd          # score findings the advisories left unscored
opencraysec explain GHSA-xxxx-xxxx-xxxx  # what it is, how bad, references
opencraysec plan-fix .                   # the upgrade commands; nothing is modified
opencraysec verify-fix . --id GHSA-xxxx-xxxx-xxxx   # re-scan; "resolved" needs an earlier scan of this path
opencraysec record-fix . --id GHSA-xxxx-xxxx-xxxx --summary "Upgrade lodash" --reason "Prototype pollution"
opencraysec scan-code .                  # suspected weaknesses in your own source
opencraysec scan-agent-config .          # rule files, MCP servers, hooks and skills of your AI assistant
opencraysec scan-runtime                # PHP, nginx, Node.js ... installed here: end of life? behind?
opencraysec scan-runtime php@8.2.30     # or name the versions, for a container or another machine
opencraysec scan-runtime --nvd          # also the CVEs NVD lists for those versions (network)
opencraysec dashboard                    # the report on http://localhost:1787
opencraysec report -o report.html        # the same report as one file
opencraysec status                       # what data is stored, and how old

scan works without downloading anything: for an ecosystem with no local data it asks the OSV API about the exact package names and versions it found (never your code) and says so in the report. --offline forbids that. Run update once for fully offline scans.

scan --fail-on exits 1 when it found something at or above the threshold, and 3 when a pass would prove nothing: no lockfile, an unreadable lockfile, an ecosystem with no advisory data, or only requirement lines without an exact == pin. Requirement lines listed next to dependencies that were checked do not fail the gate; the report then says it is incomplete. verify-fix exits 1 when a finding remains, an id is unknown, or the result could not be trusted. The full table is in docs/CONFIGURATION.md.

MCP server

{
  "mcpServers": {
    "opencraysec": { "command": "opencraysec", "args": ["mcp", "--workspace", "/path/to/project"] }
  }
}
Tool Purpose
scan_dependencies Check lockfiles against current advisories, ranked, with usage evidence.
scan_code Suspected weaknesses in the project's own source.
scan_agent_config Rule files, MCP server settings, hooks, auto-run tasks and skills that steer an AI assistant.
scan_runtime Installed interpreters, servers and databases against release and end-of-life data.
explain_advisory One advisory: what it is, CWE, exploitation signals, references.
plan_fix The minimal upgrades and the commands to run. Modifies nothing.
verify_fix Re-scan and prove advisories are gone (and whether that proof can be trusted).
record_fix Optional, like a commit message: what the assistant changed and why.
update_db Download or refresh the advisory data.
db_status What data is stored, and how old it is.

Paths are confined to --workspace. The server never edits your project: it tells the assistant what to run, and record_fix writes only to the activity log. Full arguments and results are in docs/TOOLS.md.

The dashboard

opencraysec dashboard serves a read-only report from the activity log: counts, severity over time, the riskiest packages, usage evidence, activity, the vulnerable dependencies, the packages that run code when installed, the runtime products (scan-runtime) with the CVEs NVD lists for them, the assistant configuration findings, suspected code issues, and the history of what was changed and why.

It listens on every network interface by default (0.0.0.0:1787) and the report lists your vulnerabilities. Use --host 127.0.0.1 to keep it on this machine, or --token SECRET to require one. Details, including what the log holds, are in docs/DASHBOARD.md.

Limits

  • Dependency matching uses lockfile versions. Usage evidence is source text, not a call graph: it can miss dynamic use and cannot see use by other dependencies, so not_found means "your code does not import it", not "safe". For Go, run govulncheck for a call-graph proof.
  • scan-agent-config is pattern matching too: it cannot see what an MCP server or a skill does once it runs, only what it is made of and the package it is started from. See docs/AGENT-CONFIG.md for each rule's false positives and misses.
  • scan-code is pattern matching with a small rule pack. Every hit is suspected; confirm it before reporting.
  • A requirements.txt entry without an exact == pin cannot be matched. CVSS v4 vectors are not computed locally; --enrich-nvd fetches NVD's score.
  • The activity log is not rotated.

Privacy

Scanning is local. The only network traffic is downloading public datasets (OSV, CISA, FIRST, MITRE, endoflife.date, php.net), querying api.osv.dev with package names and versions when an ecosystem has no local data and you did not pass --offline, and NVD lookups when you pass --enrich-nvd (CVE ids) or scan-runtime --nvd (a product's CPE name and version). The activity log holds package names, versions, advisory and CVE ids and file paths, never source code or secrets, and stays on your machine. See docs/CONFIGURATION.md.

Documentation

docs/INSTALL.md Installing, building, uninstalling, verifying a download
docs/CLIENTS.md Claude Code, Cursor, opencode, Codex and any other MCP client
docs/TOOLS.md Every MCP tool, its arguments and results
docs/LANGUAGES.md Supported lockfiles, usage evidence, fix commands, code rules
docs/AGENT-CONFIG.md scan-agent-config: what it reads, every rule with its CWE and OWASP entry, and its limits
docs/DASHBOARD.md The report, the log, and who can see them
docs/DATA-SOURCES.md Where every fact comes from, and how findings are ranked
docs/CONFIGURATION.md Data directory, environment variables, limits, exit codes
docs/TROUBLESHOOTING.md Common problems
docs/ARCHITECTURE.md How the crates fit together and why
docs/RELEASING.md How a release is cut

Repository layout

Crate Role
opencraysec-core Package model, per-ecosystem version ordering, CVSS v3, OSV matching.
opencraysec-lockfile Lockfile and SBOM discovery and parsers.
opencraysec-runtime Runtime products (PHP, nginx, ...): version detection, release and end-of-life verdicts, NVD answers. No network.
opencraysec-db Local store, dataset updates, the OSV and NVD clients, the release-data feeds.
opencraysec-engine Scan, usage evidence, code rules, explain, plan and verify fix, SARIF and CycloneDX.
opencraysec-log The activity log (JSONL), dependency snapshots and report summaries.
opencraysec-web The read-only dashboard server and the HTML export.
opencraysec-mcp The MCP stdio server.
opencraysec-cli The opencraysec binary.

Build and test with make ci (format, clippy, tests, layering, licence, installer and docs checks) and make preflight before every push (the same list CI runs, plus the 90% coverage gate). See CONTRIBUTING.md for the conventions.

License

MIT. See LICENSE and SECURITY.md.

Dependencies are under their own licenses: see THIRD-PARTY-LICENSES.md for the crate-by-crate inventory and NOTICE for the required attributions. The licence texts those require are in licenses/. deny.toml is the policy and make deny is the gate; CI runs it on every push. The vulnerability data opencraysec downloads belongs to its publishers; see docs/DATA-SOURCES.md.

An installed copy carries all of it: install.sh and make install put this set under $PREFIX/share/doc/opencraysec, the release archive carries it so there is something to install, and both uninstall paths remove it.

The crates in this workspace are marked publish = false in their Cargo.toml. That is deliberate: they are released as the opencraysec binary, not as a library for others to depend on. It also means cargo install opencraysec from crates.io does not work and is not intended; use the installer above, or build from a checkout with cargo build --release -p opencraysec-cli.

About

Dependency vulnerability checker for AI assistants: a CLI, an MCP server and a local dashboard. Scans Rust, JS/TS, PHP, Go and Python lockfiles against OSV, ranked by CISA KEV and EPSS.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages