OSV Vulnerability Scanner: npm, PyPI, Go & Maven avatar

OSV Vulnerability Scanner: npm, PyPI, Go & Maven

Pricing

from $1.00 / 1,000 vulnerability founds

Go to Apify Store
OSV Vulnerability Scanner: npm, PyPI, Go & Maven

OSV Vulnerability Scanner: npm, PyPI, Go & Maven

Check npm, PyPI, Go, Maven, crates.io and other packages, or a package.json, package-lock, requirements.txt or go.mod, against the free OSV.dev database. One row per package and per vulnerability with CVE, CVSS, severity and fixed versions. $0.50 per 1,000 packages + $1.50 per 1,000 vulns.

Pricing

from $1.00 / 1,000 vulnerability founds

Rating

0.0

(0)

Developer

Fairquery

Fairquery

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Share

OSV Dependency Vulnerability Scanner (npm, PyPI, Go, Maven)

What does it do?

This dependency vulnerability scanner checks open-source packages against the free OSV.dev database, which aggregates the GitHub Advisory Database, PyPA, the Go vulnerability database and others. Give it a list of packages, paste a package.json, package-lock.json, requirements.txt or go.mod, or paste a CycloneDX JSON SBOM. It returns one row per package (vulnerable or clean) and one row per vulnerability with CVE and GHSA IDs, CVSS, severity, affected and fixed versions and references.

Each package row is also an install verdict: malicious (OSV MAL- advisories and the same signal on aliases), the registry-declared license, whether that version is deprecated, firstPublished / lastPublished, and public maintainers names. Those health fields are included in the package-checked event. There is no separate SBOM or license charge.

Use it in CI, in a scheduled audit across many repos, or from an AI agent that needs an npm audit-style answer for any ecosystem.

How much does it cost?

Pay per event, no subscription. Prices per 1,000 rows:

EventFree planStarter (Bronze)Scale (Silver)Business (Gold)
vulnerability-found (primary)$1.50$1.35$1.20$1.00
package-checked$0.50$0.45$0.40$0.35

The Apify Free plan includes $5 of usage every month, no credit card needed, and this Actor's event charges come out of that $5. That covers about 10,000 clean package checks a month ($5 ÷ ($0.50/1,000)), or about 29 lockfiles like the example below, plus a start fee of $0.05 per 1,000 runs. Error and warning rows are never charged.

Example (Free-plan prices): A 300-package lockfile with 12 vulnerability rows: 300 × ($0.50/1,000) + 12 × ($1.50/1,000) = about $0.17 ($168.00 per 1,000 such runs). Set minSeverity to HIGH to emit (and pay for) only high and critical vulnerability rows; every package row is still charged, and unknown-severity rows stay in unless you turn off includeUnknownSeverity.

Paid Apify plans get the Store discount automatically: Starter = Bronze, Scale = Silver, Business = Gold. Set a maximum cost per run in the run options and the Actor stops cleanly at that limit.

How to use it

  1. Add Packages ({"ecosystem": "npm", "name": "lodash", "version": "4.17.20"}), paste a manifest into Manifest text, or paste a CycloneDX JSON document into CycloneDX SBOM. The manifest type is detected automatically (cyclonedx is one of the types).
  2. Choose a minimum severity and whether to include dev dependencies.
  3. Click Start, or call it from CI with the Apify API. Export rows as JSON or CSV.

Example input

{
"packages": [
{
"ecosystem": "npm",
"name": "lodash",
"version": "4.17.20"
}
],
"minSeverity": "ALL"
}

Example output (2 rows from a real run on 2026-10-19, shortened to the main fields):

[
{
"type": "package",
"ecosystem": "npm",
"name": "lodash",
"version": "4.17.20",
"vulnerable": true,
"vuln_count": 5,
"max_severity": "HIGH",
"max_cvss_score": 8.1,
"fixed_versions": [
"4.18.0",
"4.17.21",
"4.17.23"
],
"recommended_version": "4.18.0"
},
{
"type": "vulnerability",
"id": "GHSA-r5fr-rjxr-66jc",
"package_name": "lodash",
"package_version": "4.17.20",
"cve_ids": [
"CVE-2026-4800"
],
"summary": "lodash vulnerable to Code Injection via `_.template` imports key names",
"severity": "HIGH",
"cvss_score": 8.1,
"cwe_ids": [
"CWE-94"
],
"fixed_versions": [
"4.18.0"
],
"source_url": "https://api.osv.dev/v1/vulns/GHSA-r5fr-rjxr-66jc"
}
]

FAQ

How do I check npm or PyPI packages for vulnerabilities without installing them?

Send the package names and versions, or paste the lockfile text. The Actor queries OSV.dev directly, so nothing is installed or executed.

Is this an npm audit alternative for other languages?

It answers the same question as npm audit (known advisories for the versions you use) across npm, PyPI, Go, Maven, crates.io and other OSV ecosystems, in one schema. It doesn't fix or upgrade packages for you.

