Skip to main content
Glama
OSV Dependency Vulnerability Check MCP Server

OSV Dependency Vulnerability Check MCP Server

README.md
# 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

A4.9/5.0

Scored across 3 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues