OSV Dependency Vulnerability Check MCP Server
# Dependency Vulnerability Check for Agents
**Checks npm, PyPI, Go, Maven and other dependencies (or a lockfile) against OSV.dev, for $0.50 per 1,000 packages plus $1.50 per 1,000 vulnerability rows.** Error and warning rows are free. Example: a 300-package lockfile with 12 vulnerability rows costs 300 × $0.0005 + 12 × $0.0015 = **$0.17**, plus Apify's $0.00005 Actor-start fee.
**Fairquery** Apify Actor that checks open-source dependencies against the free **[OSV.dev](https://osv.dev)** vulnerability database and returns agent-ready rows: one per package (vulnerable or not) and one per vulnerability (CVE, CVSS, severity, affected/fixed versions, references).
## When to use this Actor (LLM / tool selection)
Use it when an agent needs to:
- Answer "is `lodash@4.17.20` / `django==3.2.0` vulnerable, and to what version should I upgrade?"
- Audit a pasted **package.json, package-lock.json, requirements.txt, or go.mod**
- Filter to **HIGH/CRITICAL** issues only for a CI gate or PR comment
- Map OSV / GHSA / PYSEC / GO IDs to **CVE IDs** and CVSS scores
Supported ecosystems: everything OSV supports (npm, PyPI, Go, Maven, crates.io, RubyGems, NuGet, Packagist, Pub, Hex, …). Aliases like `pip`, `golang`, `cargo`, `composer` are accepted.
Do **not** use it for: reachability analysis, license checks, container/OS image scanning, or unpinned version ranges (it checks exact versions).
## Data sources
| Resource | URL |
| --- | --- |
| Batch query | `POST https://api.osv.dev/v1/querybatch` |
| Vulnerability detail | `GET https://api.osv.dev/v1/vulns/{id}` |
Free, no API key. Retries on 429/5xx with exponential backoff; detail fetches are cached and run 8 in parallel.
## Input
| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `packages` | `{ecosystem,name,version}[]` | `[]` | Exact package versions to check |
| `manifestText` | `string` | — | Raw package.json / package-lock.json (v1–v3) / requirements.txt / go.mod |
| `manifestType` | enum | `auto` | Force the manifest format |
| `minSeverity` | `ALL`\|`LOW`\|`MEDIUM`\|`HIGH`\|`CRITICAL` | `ALL` | Minimum severity of emitted vulnerability rows |
| `includeUnknownSeverity` | `bool` | `true` | Keep vulns with no severity data when filtering |
| `includeDevDependencies` | `bool` | `true` | Include dev deps from npm manifests |
| `dedupeAliases` | `bool` | `true` | Collapse GHSA/PYSEC/GO records describing the same issue into one row (GHSA preferred) |
| `maxPackages` | `int` | `1000` | Safety cap on unique packages |
Manifest notes: `package.json` ranges are approximated to their lower bound (`^4.17.20` → `4.17.20`) and a `RANGE_APPROXIMATED` warning row is emitted — prefer the lockfile. `requirements.txt` lines without `==` pins are skipped with a `VERSION_NOT_PINNED` warning (use `pip freeze`).
### Example input
```json
{
"packages": [
{ "ecosystem": "npm", "name": "lodash", "version": "4.17.20" },
{ "ecosystem": "PyPI", "name": "django", "version": "3.2.0" }
],
"minSeverity": "HIGH"
}
```
## Output
Every row has `schema_version` (`1.0.0`), `type` (`package` | `vulnerability` | `error`), `source_url` (OSV API URL), and `checked_at`.
### Package row
```json
{
"type": "package", "ecosystem": "npm", "name": "lodash", "version": "4.17.20",
"purl": "pkg:npm/lodash@4.17.20", "vulnerable": true, "vuln_count": 3, "vuln_count_total": 5,
"vuln_ids": ["GHSA-r5fr-rjxr-66jc", "GHSA-35jh-r3h4-6jhm", "GHSA-29mw-wpgm-hmr9"],
"max_severity": "HIGH", "max_cvss_score": 8.1,
"fixed_versions": ["4.18.0", "4.17.21"], "recommended_version": "4.18.0"
}
```
`vuln_count` is after the severity filter and alias de-duplication; `vuln_count_total` is the raw OSV count. `recommended_version` is the smallest version that fixes every emitted vuln (best-effort, null if some vuln has no fix).
### Vulnerability row
Fields: `id`, `package_name`, `package_version`, `aliases`, `cve_ids`, `summary`, `details` (≤2000 chars), `severity`, `cvss_score` (computed CVSS v3 base score), `cvss_vector`, `cvss_version`, `severity_source` (`cvss` | `database_specific` | `alias` | `none`), `severity_alias_id`, `cwe_ids`, `affected_ranges[]` (`introduced`/`fixed`/`last_affected`), `affected_versions_sample`, `fixed_versions`, `published`, `modified`, `references[]`, `osv_url`.
Severity: CVSS v3 base score → NONE/LOW/MEDIUM/HIGH/CRITICAL; otherwise the advisory's label (GHSA `MODERATE` → `MEDIUM`); otherwise borrowed from a GHSA alias; otherwise `UNKNOWN` (common for some Go advisories).
### Error / warning rows (machine-readable)
```json
{ "type": "error", "code": "OSV_VULN_FETCH_FAILED", "message": "OSV /vulns/GHSA-… -> HTTP 503", "retryable": true, "vuln_id": "GHSA-…" }
```
Codes: `INPUT_EMPTY`, `INVALID_PACKAGE`, `MANIFEST_UNDETECTED`, `MANIFEST_PARSE_FAILED`, `MAX_PACKAGES_EXCEEDED`, `OSV_QUERYBATCH_FAILED`, `OSV_VULN_FETCH_FAILED`; warnings (with `context.severity = "warning"`): `RANGE_APPROXIMATED`, `VERSION_NOT_PINNABLE`, `VERSION_NOT_PINNED`.
### Run summary
Key-value store record **`RUN_SUMMARY`**: packages checked/vulnerable, vulnerabilities emitted/filtered/deduplicated, severity counts, OSV request count, echoed input.
## Pricing
| Event | Price | When |
| --- | --- | --- |
| `package-checked` | $0.0005 | Each package row (vulnerable or clean) |
| `vulnerability-found` | $0.0015 | Each emitted vulnerability row (after the severity filter and alias de-duplication) |
| `apify-actor-start` | $0.00005 | Once per run, per GB of memory (Apify default event) |
Error and warning rows are **never** charged.
**Worked example:** a 300-package lockfile with 12 vulnerability rows: 300 × $0.0005 + 12 × $0.0015 = $0.15 + $0.018 = **$0.17**, plus $0.00005. Set `minSeverity: "HIGH"` to emit (and pay for) only high and critical rows.
To cap spend, set a maximum cost per run in the run options; the Actor stops cleanly at the limit. `maxPackages` caps unique packages per run. Prices are from the Store pricing tab (October 2026).
## Memory / runtime
Default **128 MB**. HTTP only (no browser). A 2-package run finishes in about 5–10 s; time grows with the number of advisories to fetch.
## MCP / Apify tools
Call from agents via [Apify MCP](https://mcp.apify.com):
1. Connect an MCP client to `https://mcp.apify.com` with your Apify token.
2. Run actor `fairquery/osv-dependency-vulnerability-check`.
3. Read the default dataset (filter `type == "vulnerability"`) and the `RUN_SUMMARY` record.
```json
{
"actor": "fairquery/osv-dependency-vulnerability-check",
"input": { "manifestText": "django==3.2.0\nrequests==2.25.0", "minSeverity": "HIGH" }
}
```
## Local stdio MCP server
This repo also ships a **stdio MCP server** (TypeScript, `@modelcontextprotocol/sdk`) under [`mcp/`](./mcp). It exposes three tools: `check_dependency_vulnerabilities` (runs this Actor through the Apify API), the free `get_vulnerability_details` (direct OSV.dev lookup by advisory ID) and the free `list_package_vulnerabilities` (all OSV.dev advisories recorded for one package across all versions, newest first, paged; it gives no per-version verdict). The two free tools call api.osv.dev directly and need no token. `initialize` and `tools/list` work **without** a token; `check_dependency_vulnerabilities` requires `APIFY_TOKEN` (calls are billed per the pricing above).
```bash
cd mcp && npm install && npm run build
node scripts/smoke-test.mjs # initialize + tools/list, no token
APIFY_TOKEN=... node scripts/smoke-test.mjs --call # real tool call
```
Claude Desktop / Cursor config:
```json
{
"mcpServers": {
"fairquery-osv": {
"command": "node",
"args": ["/path/to/osv-dependency-vulnerability-check/mcp/dist/index.js"],
"env": { "APIFY_TOKEN": "<your Apify token>" }
}
}
}
```
Docker: `docker build -t fairquery-osv-mcp .` (the repo-root `Dockerfile` builds this MCP server and is what Glama uses; the Apify Actor image is built from `.actor/Dockerfile`). `glama.json` lists `fairquery` as maintainer.
## Troubleshooting
| Symptom | Cause and fix |
| --- | --- |
| Run fails at once with `INPUT_EMPTY` | Neither `packages` nor `manifestText` was given. The sample packages in the Console form are prefill only and are not sent with API calls. |
| `RANGE_APPROXIMATED` warnings | `package.json` ranges were reduced to their lower bound. Paste `package-lock.json` instead for exact versions. |
| `VERSION_NOT_PINNED` warnings | requirements.txt lines without `==` are skipped. Use `pip freeze` output. |
| `MANIFEST_UNDETECTED` / `MANIFEST_PARSE_FAILED` | Set `manifestType` explicitly, and paste the raw file content (not a path or URL). |
| `OSV_QUERYBATCH_FAILED` / `OSV_VULN_FETCH_FAILED` | OSV.dev was unavailable after retries (`retryable: true`). These rows are free; re-run later. |
| Severity `UNKNOWN` | Some advisories (often Go) publish no CVSS or label. Keep `includeUnknownSeverity` on so they are not filtered out. |
## FAQ
**Which ecosystems are supported?**
Everything OSV.dev supports: npm, PyPI, Go, Maven, crates.io, RubyGems, NuGet, Packagist, Pub, Hex and more.
**Does no result mean my package is safe?**
No. It means OSV.dev has no matching advisory for that exact version. It is not reachability analysis or a full security review.
**How much does it cost?**
$0.0005 per package row plus $0.0015 per vulnerability row, and a $0.00005 start fee. Error and warning rows are free.
**How do I limit spend?**
Use `minSeverity` to skip low-severity rows, set a maximum cost per run in the run options, and/or lower `maxPackages`.
**Can an AI agent call it?**
Yes, through [Apify MCP](https://mcp.apify.com) with Actor `fairquery/osv-dependency-vulnerability-check`, or through the Fairquery MCP server (`npx -y @fairquery/agent-trust-mcp`). Its free `osv_query_packages` and `osv_get_vulnerability` tools query OSV.dev directly.
## Fairquery family
Other Fairquery tools on the Apify Store. Each one returns structured rows with machine-readable error codes, and error rows are never charged:
- [Email Validator for Agents (MX, Disposable, Typo)](https://apify.com/fairquery/email-validator-mx-disposable): syntax, MX, disposable, role and typo checks without sending mail; $0.79 per 1,000 emails
- [Website Contact & Company Enricher](https://apify.com/fairquery/website-contact-company-enricher): domain in, public business emails, phones, socials and company details out; $3 per 1,000 domains
- [Website Tech, SEO & llms.txt Check for Agents](https://apify.com/fairquery/website-tech-seo-ai-readiness): tech stack, SEO score, AI-crawler rules and llms.txt per site; $1.50 per 1,000 sites
- [Sanctions & Watchlist Screener (OFAC, EU, UK, UN)](https://apify.com/fairquery/sanctions-watchlist-screener): fuzzy name screening against official sanctions lists; $3 per 1,000 names + $0.007 per run
- [LLM Data Guard: PII & Secret Redactor](https://apify.com/fairquery/llm-data-guard-pii-secrets): redact PII and secrets before text reaches an LLM; $1.50 per 1,000 documents + $0.20 per 1,000 findings
- [EDGAR Company Facts & Filings for Agents](https://apify.com/fairquery/edgar-company-facts-filings): SEC filings and XBRL facts by ticker, CIK or name; from $1.50 per 1,000 companies
- [Company Jobs Feed: Greenhouse, Lever & Ashby](https://apify.com/fairquery/company-jobs-feed): live jobs from employers' own ATS boards with age and repost signals; $0.99 per 1,000 jobs + $0.0005 per board
- [Competitor Change Tracker: Pricing, Terms, Careers & Changelog](https://apify.com/fairquery/competitor-change-tracker): watch competitors' public pricing, terms, careers and changelog pages for real changes with plain-English summaries and webhook alerts; $0.00049 per page checked + $0.0049 per change
- [AI Exposure Scanner: Public Secrets, Files & AI-Crawler Policy](https://apify.com/fairquery/ai-exposure-scanner): passive, scored scan of your own domains and public GitHub repos for leaked secrets (masked), exposed files, AI-crawler policy, security headers and SPF/DMARC; $0.039 per domain + $0.0039 per repo + $0.0019 per finding
- **MCP server** [`@fairquery/agent-trust-mcp`](https://www.npmjs.com/package/@fairquery/agent-trust-mcp): one MCP server for Claude Desktop, Cursor and VS Code (`npx -y @fairquery/agent-trust-mcp`). It has 8 free tools that need no token, plus paid tools that call the PII, email, sanctions and OSV Actors with your own Apify token.
All Fairquery Actors: https://apify.com/fairquery
## Kits & templates
Optional guides from Fairquery for wiring this Actor into agents and automations (the Actor works fine without them):
- [AI Agent Data Toolkit Quick-Start](https://fairquery.gumroad.com/l/qayngz) (PDF): MCP setup for Claude Desktop and Cursor, API calls, recipes, cost estimates.
- [n8n + Zapier Workflow Template Pack](https://fairquery.gumroad.com/l/koffbf): 10 importable n8n workflows for the four Fairquery Actors, plus Zapier setup guides.
- [Agent Prompt Pack for Research & Lead Ops](https://fairquery.gumroad.com/l/djdilu): 69 prompts for company research, lead cleaning, SEO and security reviews.
- [Agent Starter Kit: 10 copy-paste MCP + n8n recipes](https://fairquery.gumroad.com/l/idvrck) ($5): 10 copy-paste MCP + n8n recipes, with ready-made Claude/Cursor configs and 3 starter workflows.
## Disclaimer
Data comes from OSV.dev (aggregating GitHub Advisory Database, PyPA, Go Vulnerability DB and others) under their respective licenses. No warranty of completeness; absence of results does not prove a package is safe.
## Links
- Apify Store: https://apify.com/fairquery/osv-dependency-vulnerability-check
- GitHub: https://github.com/fairquery/osv-dependency-vulnerability-check
- Contact: fairquery@proton.me
- License: MIT
## Development
Local development, tests and deployment notes are in [DEVELOPMENT.md](./DEVELOPMENT.md). The Apify Store README is [`.actor/README.md`](./.actor/README.md).
TDQS
Scored across 3 tools
Each tool has a clearly distinct input and purpose: check_dependency_vulnerabilities takes pinned versions/manifests, get_vulnerability_details takes advisory IDs, and list_package_vulnerabilities takes a package name with no version. The descriptions explicitly cross-reference each other with WHEN TO USE / WHEN NOT TO USE, leaving no meaningful overlap.
All three names follow a consistent snake_case verb_noun pattern: check_, get_, and list_ prefixes with clear resource nouns. The verbs vary appropriately by action rather than chaotically, and there is no mixed casing or style.
Three tools map cleanly to the three core OSV.dev query modes: version/manifest audit, advisory-by-ID lookup, and package advisory listing. The server is a focused wrapper, so each tool earns its place without redundancy or excessive surface area.
The surface covers the main workflows: checking pinned versions or manifests, retrieving full advisory records, and listing all advisories for a package. Minor gaps exist, such as querying by commit hash or browsing advisories across an entire ecosystem, but these are unlikely to block typical auditing tasks.