How many packages can I scan for free?

About 10,000 package checks per month on Apify's Free plan, which includes $5 of usage; each vulnerability row found adds $1.50 per 1,000.

Does a clean result mean my dependencies are safe?

No. It means OSV.dev has no matching advisory for those versions at scan time.

Limits

Data comes from OSV.dev and the public package registries under their licenses, with no warranty of completeness. It doesn't scan your code or containers. license is the registry-declared license string (or the CycloneDX component license when the registry has none), not a source-tree license compliance scan.

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, go.mod, or CycloneDX JSON SBOM
  • Decide whether to install a pinned version: known advisories, a malicious-package flag, declared license, deprecation, publish dates and maintainer names
  • 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, a legal license review of source files, container/OS image scanning, or unpinned version ranges (it checks exact versions).

Data sources

ResourceURL
Batch queryPOST https://api.osv.dev/v1/querybatch
Vulnerability detailGET https://api.osv.dev/v1/vulns/{id}
npm metadataGET https://registry.npmjs.org/{package}/{version} and the packument time map
PyPI metadataGET https://pypi.org/pypi/{package}/json and /{version}/json
Go metadataGET https://proxy.golang.org/{module}/@v/list and .info
Maven metadataMaven Central search timestamps and that version's POM
Other registriescrates.io, RubyGems, NuGet registration, repo.packagist.org, pub.dev, hex.pm

Free, no API key. OSV retries on 429/5xx; detail fetches are cached and run 8 in parallel. Registry lookups run 4 at a time and never fail the vulnerability check: a miss leaves license null (unless the SBOM component declared one), deprecated false, dates null and maintainers empty. Maintainer emails are dropped. Go has no license or maintainer fields in the module proxy (license null, maintainers empty, deprecated false). Maven deprecated stays false; its license is read from that version's POM and is null when the license lives only on a parent POM. For Go modules, firstPublished / lastPublished are the proxy timestamps of the oldest and newest versions in the module list.

Input

FieldTypeDefaultDescription
packages{ecosystem,name,version}[][]Exact package versions to check
manifestTextstring—Raw package.json / package-lock.json (v1–v3) / requirements.txt / go.mod / CycloneDX JSON
manifestTypeenumautoForce the manifest format, including cyclonedx
sbomTextstring""CycloneDX JSON SBOM. Same component rules as a CycloneDX manifestText. Empty is ignored
minSeverityALL|LOW|MEDIUM|HIGH|CRITICALALLMinimum severity of emitted vulnerability rows
includeUnknownSeveritybooltrueKeep vulns with no severity data when filtering
includeDevDependenciesbooltrueInclude npm dev deps and CycloneDX development/excluded components
dedupeAliasesbooltrueCollapse GHSA/PYSEC/GO records describing the same issue into one row (GHSA preferred)
maxPackagesint1000Safety 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).

CycloneDX notes: paste JSON (bomFormat: "CycloneDX"), not XML, SPDX, a file path or a URL. Components are read from components (including nested components) and metadata.component. A component is checked when its purl (or bom-ref, or a Syft/Trivy type property plus name and version) maps to npm, PyPI, Go, Maven, crates.io, RubyGems, NuGet, Packagist, Pub or Hex and it has a version. pkg:maven/group/artifact@version becomes Maven group:artifact. Other purl types (deb, apk, oci, …) are counted in one free SBOM_COMPONENTS_SKIPPED warning. Set includeDevDependencies to false to skip components with scope: "excluded" or property cdx:npm:package:development=true. Each resolved component is one package-checked row (origin: "sbom").

{
"sbomText": "{\"bomFormat\":\"CycloneDX\",\"specVersion\":\"1.5\",\"components\":[{\"type\":\"library\",\"name\":\"lodash\",\"version\":\"4.17.20\",\"purl\":\"pkg:npm/lodash@4.17.20\"}]}",
"minSeverity": "HIGH"
}

Example input

{
"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.1.0), type (package | vulnerability | error), source_url (OSV API URL), and checked_at.

Package row

{
"type": "package", "ecosystem": "npm", "name": "lodash", "version": "4.17.20",
"purl": "pkg:npm/lodash@4.17.20", "origin": "input",
"vulnerable": true, "malicious": false, "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",
"license": "MIT", "deprecated": false,
"firstPublished": "2012-04-23T16:37:11.912Z",
"lastPublished": "2026-04-01T21:01:20.458Z",
"maintainers": ["bnjmnt4n", "jdalton", "mathias"]
}

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 counts in the block above are shortened. The license, dates and maintainer names are the public npm registry values for lodash: time.created, the newest version timestamp in the packument time map (4.18.1), and the 4.17.20 version document's maintainer names with emails removed.

malicious is true when any advisory id for that package starts with MAL-, or a fetched non-withdrawn advisory has a MAL- alias, database_specific.malicious, a non-empty malicious-packages-origins list, or CWE-506. Withdrawn advisories do not count. The flag stays set when minSeverity filters that advisory out of the vulnerability rows. license prefers the registry and falls back to the CycloneDX component's license. deprecated is false when the registry does not mark the version — it is not a promise that the package is maintained. Go and Maven do not expose a deprecation flag in the sources this Actor reads. A registry miss leaves dates null, license null unless the SBOM had one, deprecated false and maintainers empty, and the OSV rows are still returned.

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)

