Search CVEs
Tracker searches accept scope=nixpkgs&trackerState=open or scope=nixpkgs&trackerState=closed. Omit trackerState for both states. Status combines with filedAfter and filedBefore and is applied before pagination and distinct-CVE counts. Unknown states do not match a requested status. Other corpora reject this filter. These are tracker issue states, not claims that a vulnerability is fixed or a system is affected.
The site's ecosystem/distribution selector includes NixOS / nixpkgs (security issue filings). It selects scope=nixpkgs, not an OSV ecosystem. Matching filings are not a release exposure assessment. Repology package/version evidence remains separate and does not by itself prove CVE applicability or fixed status.
Site prompt search resolves relative dates in the browser's timezone. The date filters themselves remain inclusive UTC source dates. Tracker CVE searches match mapped identifiers exactly; they do not establish affected or fixed status.
The site's source and ecosystem selectors constrain retrieval, not just the current page. Ecosystem selection uses the OSV index. Automatic source selection may answer from that index; it does not promise to query every upstream. Explicit NVD, tracker, GitHub advisory and CVE Program selections use their corresponding retrieval paths. Some sources cannot honor ecosystem or dated-plan constraints; incompatible combinations are rejected rather than ignored.
For scope=nixpkgs, total/knownCount count nixpkgs security issues. cveCount counts distinct valid CVE IDs referenced across all matching available issues, before pagination. issuesWithoutCves counts issues without a mapped CVE. A tracker filing date is not a vulnerability discovery date. When partial is true, known counts are lower bounds, not exhaustive totals.
Full-text search across all vulnerability sources including MITRE CVE List V5, NVD, GitHub Advisories, OSV, and nixpkgs security issues.
Endpoint
GET /api/v1/search?q={query}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query (min 2 characters) |
sources | string | No | Comma-separated list of sources to search: nixpkgs-tracker, github-advisories, osv, cve-list-v5, nvd. An unrecognized name returns 400 |
sort | string | No | Sort order: date (default, newest first) or severity. Any other value returns 400 |
ecosystem | string | No | Filter by ecosystem (e.g., npm, PyPI) |
indexed | 1 | No | Search indexed OSV records, or the tracker corpus for q/q, without a live fan-out |
scope | indexed, nixpkgs, nvd | No | Explicit corpus selection overrides keyword inference, including for q |
limit | integer | No | Page size, 1 to 100; default 50 |
offset | integer | No | Page offset for indexed, tracker or NVD searches |
recordedAfter, recordedBefore | date | No | Inclusive source-reported OSV record dates (YYYY-MM-DD). These may be import or roll-up dates, not original CVE publication dates |
filedAfter, filedBefore | date | No | Inclusive nixpkgs security issue filing dates, not CVE publication dates |
publishedAfter, publishedBefore | date | No | With scope, inclusive NVD publication dates. A dated search needs a start date and at most 120 days; omitted end means today |
Indexed and explicit tracker searches apply supported constraints before counting and pagination. Read partial, coverage, coverageHealth and dateBasis. total: null means completeness or freshness is unknown; knownCount counts only stored matching records. No matches is not proof that no vulnerabilities exist. Unsupported constraints return 422; unavailable storage returns 503. Corpus-wide severity constraints and original CVE publication-date constraints are not supported by this indexed search. sources and explicit sorting cannot be combined with constrained indexed searches.
NVD scope applies dates before pagination and caches successful queries for five minutes. It searches descriptions, so a mention is not proof that the named product is affected. These dates are not vendor disclosure dates. NVD scope does not accept indexed, ecosystem, source-selection or severity constraints. An upstream failure returns 503, never zero matches. OSV relevance places upstream advisories ahead of distributor notices before pagination, preserving advisory identities and totals.
Natural-language interpretation is a website feature, not a public API service. Build agents using these deterministic search parameters and the dossier API.
curl 'https://api.vulnpatch.dev/api/v1/search?q=openssl&indexed=1&recordedAfter=2026-01-01'
curl 'https://api.vulnpatch.dev/api/v1/search?q=nixpkgs&filedAfter=2025-12-25&offset=50'
curl 'https://api.vulnpatch.dev/api/v1/search?q=chrome&scope=nvd&publishedAfter=2026-09-20&publishedBefore=2026-09-26'Available Sources
| Source Key | Description |
|---|---|
nixpkgs-tracker | nixpkgs security issues (the scope keeps its original name for compatibility) |
github-advisories | GitHub Security Advisories |
osv | OSV.dev vulnerabilities |
cve-list-v5 | MITRE CVE List V5 (official source) |
nvd | NVD (NIST enriched data) |
Response
Illustrative response shape; identifiers and descriptions below are synthetic.
{
"success": true,
"data": {
"query": "curl",
"ecosystem": "all",
"sources": ["nixpkgs-tracker", "github-advisories", "osv", "cve-list-v5", "nvd"],
"sort": "date",
"count": 2,
"total": null,
"partial": true,
"results": [
{
"type": "cve",
"id": "CVE-2099-10001",
"cve_id": "CVE-2099-10001",
"summary": "Synthetic example advisory for curl",
"severity": "high",
"published_at": "2024-09-15T12:00:00Z",
"source": "cve-list-v5"
},
{
"type": "github-advisory",
"id": "GHSA-xxxx-yyyy-zzzz",
"cve_id": "CVE-2099-10001",
"summary": "Synthetic example advisory for curl",
"severity": "high",
"source": "github-advisories"
}
]
},
"timestamp": "2026-02-05T12:00:00.000Z"
}Response Fields
| Field | Type | Description |
|---|---|---|
count | number | Matches found before the page was cut to limit -- not the length of results. Check results for what's actually in this response |
total | number|null | Total matches, when the source can report one; null when it cannot |
partial | boolean | true when not every source answered, or an answering source itself reported a partial result -- read this before trusting an empty or small results |
truncated | boolean | count (or a source behind it) held more matches than this page returned |
cappedSources | string[] | Sources that were truncated for this query |
failedSources | string[] | Sources that errored and contributed nothing to this response; absent from results means not found only for sources NOT in this list |
slowSources | string[] | Sources still running when the request's own budget ran out; same meaning as failedSources for the purpose of trusting an empty result |
notWaitedFor | string[] | Sources deliberately not queried for this request shape (e.g. NVD on a keyword query without scope) |
corpusMatch | string|null | The corpus keyword the query matched (e.g. nixpkgs-tracker), or null when it matched nothing |
nicknameMatch | object|null | The project nickname record the query matched ({nickname, cves, summary, reference, ambiguous, advisories, noCveReason}), or null when it matched nothing |
emptyReason | string|undefined | Present only on a genuinely empty result, naming why (e.g. no sources matched) rather than leaving a reader to guess |
suggestions | string[]|undefined | Alternate queries to try, offered only alongside an empty or thin result |
upstreamAvailable | boolean | Indexed search only. Whether each result's upstream CVE relationships could actually be read this request. false means that lookup failed, not that no result has an upstream CVE |
Each indexed result can also carry:
| Field | Type | Description |
|---|---|---|
upstream | string[] | CVE ids this advisory names only indirectly -- a distribution package advisory naming a CVE it fixes, without that CVE being the advisory's own id or a listed alias. Empty when none are known or upstreamAvailable is false, which are not the same thing |
summaryFrom | object|undefined | Set when summary was borrowed from a different, more descriptive advisory about the same CVE, because this record's own source (commonly a container distribution) publishes no free-text description of its own. Names the donor: { cve, id } |
A reader should never treat an empty or short results array as "nothing exists" without first checking partial, failedSources and slowSources: those three together are the difference between a confirmed-empty search and one where a source simply didn't answer in time.
Example
# Search for curl vulnerabilities across all sources
curl "https://api.vulnpatch.dev/api/v1/search?q=curl"
# Search only MITRE and NVD
curl "https://api.vulnpatch.dev/api/v1/search?q=openssl&sources=cve-list-v5,nvd"
# Search by CVE ID
curl "https://api.vulnpatch.dev/api/v1/search?q=CVE-2024-45490"Code Examples
async function searchVulns(query, sources = null) {
let url = `https://api.vulnpatch.dev/api/v1/search?q=${encodeURIComponent(query)}`;
if (sources) {
url += `&sources=${encodeURIComponent(sources)}`;
}
const response = await fetch(url);
const { data } = await response.json();
console.log(`Found ${data.total} results for "${data.query}"`);
data.results.forEach(result => {
console.log(`[${result.source}] ${result.id}: ${result.summary || result.title}`);
});
return data.results;
}
// Search all sources
searchVulns('curl');
// Search specific sources
searchVulns('openssl', 'cve-list-v5,nvd');import requests
from urllib.parse import urlencode
def search_vulns(query, sources=None):
params = {'q': query}
if sources:
params['sources'] = sources
url = f"https://api.vulnpatch.dev/api/v1/search?{urlencode(params)}"
response = requests.get(url)
data = response.json()['data']
print(f"Found {data['total']} results for '{data['query']}'")
for result in data['results']:
print(f"[{result['source']}] {result['id']}: {result.get('summary') or result.get('title')}")
return data['results']
# Search all sources
search_vulns('curl')
# Search specific sources
search_vulns('openssl', 'cve-list-v5,nvd')Use Cases
- CVE lookup: Search by CVE ID to find details across sources
- Package security: Search by package name to find known vulnerabilities
- Research: Explore vulnerabilities by keyword or technology
- Dashboards: Build unified search interfaces across data sources
Caching
Traditional search uses query-specific caches. Explicit constrained corpus searches are returned with Cache-Control: no-store.
Evidence questions on the site
Reviewed security terms use a separate deterministic reference path. For example, what are KEVs and what is CISA KEV explain CISA's Known Exploited Vulnerabilities catalogue and cite CISA directly. These answers are labeled Reference answer; they do not run a model or search advisory descriptions. Requests to list or filter KEV entries remain distinct and are not converted into definition questions.
Definition questions such as what is heartbleed and what is log4j retrieve explanatory evidence alongside independent advisory search results. Existing nickname mappings resolve known vulnerability names; other topics search the available corpus for candidate CVEs. Up to three distinct dossiers supply descriptions for evidence selection. This is not a manual product-definition list, an exhaustive assessment, or a guarantee of product identity. Topics with no usable CVE evidence retain advisory results and an explicit coverage notice.
The site's search bar accepts single-CVE questions such as Explain CVE-2024-3094. It retrieves the public dossier and shows cited evidence with collection time and coverage gaps. The selection model cannot add factual prose or citation URLs. When selection is unavailable, the site shows labeled dossier excerpts instead. Actor attribution is not available without a reviewed actor-evidence corpus.
This is a site feature, not a public inference API. Existing keyword searches, date filters, counts and tracker membership queries keep their normal behavior. Source and ecosystem filters constrain topic candidate retrieval, not the individual facts in the resulting dossiers. They must be cleared for an exact-CVE full-record evidence answer. No semantic corpus index or live web research is used for these questions.