{ "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, SBOM_PARSE_FAILED, SBOM_UNSUPPORTED, MAX_PACKAGES_EXCEEDED, OSV_QUERYBATCH_FAILED, OSV_VULN_FETCH_FAILED; warnings (with context.severity = "warning"): RANGE_APPROXIMATED, VERSION_NOT_PINNABLE, VERSION_NOT_PINNED, SBOM_COMPONENTS_SKIPPED, SBOM_NO_PACKAGES.

Run summary

Key-value store record RUN_SUMMARY: packages checked/vulnerable/malicious, packages parsed from the manifest and from sbomText, vulnerabilities emitted/filtered/deduplicated, severity counts, OSV and registry request counts, registry misses, echoed input (manifest and SBOM bodies replaced with their lengths).

Pricing

EventPriceWhen
package-checked$0.50 per 1,000Each package row (vulnerable or clean), including each CycloneDX component. License and health fields are part of this row
vulnerability-found$1.50 per 1,000Each emitted vulnerability row (after the severity filter and alias de-duplication)
apify-actor-start$0.05 per 1,000 runsOnce 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.50/1,000) + 12 × ($1.50/1,000) = about $0.17 ($150.00 + $18.00 = $168.00 per 1,000 such runs), plus $0.05 per 1,000 runs. 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:

  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.
{
"actor": "fairquery/osv-dependency-vulnerability-check",
"input": { "manifestText": "django==3.2.0\nrequests==2.25.0", "minSeverity": "HIGH" }
}

Troubleshooting

SymptomCause and fix
Run fails at once with INPUT_EMPTYNeither packages, manifestText nor sbomText was given. The sample packages in the Console form are prefill only and are not sent with API calls.
SBOM_UNSUPPORTED / SBOM_PARSE_FAILEDsbomText was XML, SPDX, a path, or not JSON. Paste a CycloneDX JSON document.
SBOM_COMPONENTS_SKIPPEDSome components had no supported purl (for example OS packages). The count and a short sample are on the warning row. Supported components are still checked.
RANGE_APPROXIMATED warningspackage.json ranges were reduced to their lower bound. Paste package-lock.json instead for exact versions.
VERSION_NOT_PINNED warningsrequirements.txt lines without == are skipped. Use pip freeze output.
MANIFEST_UNDETECTED / MANIFEST_PARSE_FAILEDSet manifestType explicitly, and paste the raw file content (not a path or URL).
OSV_QUERYBATCH_FAILED / OSV_VULN_FETCH_FAILEDOSV.dev was unavailable after retries (retryable: true). These rows are free; re-run later.
Severity UNKNOWNSome 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. Check malicious as well as vulnerable: a malicious-package advisory can be filtered out of the vulnerability rows by minSeverity and still set malicious.

What do license, deprecated and maintainers mean?

They come from the public registry for that ecosystem, not from a scan of the package source. maintainers is names only. deprecated is true for an npm deprecation message, a yanked PyPI/crates.io/RubyGems release, a NuGet deprecation, an abandoned Packagist project, a retracted pub.dev version, or a retired Hex release. A registry miss does not fail the run.

How much does it cost?

$0.50 per 1,000 package rows plus $1.50 per 1,000 vulnerability rows, and a start fee of $0.05 per 1,000 runs. 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 with Actor fairquery/osv-dependency-vulnerability-check.

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:

All Fairquery Actors: https://apify.com/fairquery

Data handling, security and support

  • Data retention: Each run keeps only its own storages in your Apify account (INPUT, the results dataset and a counts-only RUN_SUMMARY), under your Apify plan's retention. Package names and versions are sent to api.osv.dev and to the public registry for that ecosystem (npm, PyPI, the Go module proxy, Maven Central, crates.io, RubyGems, NuGet, Packagist, pub.dev, Hex). Maintainer emails from those responses are not stored. You can delete run storages and named stores at any time in Apify Console or through the API. Fairquery's code sends nothing to Fairquery.
  • Security reports: email info@getfairquery.com.
  • Support: the Issues tab on this page or info@getfairquery.com. We aim to reply within 3 business days (a target, not an SLA).

Disclaimer

Data comes from OSV.dev (aggregating GitHub Advisory Database, PyPA, Go Vulnerability DB, the OpenSSF malicious-packages corpus and others) and from public package registries, under their respective licenses. No warranty of completeness; absence of results does not prove a package is safe.