EchelonGraph CVE & Exposure
Server Details
CVE, KEV, EPSS, SBOM and advisory lookups; per-CVE exposure from Shodan data (© Shodan). Keyless.
- Status
- Healthy
- Uptime
- 100.0% over 19 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- echelongraph/echelongraph-mcp
- GitHub Stars
- 8
- Server Listing
- EchelonGraph MCP Server
TDQS
Scored across 16 tools
There are three distinct 'am I affected' tools (check_affected for a single product/package, check_sbom for purls/SBOM documents, scan_manifest for lockfiles) and three per-CVE deep-dive tools (get_cve, cve_intel, cve_remediation) whose returned fields overlap heavily, e.g. get_cve already carries a capped remediation summary and cve_intel carries fixed_branches. The descriptions are unusually detailed and do disambiguate on close reading, but an agent picking among the per-CVE tools or among check_sbom/scan_manifest must read a lot of prose to choose correctly.
All names are snake_case, but the convention splits into several families: verb_noun actions (check_affected, scan_manifest, search_cves, get_cve), bare noun-phrase resources (cve_intel, cve_exposure, cve_summary, epss_history, exposure_radar, kev_recent), and a prepositional form (vendor_advisories_for_cve). Notably get_cve sits alongside cve_intel/cve_remediation/cve_exposure for the same per-CVE scope, so the verb-first vs noun-first split does not map cleanly onto a pattern.
16 tools for a CVE intelligence, remediation and exposure platform is slightly above the comfortable band but each maps to a recognizable capability (search, detail, enrichment, remediation, EPSS history, KEV, CWE, exposure, SBOM/manifest scanning, vendor advisories). No tool looks redundant enough to drop outright, though the three per-CVE detail tools could plausibly be consolidated.
The surface covers the domain broadly: CVE search and detail, CWE lookup, EPSS history, KEV recency, remediation, vendor advisories at three levels, per-CVE and aggregate exposure, and affected checks at single-package, SBOM and lockfile granularity. Gaps are minor — no batch multi-CVE lookup, no CWE browsing/search, and no way to enumerate tracked vendors or ecosystems, all of which agents can work around.
Available Tools
16 toolscheck_affectedAm I affected? (product or package at a version)ARead-onlyIdempotentInspect
Whether a product or package at a given version is affected by known CVEs, from the same matcher as echelongraph.io/am-i-affected. The CPE path takes product (an NVD CPE product token, such as nginx) and version, and returns the CVEs whose NVD CPE match criteria include that product at that version; each match names the vendor NVD asserts (cpe_vendor) and whether it was verified (vendor_unknown). The registry path takes ecosystem (npm, PyPI, Maven and other OSV ecosystem names), package and version, and decides each OSV advisory EchelonGraph holds for that package as affected, not affected or undetermined. count depends on assessed: assessed false means the lookup did not evaluate this component, not_assessed_reason says why, and a count of 0 there is not a finding of not affected. An advisory undecidable at this version is reported as undetermined (undetermined_count, and up to 50 of them in undetermined), never as safe. Each match carries cve_id, kev_listed, ransomware, epss_score, effective_score, effective_severity and score_assessed (false: not yet scored, so echelongraph_score is withheld). A registry match also carries interval, the advisory interval holding it, and fixed_in, the lowest unaffected version above it, or null with fixed_in_reason; a CPE match carries no fixed_in. All four inputs travel in request headers, never in the URL. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, the excluded and undetermined samples keep their first 10 entries, each its cve_id and reason, cve_ids keeps its first 10, and each match keeps cve_id, kev_listed, ransomware, epss_score, effective_score, score_assessed and fixed_in at least. Every CPE match stays in the text; near the cap, a registry list's last matches can leave it, and the note says how many.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| package | No | Registry path: the package name in that ecosystem, such as lodash. | |
| product | No | CPE path: the NVD CPE product token, such as openssl, nginx or linux_kernel. Leave out for the registry path. | |
| version | Yes | The version to check, such as 3.0.0. | |
| ecosystem | No | Registry path: the package's ecosystem, such as npm, PyPI or Maven. Give with package, not with product. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover read-only/idempotent/open-world, and the description goes far beyond them: it discloses that inputs travel in request headers not the URL, that assesssed=false means 'not evaluated' rather than a negative finding, that undetermined is never reported as safe, that echelongraph_score is withheld when score_assessed is false, and it spells out truncation semantics (TEXT CUT vs DATA CUT and which fields survive). That is exactly the behavioral context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded, but the body is a dense wall of run-on sentences, and roughly 40% of the text is devoted to truncation mechanics (30,000-character cap, field thinning order, which samples keep their first 10 entries). That detail is useful once but crowds out path selection guidance and is disproportionately verbose relative to the tool's five parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description supplies the interpretive layer an agent needs: what each match field means (cve_id, kev_listed, epss_score, effective_score, score_assessed), interval/fixed_in versus the CPE path's lack of fixed_in, and how truncated results behave. Nothing required to call it or read the answer correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the description largely restates it — 'product (an NVD CPE product token, such as nginx)', 'ecosystem (npm, PyPI, Maven…)' and 'Leave out for the registry path' all mirror the schema text. The only genuinely additive points are the mutual exclusivity framing of the two paths and the header-transport note, which is modest compensation for a 3-parameter-path tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a specific verb and resource ('Whether a product or package at a given version is affected by known CVEs') and pins the source of truth ('same matcher as echelongraph.io/am-i-affected'). It then splits the tool into two named paths (CPE and registry) so an agent can tell exactly which mode it is invoking, distinct from siblings like check_sbom or scan_manifest.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly states the conditions selecting each path: CPE needs product (NVD CPE product token) + version, registry needs ecosystem + package + version. What it does not do is route against siblings (scan_manifest, check_sbom, cve_exposure) — there is no 'use this instead of X when…' statement, so sibling selection is still inferred from name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_sbomCheck an SBOM against the advisory corpusARead-onlyIdempotentInspect
Check a dependency list against EchelonGraph's advisory corpus, one verdict per component. For container images and Kubernetes pods, the input is an SBOM of each image, or its purls. Pass purls (package URLs, up to 2,000 distinct, 10,000 with repeats) or sbom (a CycloneDX or SPDX JSON document, up to 5,000,000 characters). This server reads the document's purls; only they are sent to the API, in POST bodies of at most 200, never in a URL; the document itself is not sent on. Run from npm, this server is on your machine; over the hosted endpoint (mcp.echelongraph.io) it is EchelonGraph's, and the document is the request body, accepted up to 6 MiB. data.results holds one row per component sent, in order, with verdict (affected, not_affected, undetermined or not_assessed), not_assessed_reason, cve_ids, matched_package and matched_via (a deb or apk purl's upstream qualifier matches as its source package); each match carries fixed_in (the next unaffected version) or null with fixed_in_reason. data.summary counts the verdicts. not_affected is the only clean verdict: not_assessed (no verdict, as for a deb, apk or rpm purl without a distro qualifier naming its release, which EchelonGraph does not guess) and undetermined are not, and the note counts both. The API allows 1,200 components a minute per caller; on a 429 the tool waits out Retry-After, up to 50 seconds a call, then answers what it has, the rest in data.not_sent_purls, not clean. Input with more than 2,000 distinct purls is refused, not truncated. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, each row keeps index, purl, verdict, not_assessed_reason and cve_ids at least, each match its fixed_in while kept; not_affected rows leave the text first, then not_assessed ones; not_sent_purls keeps its first 10.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| sbom | No | a CycloneDX JSON or SPDX JSON document, as JSON text or as an object; its purls are read by this MCP server and only they are sent to the API; over the hosted endpoint (mcp.echelongraph.io) the document is the request body | |
| purls | No | package URLs to check, e.g. pkg:npm/lodash@4.17.20 or pkg:deb/debian/openssl@3.0.11-1~deb12u1?distro=debian-12 (up to 2,000 distinct, sent in batches of 200), in a list of at most 10,000 entries, repeats included |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent, but the description adds substantial behavioral detail beyond them: only purls are sent to the API (never the document, never in a URL), batching at 200 per POST, a 1,200-component/min rate limit, 429 handling with Retry-After up to 50 seconds, refusal rather than truncation above 2,000 distinct purls, and the TEXT CUT/DATA CUT truncation scheme with row-retention order. This is exactly the operational context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and nearly every sentence carries operational detail (limits, truncation, verdict meaning) rather than filler. The density makes it a wall of run-on sentences, which costs readability, but little could be removed without losing real guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an output schema existing, the description supplies the interpretation rules an agent cannot get from the schema alone: not_affected is the only clean verdict, not_assessed/undetermined are not, fixed_in semantics, and the truncation/rate-limit failure modes. Nothing material is missing for correct invocation and result reading.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema does most of the work. The description still adds semantics beyond it: purls up to 2,000 distinct (10,000 with repeats), sbom as CycloneDX or SPDX JSON up to 5,000,000 characters, a 6 MiB hosted-endpoint body limit, and that only the document's purls are read and sent. A 5 is not warranted because much of this is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource — check a dependency list / SBOM against EchelonGraph's advisory corpus, one verdict per component — and names the concrete input forms (CycloneDX/SPDX SBOM or purls) for container images and Kubernetes pods. It does not explicitly distinguish itself from siblings such as scan_manifest or check_affected, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: use it for container images and Kubernetes pods, supplying an SBOM of each image or its purls. It also explains what 'clean' means (only not_affected), which guides interpretation. It never names an alternative tool or an exclusion condition, so not a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cve_exposureInternet exposure for one CVEARead-onlyIdempotentInspect
Internet-exposure footprint for one CVE from EchelonGraph's KEV-exposure radar: how many internet-facing services (distinct ip:port, returned as exposed_hosts; a machine answering on two ports counts twice) the radar has on record running a version its CVE matcher maps to this CVE, with a country/product breakdown and a ransomware flag. Aggregate and host-redacted; free and keyless. Method: exposure counts are derived from Shodan data. Shodan data is owned by Shodan, which holds its copyright (© Shodan). Every 12 h, when Shodan query credits allow, the radar runs one Shodan query per tracked product, reads up to 100 ip:port services per query, and keeps a service when its banner version matches a CISA-KEV or high-EPSS CVE; a service whose row has not been written or refreshed for 21 days is dropped. The radar only looks for its tracked set of CVEs: for a CVE outside that set the note says NOT ASSESSED (exposure_state not_assessed), and its 0 is not a measurement. last_seen is when EchelonGraph last wrote or refreshed a service's row, not when the service was observed: a port still listed by Shodan InternetDB refreshes it without re-reading the banner, so a patched service can stay counted while its port stays open. A count is therefore a banner-version inference over a sample, not an exploit test and not an internet-wide census. Its structured result's state is not_assessed with measured_at null, since the answer dates no observation; the count is still relayed, labelled, as what the radar holds on record. exposure_state says what the count is: exposed, measured_zero, not_assessed or tracking_unknown; coverage.in_scope is the API's tracked verdict; freshness is null; data is the API's JSON. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| cve_id | Yes | a CVE ID, e.g. CVE-2023-44487 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the readOnly/openWorld annotations: discloses data provenance (Shodan, copyright), refresh cadence (every 12 h, credit-limited), the 100 services/query sampling cap, the 21-day staleness drop, and the subtle last_seen semantics (a port still in InternetDB refreshes the row without re-reading the banner, so patched hosts can stay counted). Also explains truncation behavior for both text and structured results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is correctly front-loaded, but the body is a single very dense paragraph with repeated material: the 30,000-character cut rule is stated twice and then restated at length in the `full` schema description. Sentences like 'its structured result's state is not_assessed with measured_at null, since the answer dates no observation' are hard to parse for an agent scanning for a call decision.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still supplies the interpretive layer an agent needs: exposure_state enum values (exposed, measured_zero, not_assessed, tracking_unknown), what coverage.in_scope means, why freshness is null, and how DATA CUT/TEXT CUT manifest. Nothing material about invoking or interpreting this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so baseline is 3; the description still adds value by explaining what `full: true` buys (uncut structured data) and why a client output cap can refuse a large answer, plus why a returned count may be a labelled 'not_assessed' rather than a measurement. The cve_id semantics are left entirely to the schema, which is acceptable given coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope: 'Internet-exposure footprint for one CVE', and immediately defines the unit (distinct ip:port, double-counting multi-port hosts). This clearly separates it from aggregate siblings like exposure_radar and from intel/remediation siblings (cve_intel, cve_remediation) without the agent needing to open schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States a concrete when-not-to-trust-it rule: for CVEs outside the tracked set the result is NOT ASSESSED and 'its 0 is not a measurement', and it explicitly frames the count as 'not an exploit test and not an internet-wide census'. It never names a sibling alternative (exposure_radar, cve_intel), so routing is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cve_intelCVE weakness, exploits and packagesBRead-onlyIdempotentInspect
Weakness, exploit code, detection checks, affected packages and fixed versions for one CVE, from EchelonGraph's per-CVE enrichment. Returns cwes (each cwe_id with name and source), exploits (each with kind, source_name, source_url, source_published_at (the source's date, null if none), eg_first_seen_at (when EchelonGraph recorded it) and verified_status; at most 10, verified first) with exploits_total, exploits_capped, exploits_by_kind and exploits_by_status, affected_packages (ecosystem, package_name, version_range, fixed_version, fixed_branches), fixed_versions (each fixed version with the vulnerable_range it fixes) and timeline (newest enrichment-history rows, with timeline_total). fixed_branches lists each affected range on record (from introduced ("0" is the first version) to below fixed, or through last_affected, with advisory_id (its OSV record) and source); in the ecosystem's version order, an affected version's fix is the first fixed above it that no range of its row holds (none past a range with no fixed). fixed_version is one range's fix, kept for compatibility, not the fix for every affected range. fixed_branches [] is not a finding that no fix exists. verified_status is the source's label, not a guarantee the exploit works on a given system. An empty exploits list is not evidence that no public exploit exists: it covers only the sources EchelonGraph ingests, and which are polled depends on the deployment. A section the API could not read is named in coverage.sections_failed and left out of data, never relayed as an empty list. Its structured result carries notes, with data, which the first text block holds whole up to 30,000 characters; its coverage names the sections relayed, failed and left out. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| cve_id | Yes | a CVE ID, e.g. CVE-2021-44228 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/openWorld, yet the description still adds real behavioral context: empty exploits is not proof no exploit exists and which sources are polled is deployment-dependent, verified_status is a source label not a guarantee, coverage.sections_failed means a section is omitted rather than empty, and fixed_branches [] does not mean no fix exists. These are non-obvious failure-mode disclosures, though they are buried rather than structured.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph re-enumerates return fields (cwes, exploits with all subfields, affected_packages, fixed_versions, timeline) even though an output schema exists, and the truncation/30,000-character material appears twice. Useful caveats are interleaved with restatement, so it is not front-loaded for scanning and several sentences do not earn their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering safety, the description still supplies the interpretation caveats an agent needs (coverage gaps, exploit-source limits, fixed_version compatibility note, truncation). What remains missing is selection guidance relative to the many sibling CVE tools, not payload completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the `full` parameter already has an extensive schema description covering DATA CUT and truncation, so the schema does the heavy lifting. The prose repeats that same truncation/`full: true` behavior at the end, adding little beyond what the schema states, which matches the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a concrete resource for a single CVE (weaknesses, exploits, detection checks, affected packages, fixed versions) from a named enrichment source, so the agent knows exactly what it gets. It does not differentiate from near-siblings like get_cve, cve_summary or cve_remediation, which is the main gap, and it is phrased as a noun list rather than a verb.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to pick this over get_cve, cve_summary, cve_exposure or cve_remediation, and no exclusion conditions. The only conditional guidance present concerns the `full` parameter ('Whole data is for a program...'), which is parameter usage, not tool selection. Usage is at best implied by 'for one CVE'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cve_remediationHow one CVE is fixedARead-onlyIdempotentInspect
How one CVE is fixed, as its sources state it, in one answer. Every text is relayed as stated by its source; EchelonGraph has not tested it. An empty list or a remediation_state of none_in_source or not_parsed is not a finding that no fix exists. Returns fix_status (the API's fix-status rule, as CVE Pulse shows it: state and basis), cisa (for a KEV-listed CVE CISA's required_action, due_date, short_description and notes_urls, verbatim; CISA's required_action is directed at US federal civilian agencies (under BOD 26-04, which replaced BOD 22-01 on 10 June 2026) and is not EchelonGraph's advice.), fixed_branches (each affected package with fixed_branches: every affected range, introduced and fixed or last_affected, and fixed_version, one range's fix), vendor_remediations (each vendor advisory naming the CVE, newest first, at most 20, with remediation_state, remediation_kinds and items, each with kind, source_category, text and url), fix_references (references NVD or the CNA tagged Patch or Mitigation), patches, coverage and failed_sections. kind is the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. remediation_state is parsed, none_in_source (none listed for this CVE), not_parsed (that vendor's remediation is not read) or withdrawn. ecosystem, package and version (all three or none, sent in request headers, never in the URL) add installed, the verdict at that version, and fixed_in, the lowest unaffected version above it, or null with fixed_in_reason. A section the API could not read is named in failed_sections, not relayed as empty. A REJECTED CVE answers not_assessed. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, vendor texts are shortened first; kinds, states and URLs are kept.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| cve_id | Yes | a CVE ID, e.g. CVE-2021-44228 | |
| package | No | Installed version, with ecosystem and version: the package name in that ecosystem, such as org.apache.logging.log4j:log4j-core. Sent in a request header. | |
| version | No | Installed version, with ecosystem and package: the version installed, such as 2.14.1. Sent in a request header. | |
| ecosystem | No | Installed version, with package and version: the package's ecosystem, such as npm, PyPI or Maven. Sent in a request header. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the readOnly/idempotent annotations: it discloses that all text is relayed verbatim and untested, that an empty list or none_in_source/not_parsed is not evidence of no fix, that CISA required_action is aimed at US federal agencies and is not advice, that failed_sections means a section could not be read rather than being empty, that REJECTED CVEs answer not_assessed, and that responses past 30,000 characters are cut (TEXT CUT/DATA CUT) with a stated precedence for what gets shortened.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and every sentence carries information, but the run-on parenthetical sentences (the CISA BOD asides, the nested truncation rules) make it hard to scan. It is dense rather than concise, and restructuring into short bullets would preserve the content with less parsing effort.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the hard cases an agent must handle (truncation, failed sections, rejected CVEs, empty result semantics) and the field vocabulary of the return value. Since an output schema exists, the field-by-field enumeration is partly redundant, but the behavioral caveats are not, and nothing essential for a correct call appears missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics: ecosystem/package/version must be supplied all three or none, they are sent in request headers and never in the URL, and together they add installed, a version verdict, and fixed_in / fixed_in_reason. The full flag's cost (a client sizing structured output can refuse an oversized answer) is also explained beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource statement: it answers how one CVE is fixed, as its sources state it. Clear what it returns (fix_status, cisa, fixed_branches, vendor_remediations, fix_references). It does not name or distinguish itself from siblings like get_cve, cve_summary or cve_intel, which likely overlap on the same CVE.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied through the optional ecosystem/package/version triple adding an installed-version verdict, and through the 'empty list is not a no-fix finding' caveat, but there is no explicit when-to-use-this-vs-alternatives guidance. With siblings get_cve, cve_summary, cve_intel and vendor_advisories_for_cve in the namespace, the agent is left to infer the routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cve_summaryCVE feed summaryBRead-onlyIdempotentInspect
Summary of EchelonGraph's CVE Pulse feed: summary.total active CVEs, their counts by severity band (summary.critical, summary.high, summary.medium, summary.low), the count with no band (summary.none), and summary.last_updated, the newest modification time among those records. summary.none is not a severity rating of None: it counts the active CVEs with no severity band from any source, that is, CVEs not yet scored, and the answer may carry the same count again as summary.unscored. Whenever summary.none is above zero the note says so, and names those CVEs not yet scored, not CVEs rated None. summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label: provenance, never EchelonGraph's severity band. summary.nvd_none is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. summary.rejected counts the CVE records rejected (withdrawn) by their numbering authority, which summary.total and the other counts above leave out: they are withdrawn records, none of them a vulnerability. poller holds the in-memory counters of the NVD poller of the one API instance that answered, counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. Its structured result's state is measured, with freshness.nvd_poll the fleet's last completed NVD poll and its interval, from the answer's nvd_poll (freshness null without one), and data equal to the API's JSON less each poller field (or the whole poller) the note names as left out. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only/idempotent annotations, the description meaningfully discloses runtime behavior: truncation past 30,000 characters of JSON, the TEXT CUT/DATA CUT signaling, and the fact that 'poller' counters are in-memory, instance-specific, and zeroed on restart. It also clarifies that rejected/withdrawn records are excluded from total. That is substantive behavioral context, though much of the rest duplicates output-field semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a dense, run-on block of field-by-field exposition with no headings, bullets, or front-loading of the usage decision. Many sentences laboriously distinguish summary.none from summary.nvd_none, and the reader must wade through all of it to learn what the tool is for.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description need not explain return values, yet nearly all its length is devoted to that. It omits the selection context an agent actually needs among many CVE siblings, making it over-complete on payload semantics and under-complete on purpose fit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single optional 'full' parameter is fully documented in the schema itself, so the baseline is 3. The description adds only the cross-reference to DATA CUT, which is marginal beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause, 'Summary of EchelonGraph's CVE Pulse feed: summary.total active CVEs, their counts by severity band,' does state a specific resource and an aggregate-count purpose, so an agent can tell this is a stats tool rather than a lookup. However, it never contrasts itself with siblings such as search_cves or cve_intel, so the distinction is left implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use or when-not-to-use guidance and no named alternative among the fifteen sibling tools. The only actionable instruction concerns the 'full' flag for output size, which is a parameter mechanic, not tool selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
epss_historyEPSS change history for one CVEARead-onlyIdempotentInspect
How one CVE's EPSS score (FIRST's exploit-prediction probability, 0 to 1, with its percentile) has changed, as EchelonGraph recorded it: points, oldest first, each with at, epss_score, epss_percentile and score_date (FIRST's score date, null where the record does not hold it); current, the record's value now (epss_score, epss_percentile, epss_updated_at); series_kind, always change_only; series_starts_at, when EchelonGraph began recording EPSS changes for any CVE; complete_since, from when the record holds every change; coverage, which FIRST score dates the record holds; history_rows, points_truncated and latest_point_matches_current. Pass a CVE ID like CVE-2023-44487. The series is change-only: a point is a recorded change, and a day without a point is not a recorded value. A daily series interpolated from it holds values EchelonGraph never recorded, so the series is never a daily series. Before series_starts_at nothing was recorded, so a missing point there means not recorded, not unchanged, and the value in force before a CVE's first point is not in the series. Between series_starts_at and complete_since the record misses changes, so a missing point there does not mean unchanged either; only from complete_since on is every change a point. coverage.days_missing and coverage.days_partial name the FIRST score dates the record does not hold, or holds for some CVEs only. latest_point_matches_current false means a change is missing from the series. Its structured result's measured_at is current.epss_updated_at (when EchelonGraph last wrote a changed value, not FIRST's score date), its coverage says which part of the record is complete and which score dates it holds, and its freshness is null. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| cve_id | Yes | a CVE ID, e.g. CVE-2023-44487 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive), and the description goes well beyond them: it discloses the 30,000-character cut with TEXT CUT/DATA CUT markers and full:true bypass, states freshness is null, and defines measured_at as EchelonGraph's write time rather than FIRST's score date. Completeness semantics (series_starts_at, complete_since, coverage.days_missing, latest_point_matches_current) give the agent the guardrails needed to avoid misreading gaps as stability.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, but the body is a dense semicolon-and-parenthetical chain that mixes return-field documentation with interpretation rules in one block. Nearly every clause is informative, yet the presentation makes it harder to scan than a few short, separated statements would.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool whose result semantics are unusually subtle (change-only series, partial coverage windows, output truncation), the description supplies everything needed to call and interpret it correctly, including what measured_at, coverage and freshness mean. With an output schema present, it still adds interpretive context rather than merely restating fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already defines both cve_id and full in depth, so the baseline is 3. The description echoes the CVE-ID example and the 'unless full: true' caveat but adds no format or constraint detail beyond what the structured fields already carry.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening states a precise verb+resource: the recorded change history of one CVE's EPSS score, including the exact fields returned (points, current, series_kind). It is clearly not the same as a general CVE lookup. It never names a sibling (e.g., 'use cve_intel/get_cve for the current score only'), so differentiation is inferred from scope rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Pass a CVE ID like CVE-2023-44487' gives the calling pattern, and the long change-only explanation tells the agent how to interpret results correctly. However, there is no explicit when-to-use/when-not-to-use against the 16 siblings, and no routing statement such as using this only when trend history matters versus a current-score tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
exposure_radarExposure radar totalsARead-onlyIdempotentInspect
Aggregate totals from EchelonGraph's internet-exposure radars: kev_exposure, internet-facing services running actively-exploited (CISA-KEV) CVEs, plus the ransomware-linked subset, derived from Shodan data; exposed_databases, unauthenticated data stores and observability UIs, found through Shodan (LeakIX when Shodan query credits run low) and then confirmed by EchelonGraph's own identified check (not a pure read: on Redis it names its client, and on ClickHouse its query is recorded in the server's query log); leaked_credentials, sampled from public GitHub push events; and shadow_ai, services found through Certificate Transparency logs and Shodan and then checked by EchelonGraph's identified probes. Shodan data is owned by Shodan, which holds its copyright (© Shodan). It also gives MCP-server counts: hostnames named like an MCP server in EchelonGraph's own Certificate Transparency feed (no Shodan data), each counted once by its latest verdict from EchelonGraph's identified MCP probe, which never sends tools/call. Service counts are distinct ip:port services, not machines. The result's note, and the outputSchema's description of each radar, label every number by what it counts. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. A kev_exposure.newest_kev CVE whose exposure_state is not_assessed has no measurement in the answer: its 0 is not one. Its structured result's state is not_assessed with measured_at null, since no radar dates what it counts; each count is still relayed as what that radar holds on record. freshness gives each radar's last_run_at where the API serves one; coverage names the radars that answered. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations by disclosing data provenance and licensing (Shodan ©, LeakIX fallback, GitHub push events, CT logs), the side effects of the 'identified check' (Redis client naming, ClickHouse query-log entries), and precise truncation semantics (30,000 chars, TEXT CUT vs DATA CUT, what the note explains). The 'not a pure read' wording sits in tension with readOnlyHint but is framed as probe artifacts on the target's logs rather than data mutation, so it reads as useful disclosure rather than a contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in the first clause, and most clauses carry real information, but the whole thing is one dense run-on paragraph mixing scope, provenance, licensing, truncation rules and null semantics. For a tool with a single optional boolean and a rich output schema, this is over-long and hard to scan; sub-structure or trimming of return-value detail would help.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of four heterogeneous radars, an output schema, and a truncation policy, the description covers what an agent needs: what each count means, what does *not* count (not_assessed, non-confirmed shadow_ai), how freshness/coverage behave, and how truncation is signalled. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above that by adding behavior the schema omits, namely that the *first text block* is also cut (TEXT CUT) at 30,000 characters and why whole data suits programs rather than token-capped clients. The `full` semantics themselves are already thoroughly documented in the schema, so it is not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause names a specific verb and resource ('Aggregate totals from ... internet-exposure radars') and then enumerates the four radars (kev_exposure, exposed_databases, leaked_credentials, shadow_ai) plus MCP-server counts. That scope is clearly distinguishable from the CVE-centric siblings (get_cve, cve_exposure, kev_recent), so an agent can tell what it gets here without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the reader infers 'use this for aggregate exposure totals, not per-CVE lookups.' The only explicit when-to guidance concerns the `full` parameter (whole data for a program; clients that size structured results can refuse it), and no sibling tool is named as an alternative for narrower questions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_cveCVE detailARead-onlyIdempotentInspect
One CVE's record: description, severity, cvss_v3_score, cvss_v4_score and cvss_v4_severity, echelongraph_score, echelongraph_severity and score_confidence, epss_score and epss_percentile, CISA-KEV status (kev_listed, kev_added_date, kev_due_date, kev_ransomware) and, if KEV-listed, CISA's own text relayed verbatim (kev_required_action, not EchelonGraph's advice; kev_short_description; kev_notes_urls), ghsa_id, references, cpe_match (one flat list) and cpe_configurations (NVD's configurations as NVD sent them, with each AND/OR operator; absent where none is stored, which is not a finding that no product is affected), remediation (a capped summary of its fix), published, modified and updated_at; each field only where the record has it. Pass a CVE ID like CVE-2023-44487. echelongraph_score, echelongraph_severity and echelongraph_risk are EchelonGraph's score only when score_assessed is true. With score_assessed false the CVE is NOT YET SCORED, not scored 0: any of those three it carries (0, NONE, 0) is a placeholder, not a rating, and does not mean the CVE is harmless; score_unassessed_reason says why, and the note labels each such CVE NOT YET SCORED. An answer with no score_assessed (an API older than that field) does not say whether the CVE was scored, the note says so, and a 0 there is not a rating either. patch_available is true when EchelonGraph holds, or once held, fix evidence for the CVE; patch_evidence is what it holds now, strongest first. patch_available false means no fix evidence is on record, which is not a finding that no fix exists. freshness is null: this answer carries no poll-completion time. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, each list in the record keeps its first entries, and the note names each list cut with its full length.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| cve_id | Yes | a CVE ID, e.g. CVE-2023-44487 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), and the description adds substantial interpretive context beyond them: score_assessed=false means NOT YET SCORED rather than 0, placeholder values must not be read as harmless, KEV text is CISA's verbatim wording rather than EchelonGraph advice, patch_available=false is an absence of evidence and not evidence of absence, freshness is null, and TEXT CUT/DATA CUT truncation behavior is explained.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The resource scope is front-loaded and the caveat sentences earn their place, but the long comma-separated enumeration of every returned field is redundant given the output schema exists, and several sentences are dense run-ons. It is information-dense rather than padded, yet materially longer than needed for correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations, a full input schema and an output schema already present, the description supplies exactly the missing interpretive layer: unscored-vs-zero semantics, provenance of KEV text, meaning of absent cpe_configurations and patch evidence, and truncation behavior. An agent can call this correctly and interpret the result without further context, with only sibling routing left to usage guidelines.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents both cve_id and the full/truncation parameter extensively, so the description's 'Pass a CVE ID like CVE-2023-44487' and 'unless full: true' are largely restatements. The description does add the TEXT CUT counterpart to the schema's DATA CUT explanation, but on balance it adds little semantic meaning to the parameters beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific resource and scope: 'One CVE's record', followed by an exhaustive enumeration of what that record contains (scores, KEV, GHSA, CPE, remediation, timestamps). It is clearly a single-CVE detail fetch rather than a search, but it never names a sibling such as cve_summary or cve_intel to draw the boundary explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the field-level detail signals 'call this when you need the full record', and 'Pass a CVE ID like CVE-2023-44487' gives the input shape. There is no statement of when to prefer cve_summary, cve_intel or cve_remediation over this tool, and no exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_cweCWE and its CVEsARead-onlyIdempotentInspect
One CWE (weakness class) and the CVEs classified under it. Returns cwe_id, name and description (from the MITRE CWE catalog EchelonGraph embeds, version catalog_version), total (the active CVEs in EchelonGraph's feed that an NVD, GitHub or CVE.org record classifies under it, rejected and reserved records left out), and cves, one page of 50: each with cve_id, severity, cvss_v3_score, echelongraph_score, echelongraph_severity, score_assessed, kev_listed, published and a shortened description. order says how the rows are sorted (CISA-KEV-listed first, then EchelonGraph score); an answer without order does not state its order, and the note says so. page is the page served, page_size its size and max_page the last page the API serves: a later page is answered as max_page, so past max_page pages total counts CVEs no page lists. echelongraph_score is EchelonGraph's score only when score_assessed is true; the note labels each row that is NOT YET SCORED. A total of 0 says that no CVE in EchelonGraph's feed is classified under that CWE, not that none exists. Pass cwe_id like CWE-79 (or 79) and an optional page (1-200). Its structured result carries state (measured), measured_at (null), method, coverage (total, returned, page, page_requested, page_size, max_page), freshness (null) and notes, with data equal to the API's JSON; the result's last text block repeats it without data (the first text block) and without the note's sentences (the text block before it), with which notes ends. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| page | No | page of 50 CVEs (default 1, max 200) | |
| cwe_id | Yes | a CWE ID, e.g. CWE-79 (or 79) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses ordering behavior, max_page clamping, score_assessed caveats, truncation modes, and text-block duplication semantics. These are substantial behavioral details not captured by the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a dense run-on paragraph that repeats return-value details already available in the output schema and buries key caveats in nested clauses. It front-loads the purpose but is not appropriately sized or structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with complex pagination, truncation, and composite result shapes, the description covers the important edge cases an agent needs and the output schema exists. It is complete, even if overlong.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents full, page, and cwe_id in detail. The description largely restates the same parameter behavior, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a clear verb+resource: one CWE and the CVEs classified under it, then enumerates the returned fields. It does not name or distinguish sibling tools such as get_cve or search_cves, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides mechanics such as passing cwe_id like CWE-79 (or 79), an optional page 1-200, and the meaning of total 0. It never says when to choose this tool over get_cve or search_cves, so usage is only implied by the purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_vendor_advisoryVendor advisory detailARead-onlyIdempotentInspect
One vendor advisory in full, by vendor and the vendor's advisory ID (the vendor and vendor_advisory_id of a vendor advisory row, never its advisory_id, EchelonGraph's internal UUID): title, description, severity, cvss_v3_score, cve_ids and known_cve_ids (those with a record in EchelonGraph's CVE feed), affected_products, remediation, references, vendor_modified_at, and withdrawn_at and withdrawn_reason when the vendor withdrew it. remediations lists each remediation the vendor lists, with kind (the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other), source_category, text, url and the cve_ids and product_ids it covers; each text is the vendor's, verbatim, untested by EchelonGraph. remediation_state is parsed, none_in_source, not_parsed or withdrawn: none_in_source and not_parsed are not a finding that no fix exists. Each advisory carries vendor_published_at (the vendor's date), our_first_seen_at (when EchelonGraph first recorded it) and withdrawn (true: the vendor rescinded it). Each advisory also carries rejected_cve_ids: the CVE IDs it names whose CVE record was rejected (withdrawn) by its numbering authority, which are not active vulnerabilities. coverage.vendor_window is that vendor's window in what EchelonGraph holds: vendor, advisories, earliest_vendor_published_at, latest_vendor_published_at, held_since (where that window begins) and history_backfill (in_progress or not_started: older advisories not all held yet); null when the windows could not be read or carry none for that vendor. measured_at is our_first_seen_at. Its freshness is null: the answer carries no poll-completion time. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| vendor | Yes | the vendor slug, e.g. microsoft, redhat, github | |
| advisory_id | Yes | the vendor's own advisory ID, a row's vendor_advisory_id, e.g. RHSA-2024:1234, GHSA-xxxx-xxxx-xxxx or CVE-2024-3400; not a row's advisory_id, EchelonGraph's internal UUID |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations (which only declare read-only/idempotent) by disclosing that remediation text is the vendor's verbatim and untested, that none_in_source and not_parsed are not a finding that no fix exists, that rejected_cve_ids are not active vulnerabilities, that freshness is null because no poll-completion time is carried, and how coverage windows and backfill state are reported. These are exactly the traps an agent would otherwise misread.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One enormous run-on paragraph that mixes identifier warnings, field enumeration, remediation semantics, and output-size behavior with no headers or front-loading. Nearly every fact is legitimate, but the packing makes it hard to scan and the truncation mechanics arrive at the end, where they compete with the actual call guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex, caveat-laden record lookup the description covers the traps (ID confusion, withdrawn/rejected states, partial coverage, truncation) and an output schema exists so return shapes needn't be re-explained. It loses a point for spending most of its length re-describing output fields that the output schema already defines.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already spells out the vendor slug, the vendor_advisory_id-vs-advisory_id distinction, and the full/truncation flag. The description largely restates those same points in prose rather than adding syntax, formats, or edge cases the schema lacks, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource ('One vendor advisory in full, by vendor and the vendor's advisory ID') and immediately disambiguates the identifier from EchelonGraph's internal advisory_id. An agent can tell this is a single-record lookup distinct from search_vendor_advisories or vendor_advisories_for_cve without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the single-record framing; the description never names the sibling tools it competes with (search_vendor_advisories, vendor_advisories_for_cve, cve_remediation) or states when to prefer this one. The one disambiguation it does give is about identifiers, not about choosing this tool over an alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
kev_recentRecent CISA KEV additionsARead-onlyIdempotentInspect
The CVEs CISA has added to its Known Exploited Vulnerabilities (KEV) catalog, newest first, from EchelonGraph's copy of that catalog, which polls CISA's feed every 5 minutes. Each kev row gives cve_id, kev_added_date (CISA's dateAdded), kev_due_date, kev_vendor, kev_product, kev_vuln_name and kev_ransomware (known ransomware-campaign use), EchelonGraph's severity, cvss_v3_score, epss_score, epss_percentile and eg_kev_tier for the CVE, and our_first_seen_kev, when EchelonGraph's poller first recorded the CVE entering the catalog (null where no such record exists). Filter by since and until (YYYY-MM-DD, inclusive, on kev_added_date), ransomware, and vendor (an exact, case-insensitive match on kev_vendor); page with limit (1 to 200, default 50) and cursor, passing back the previous page's next_cursor with the same filters. total counts the CVEs matching the filters; kev_listed_total counts every CVE EchelonGraph holds as KEV-listed, and catalog.catalog_count is CISA's own count in the catalog last fetched, so a gap between the two is entries not yet in EchelonGraph's CVE table, which no page returns. CISA's requiredAction, shortDescription and notes are not in these rows: each CVE's own record carries them, verbatim and labelled as CISA's. Its structured result's measured_at is our last successful fetch of CISA's feed (null when the API does not say), coverage counts the CISA KEV catalog (total, returned, kev_listed_total, catalog_count, limit, has_more) and freshness gives last_successful_fetch_at, catalog_version and date_released. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, each row keeps cve_id, kev_added_date, kev_vendor and kev_ransomware at least, or rows are left out, and next_cursor still continues after the page's last row, not the text's.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| limit | No | page size (default 50, max 200) | |
| since | No | earliest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it, with the time and offset dropped; anything else is refused) | |
| until | No | latest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it, with the time and offset dropped; anything else is refused) | |
| cursor | No | next_cursor from the previous page | |
| vendor | No | CISA vendorProject, an exact case-insensitive match, e.g. 'Microsoft' | |
| ransomware | No | true: only CVEs with known ransomware-campaign use; false: only those without |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, openWorldHint), and the description adds substantial context beyond that: the 5-minute polling cadence, measured_at and freshness semantics, the kev_listed_total vs catalog.catalog_count gap explanation, exact-match vs case-insensitive matching, and detailed truncation behavior (TEXT CUT/DATA CUT at 30,000 chars) with a note on where the cut data is readable. That is a rich behavioral contract not derivable from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded in the first sentence, but the remainder is a dense single-block run with long clauses, and the DATA CUT/TEXT CUT explanation duplicates the `full` parameter's schema description almost verbatim. All facts are relevant, but the reader must work hard to extract them, so it is more complete than concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-param, open-world read tool with a rich output schema and full annotations, the description is complete: it explains the data model, the gap between EchelonGraph's count and CISA's own count, cursor continuation even under truncation, and freshness/measured_at semantics. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description still adds value: since/until are inclusive and applied to kev_added_date, vendor is 'an exact, case-insensitive match on kev_vendor', and cursor must be passed back 'with the same filters', which is a real constraint not obvious from the schema. It also clarifies total vs kev_listed_total vs catalog_count, though these are outputs rather than input params.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb+resource+ordering+source: 'The CVEs CISA has added to its Known Exploited Vulnerabilities (KEV) catalog, newest first, from EchelonGraph's copy... polls CISA's feed every 5 minutes.' This is clearly distinguishable from siblings like search_cves, get_cve and exposure_radar, which an agent can discriminate without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies the usage context (browsing recent additions, filterable by date/ransomware/vendor) and gives one explicit routing hint: requiredAction, shortDescription and notes are 'not in these rows: each CVE's own record carries them', pushing the agent to get_cve. It stops short of naming when to prefer cve_exposure or exposure_radar, so it lacks a full when/when-not/alternatives matrix.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_manifestCheck a lockfile against the advisory corpusARead-onlyIdempotentInspect
Check a project's lockfile or pinned manifest against EchelonGraph's advisory corpus, one verdict per dependency. Pass files: 1 to 20 of filename and content, up to 5,000,000 characters in all; the filename or format gives the format. Read: requirements.txt (== and === pins only), go.mod (require, after replace and exclude), package-lock.json and npm-shrinkwrap.json (v1-v3), Cargo.lock, Gemfile.lock, composer.lock, poetry.lock and gradle.lockfile. package.json, pyproject.toml, Pipfile, Gemfile, Cargo.toml, composer.json and build.gradle hold ranges and are refused, naming the lockfile; go.sum is refused: it lists versions the build does not select. The server reads the files into purls; only the purls are sent to the API, in POST bodies of at most 200, never in a URL; filenames and file contents are not sent on. Run from npm, this server is on your machine; over the hosted endpoint (mcp.echelongraph.io) it is EchelonGraph's, and the files are the request body, up to 6 MiB. data.results holds a row per distinct purl, with verdict (affected, not_affected, undetermined or not_assessed), not_assessed_reason, cve_ids and matched_via; each match carries kev_listed, epss_score and fixed_in or null with fixed_in_reason. not_affected is the only clean verdict. data.not_checked lists each entry not sent (file, line, reason); not_checked entries are not clean. At most 2,000 distinct purls and 50 seconds a call. The API allows 1,200 components a minute per caller; on a 429 it waits out Retry-After within that; a later batch cut off, refused or failed ends the call, the rest in data.not_sent_purls, unchecked, not clean. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, each row keeps index, purl, verdict, not_assessed_reason and cve_ids at least; not_checked its first 20.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| files | Yes | 1 to 20 files, up to 5,000,000 characters of content in all; read by this MCP server into purls, and only the purls are sent to the API; over the hosted endpoint (mcp.echelongraph.io) the files are the request body |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses privacy behavior (only purls leave the server, files are never sent in URLs), transport differences between local npm and hosted endpoint, payload and runtime limits, rate-limit handling, partial-batch behavior, and output truncation semantics. It also explains which verdicts count as clean and that not_checked and not_sent_purls are not clean, giving the agent unusually rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded and information-dense, with little outright waste, but it is one very long paragraph bundling input formats, privacy, rate limits, output truncation and partial-batch behavior. It would be easier for an agent to parse if structured into shorter blocks, so it is adequate but not concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of manifest scanning, the schema richness and the existence of an output schema, the description covers what an agent needs: valid inputs, refused inputs, privacy boundaries, limits, verdict semantics, failure modes and truncation. Nothing critical about calling this tool correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3, but the description adds meaningful parameter context: accepted and refused lockfile formats, filename-versus-format precedence, total content limits, and the consequence that files are converted into purls before the API call. The `full` parameter is mostly restated from the schema, but the `files` parameter gains substantially more operational meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource: checking a project's lockfile or pinned manifest against EchelonGraph's advisory corpus, returning one verdict per dependency. The input scope of lockfiles and pinned manifests implicitly distinguishes it from SBOM- or package-oriented siblings, and the purpose is immediately clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong input-validity guidance, listing accepted formats and explaining why package.json, pyproject.toml, go.sum and similar files are refused. It does not explicitly say when to use this tool instead of siblings such as check_sbom or check_affected, so selection guidance is only implied by the accepted file types.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_cvesSearch CVEsARead-onlyIdempotentInspect
Search/list CVEs from EchelonGraph's CVE feed (NVD + MITRE-CNA pre-NVD + CISA-KEV + EPSS + GitHub GHSA, each polled on a schedule). Filter by severity, minimum CVSS, free text, and sort; page with limit and offset. Returns cves, each with cve_id, severity, cvss_v3_score, echelongraph_score and score_assessed (whether EchelonGraph has scored it), epss_score and kev_listed where the record has them, and the list's total, total_counted (false: total is not a count), total_is_lower_bound (true: at least total), search_relaxed, limit and offset. echelongraph_score, echelongraph_severity and echelongraph_risk are EchelonGraph's score only when score_assessed is true. With score_assessed false the CVE is NOT YET SCORED, not scored 0: any of those three it carries (0, NONE, 0) is a placeholder, not a rating, and does not mean the CVE is harmless; score_unassessed_reason says why, and the note labels each such CVE NOT YET SCORED. An answer with no score_assessed (an API older than that field) does not say whether the CVE was scored, the note says so, and a 0 there is not a rating either. patch_available is true when EchelonGraph holds, or once held, fix evidence for the CVE; patch_evidence is what it holds now, strongest first. patch_available false means no fix evidence is on record, which is not a finding that no fix exists. freshness is null: this answer carries no poll-completion time. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, each row keeps at least the fields named above and the first 200 characters of its description (100 on a page too long for that), or rows are left out and the note gives the offset to call next.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| sort | No | sort order (default: published) | |
| limit | No | page size (default 20, max 50) | |
| offset | No | rows to skip (default 0) | |
| search | No | free-text search (product, vendor, or keyword, e.g. 'tomcat') | |
| min_cvss | No | minimum CVSS score | |
| severity | No | filter to one severity |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Well beyond the readOnly/idempotent annotations, it discloses the placeholder semantics of score_assessed=false (0/NONE is not a rating, do not read as harmless), legacy responses lacking score_assessed, patch_available meaning 'evidence on record, not proof no fix exists', freshness=null, and the exact 30,000-character truncation behavior with recovery offsets. These are non-obvious traps that would otherwise cause wrong conclusions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first clause, which is good, but the body becomes a dense run-on of parenthetical caveats with no line breaks or grouping, and several clauses (the 'TEXT CUT' / 'DATA CUT' restatement, the description-field truncation lengths) are repeated nearly verbatim in the schema. High information density, but poor scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description adds the critical interpretive layer the schema cannot express (unassessed scores, patch evidence, truncation, total_is_lower_bound), which is what an agent needs to avoid misreporting results. Only gap is that it never says how it relates to get_cve/cve_summary for single-CVE or summary use cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents full, sort, limit, offset, search, min_cvss and severity. The description restates the filter names and the page/sort intent without adding syntax or interpretation the schema lacks; the one added nuance, full:true versus CUT output, is already spelled out in the schema entry for full.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search/list CVEs') and enumerates the underlying feeds (NVD, MITRE-CNA pre-NVD, CISA-KEV, EPSS, GHSA), so the agent knows what corpus it is querying. It never names a sibling (e.g. get_cve for a single CVE), so differentiation from the 15 other CVE tools is left implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Search/list' implies this is the bulk/discovery path versus a single-record lookup, but no explicit when-to-use or when-not-to-use statement is given, and no sibling is named as the alternative. The agent must infer routing from the name and the filter list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_vendor_advisoriesSearch vendor advisoriesARead-onlyIdempotentInspect
Search or list vendor-published advisories, newest first. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, IDs and affected_products (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word). Filter by vendor (slug), severity band and whether the advisory names any CVE ID. Advisories their vendor withdrew are left out. Returns advisories, each with vendor, vendor_advisory_id, title, severity, cvss_v3_score, cve_ids, summary and affected_products where present, and total, total_capped, limit, offset, search_applied and search_match. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000. Each advisory also carries rejected_cve_ids: the CVE IDs it names whose CVE record was rejected (withdrawn) by its numbering authority, which are not active vulnerabilities. The query is sent in a request header, never in the URL. coverage repeats those beside returned, and gives vendor_windows, each vendor's window in what EchelonGraph holds: vendor, advisories, earliest_vendor_published_at, latest_vendor_published_at, held_since (where that window begins) and history_backfill (in_progress or not_started: older advisories not all held yet). An advisory published before its vendor's held_since may not be held, so no advisory from a vendor is not a finding that it published none. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, each row keeps vendor, vendor_advisory_id, title, severity and cve_ids at least, its strings and lists shortened, or rows are left out and the note gives the offset to call next.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| limit | No | page size (default 20, max 50) | |
| query | No | free text, at most 100 bytes: a product, an advisory ID, a CVE ID or a keyword, e.g. 'exchange server'; 1 or 2 characters match whole words only | |
| offset | No | rows to skip (default 0) | |
| vendor | No | a vendor slug, e.g. microsoft, redhat, github | |
| has_cve | No | true: only advisories naming a CVE; false: only those naming none | |
| severity | No | one severity band |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), and the description still adds substantial non-obvious behavior: withdrawn advisories are excluded, matches are capped at 1,000 with total_capped meaning '1,000 or more', rejected_cve_ids must not be read as active vulnerabilities, and held_since means absence of a vendor's advisories is not evidence it published none. It also documents the TEXT CUT / DATA CUT truncation path and the full:true escape hatch.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, but the body is a dense wall of clauses that interleaves search semantics, return fields, coverage semantics, and two separate truncation regimes in one run-on block. The truncation rules are also largely restated in the 'full' parameter description, so some content does not fully earn its place here.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter, zero-required search tool with an output schema, the definition is complete: it covers matching rules, filters, pagination, the match cap, the coverage/held_since caveat, and exactly what happens when output exceeds 30,000 characters. An agent can call it correctly and interpret the response without further guidance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description still earns above that by explaining matching semantics the schema does not spell out — substring match case-insensitively across title, description, vendor, IDs and affected_products for queries of 3+ characters, whole-word matching for 1-2 characters, and the meaning of search_match in the response. The vendor, severity and has_cve filters are described only as bands/slugs, which the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource plus ordering: 'Search or list vendor-published advisories, newest first.' That is unambiguous. It never names a sibling (get_vendor_advisory for a single record, vendor_advisories_for_cve for the CVE-driven lookup), so an agent must infer sibling routing from the names alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the filter set (vendor, severity, has_cve, query) tells the agent what this tool is for, and 'newest first' plus limit/offset signals paging. There is no explicit when-to-use/when-not language and no mention of the alternatives in the sibling list, so selection against get_vendor_advisory or vendor_advisories_for_cve is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vendor_advisories_for_cveVendor advisories for one CVEARead-onlyIdempotentInspect
The vendor-published advisories that name one CVE, newest first, at most 20: for each, vendor, vendor_display_name, vendor_advisory_id, title, severity and cvss_v3_score where the vendor gives them. Covers the vendor feeds EchelonGraph polls, for example Microsoft MSRC, Red Hat, Cisco, Palo Alto Networks and GitHub GHSA; an empty answer means none of the advisories EchelonGraph holds names the CVE, not that no vendor published one. Each advisory carries vendor_published_at (the vendor's date), our_first_seen_at (when EchelonGraph first recorded it) and withdrawn (true: the vendor rescinded it). Each advisory also carries rejected_cve_ids: the CVE IDs it names whose CVE record was rejected (withdrawn) by its numbering authority, which are not active vulnerabilities. The answer's cve_rejected is true when the CVE record of the CVE asked for was rejected. Each row has remediation_kinds and remediation_state (not_parsed is not none). coverage gives returned, cap, at_cap (true: there may be more) and cve_year; vendor_windows, each vendor's held window: vendor, advisories, earliest_vendor_published_at, latest_vendor_published_at, held_since (where that window begins) and history_backfill (in_progress or not_started: older advisories not all held yet); and vendors_not_fully_held, the vendors absent from the answer of which EchelonGraph holds none, whose held_since is after 1 January of cve_year or not known, or whose history is still being read, which the note names. An advisory published before its vendor's held_since may not be held, so no advisory from a vendor is not a finding that it published none. Past 30,000 characters of JSON, the first text block holds data cut to fit, and the note says what the cut leaves out and where to read it (TEXT CUT); so is structured data (DATA CUT), unless full: true. Cut, each row keeps vendor, vendor_advisory_id, title, severity and cve_ids at least, its strings and lists shortened.
| Name | Required | Description | Default |
|---|---|---|---|
| full | No | true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap. | |
| cve_id | Yes | a CVE ID, e.g. CVE-2024-21412 |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the readOnly/openWorld/idempotent annotations: it discloses the 20-row cap, the 30,000-character JSON cut with TEXT CUT/DATA CUT markers and the full:true escape hatch, the meaning of withdrawn and rejected_cve_ids, and the vendor coverage windows including history_backfill states. These are exactly the failure modes an agent needs to know before trusting an empty or truncated result.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, but the body is roughly 250 words of run-on semicolon-chained clauses, much of it enumerating return fields (vendor_display_name, severity, cvss_v3_score, coverage, vendor_windows) that an output schema already documents. A reader has to parse a paragraph to extract the two or three caveats that actually change behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an open-world, coverage-limited tool with an output schema, the description covers everything an agent needs: scope, cap, truncation protocol, empty-result interpretation, and the temporal-coverage caveats that could otherwise be misread as negative findings. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns an extra point by restating the practical consequence of `full` — the default cut versus whole structured data — in the body rather than relying on the schema's long parameter note. It adds nothing for cve_id, which is self-evident.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb+resource+scope: 'The vendor-published advisories that name one CVE, newest first, at most 20.' That scoping key (one CVE, capped, sorted) is enough to distinguish it from get_vendor_advisory and search_vendor_advisories in practice, but those siblings are never named, so the differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Strong on interpreting results — it explicitly warns that an empty answer means EchelonGraph holds no matching advisory 'not that no vendor published one', and repeats the caveat for the held_since window. It gives no guidance on when to pick this over cve_summary, cve_intel, search_vendor_advisories or get_vendor_advisory despite five closely related siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
16 tool updates
- Changed
check_affected1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", - "type": [ - "boolean", - "null" - ] - }, - "candidate_count": { - "type": [ - "number", - "null" - ] - }, - "candidates_capped": { - "description": "true: not every candidate CVE was loaded.", - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "description": "true: the match list stopped at its cap.", - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "degraded": { - "description": "true: the lookup ran out of time.", - "type": [ - "boolean", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "ecosystem_recognised": { - "type": [ - "boolean", - "null" - ] - }, - "excluded": {}, - "excluded_count": { - "description": "CPE candidates suppressed by the vendor or platform gate.", - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "description": "Which lookup path answered.", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_vendor": { - "description": "The vendor NVD's CPE asserts for this match.", - "type": [ - "string", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "effective_score": { - "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", - "type": [ - "number", - "null" - ] - }, - "effective_severity": { - "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "EPSS exploitation probability, 0 to 1.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "Registry match: the lowest version above this one that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds this version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which. Absent on a CPE match.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the interval that holds this version: the overlapping intervals of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Registry match: the advisory interval that holds this version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Listed in CISA-KEV: known to be exploited.", - "type": [ - "boolean", - "null" - ] - }, - "match_confidence": { - "type": [ - "number", - "null" - ] - }, - "match_method": { - "type": [ - "string", - "null" - ] - }, - "match_reason": { - "type": [ - "string", - "null" - ] - }, - "matched_criteria": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "description": "CISA-KEV records known use in ransomware campaigns.", - "type": [ - "boolean", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", - "type": [ - "boolean", - "null" - ] - }, - "score_unassessed_reason": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", - "type": [ - "string", - "null" - ] - }, - "vendor_severity": { - "type": [ - "string", - "null" - ] - }, - "vendor_unknown": { - "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", - "type": [ - "boolean", - "null" - ] - }, - "version_evidence": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "description": "Advisories decided as not affecting this version.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - }, - "product_named_count": { - "type": [ - "number", - "null" - ] - }, - "undecidable_excluded_count": { - "type": [ - "number", - "null" - ] - }, - "undecided_candidate_count": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "detail": { - "type": [ - "string", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_count": { - "type": [ - "number", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "anyOf": [ + { + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Which lookup path this call asked for." + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", + "type": [ + "boolean", + "null" + ] + }, + "candidate_count": { + "type": [ + "number", + "null" + ] + }, + "candidates_capped": { + "description": "true: not every candidate CVE was loaded.", + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "description": "true: the match list stopped at its cap.", + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "degraded": { + "description": "true: the lookup ran out of time.", + "type": [ + "boolean", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "excluded": {}, + "excluded_count": { + "description": "CPE candidates suppressed by the vendor or platform gate.", + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "description": "Which lookup path answered.", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cpe_vendor": { + "description": "The vendor NVD's CPE asserts for this match.", + "type": [ + "string", + "null" + ] + }, + "cpe_version_end_excluding": { + "description": "CPE match: NVD's versionEndExcluding for the range that matched, the first version that range no longer holds. Not a fix, and never fixed_in: another range of the same CVE, or a vendor backport, can sit past it. Absent on a registry match, and where the range sets no such end.", + "type": [ + "string", + "null" + ] + }, + "cpe_version_end_including": { + "description": "CPE match: NVD's versionEndIncluding for the range that matched, the last version that range holds. Not a fix, and never fixed_in. Absent on a registry match, and where the range sets no such end.", + "type": [ + "string", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "effective_score": { + "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", + "type": [ + "number", + "null" + ] + }, + "effective_severity": { + "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "EPSS exploitation probability, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "Registry match: the lowest version above this one that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds this version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which. Absent on a CPE match.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds this version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Registry match: the advisory interval that holds this version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Listed in CISA-KEV: known to be exploited.", + "type": [ + "boolean", + "null" + ] + }, + "match_confidence": { + "type": [ + "number", + "null" + ] + }, + "match_method": { + "type": [ + "string", + "null" + ] + }, + "match_reason": { + "type": [ + "string", + "null" + ] + }, + "matched_criteria": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "description": "CISA-KEV records known use in ransomware campaigns.", + "type": [ + "boolean", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", + "type": [ + "boolean", + "null" + ] + }, + "score_unassessed_reason": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", + "type": [ + "string", + "null" + ] + }, + "vendor_severity": { + "type": [ + "string", + "null" + ] + }, + "vendor_unknown": { + "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", + "type": [ + "boolean", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "description": "CVEs decided as not affecting this version: on the registry path one per CVE, however many of its advisory records are stored (advisories_considered counts those).", + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + }, + "product_named_count": { + "type": [ + "number", + "null" + ] + }, + "undecidable_excluded_count": { + "type": [ + "number", + "null" + ] + }, + "undecided_candidate_count": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "detail": { + "type": [ + "string", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_count": { + "type": [ + "number", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
check_sbom4 fields changed- changed
Input schema / properties / purls / descriptionPrevious value: -"package URLs to check, e.g. pkg:npm/lodash@4.17.20 or pkg:deb/debian/openssl@3.0.11-1~deb12u1?distro=debian-12 (up to 2,000 distinct, sent in batches of 200)"New value: +"package URLs to check, e.g. pkg:npm/lodash@4.17.20 or pkg:deb/debian/openssl@3.0.11-1~deb12u1?distro=debian-12 (up to 2,000 distinct, sent in batches of 200), in a list of at most 10,000 entries, repeats included" - added
Input schema / properties / purls / maxItemsAdded value: +10000 - changed
Input schema / properties / sbom / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "additionalProperties": {}, - "propertyNames": { - "type": "string" - }, - "type": "object" - } -]New value: +[ + { + "type": "string" + }, + { + "additionalProperties": {}, + "maxProperties": 64, + "propertyNames": { + "type": "string" + }, + "type": "object" + } +] - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matched_package": { - "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", - "type": [ - "string", - "null" - ] - }, - "matched_version_from": { - "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", - "type": [ - "string", - "null" - ] - }, - "matched_via": { - "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", - "type": [ - "boolean", - "null" - ] - }, - "match_reason": { - "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "matches_truncated": { - "additionalProperties": false, - "description": "Present only on a row whose matches the structured result's cut (DATA CUT) shortened or left out: total, the row's matches in the answer; returned, the ones data keeps (its first, highest effective_score first); and, while they fit, of all its matches, the CVE IDs KEV-listed (kev_listed_cve_ids) or used in ransomware (ransomware_cve_ids), and the distinct fixed_in versions (fixed_in_versions). The same call with full: true returns every match.", - "properties": { - "fixed_in_versions": { - "items": { - "type": "string" - }, - "type": "array" - }, - "kev_listed_cve_ids": { - "items": { - "type": "string" - }, - "type": "array" - }, - "ransomware_cve_ids": { - "items": { - "type": "string" - }, - "type": "array" - }, - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "purl_name": { - "description": "Upstream rows: the purl's own (binary) package name, not looked up.", - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "anyOf": [ + { + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document." + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matched_package": { + "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", + "type": [ + "string", + "null" + ] + }, + "matched_version_from": { + "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", + "type": [ + "string", + "null" + ] + }, + "matched_via": { + "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", + "type": [ + "boolean", + "null" + ] + }, + "match_reason": { + "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "matches_truncated": { + "additionalProperties": {}, + "description": "Present only on a row whose matches the structured result's cut (DATA CUT) shortened or left out: total, the row's matches in the answer; returned, the ones data keeps (chosen used in ransomware first, then the other KEV-listed ones, then highest effective_score, and listed in the API's order); and, while they fit, of all its matches, the CVE IDs KEV-listed (kev_listed_cve_ids) or used in ransomware (ransomware_cve_ids), and the distinct fixed_in versions (fixed_in_versions). The same call with full: true returns every match.", + "properties": { + "fixed_in_versions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "kev_listed_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ransomware_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "purl_name": { + "description": "Upstream rows: the purl's own (binary) package name, not looked up.", + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_exposure1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "countries": { - "type": [ - "number", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "exposed_hosts": { - "type": [ - "number", - "null" - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev_catalog_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_seen_in_observations": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "description": "When EchelonGraph last wrote or refreshed a service's row, not when the service was observed and not when its vulnerable version was last confirmed: it is set to the time of the write when a search matches the banner, and again when a re-check finds the port still listed by Shodan InternetDB, without re-reading the banner, so a patched service can stay counted while its port stays open. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "type": [ - "string", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "top_countries": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "country": { - "type": [ - "string", - "null" - ] - }, - "hosts": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "top_products": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "hosts": { - "type": [ - "number", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "tracked": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "exposure_state": { - "anyOf": [ - { - "enum": [ - "exposed", - "measured_zero", - "not_assessed", - "tracking_unknown" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "exposure_state", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "countries": { + "type": [ + "number", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "exposed_hosts": { + "type": [ + "number", + "null" + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev_catalog_listed": { + "description": "The CISA-KEV catalog flag: true when EchelonGraph's CVE record marks the CVE as CISA-KEV-listed. false also where EchelonGraph holds no record of the CVE, so a false says what EchelonGraph's data holds, not that the CVE is outside CISA's catalog.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed": { + "description": "Deprecated: the same value as kev_seen_in_observations, kept for compatibility. It is the radar's observation flag, not CISA-KEV catalog status: false for a CISA-KEV CVE the radar holds no service for (CVE-2024-3400 on 2026-10-10: kev_listed false, kev_catalog_listed true). kev_catalog_listed is the catalog flag.", + "type": [ + "boolean", + "null" + ] + }, + "kev_seen_in_observations": { + "description": "true: at least one of the radar's service rows for the CVE carries the CISA-KEV flag copied in when the radar matched that service; false where none does, as for a CVE the radar holds no service for. It is the radar's observation flag, not CISA-KEV catalog status.", + "type": [ + "boolean", + "null" + ] + }, + "last_seen": { + "description": "When EchelonGraph last wrote or refreshed a service's row, not when the service was observed and not when its vulnerable version was last confirmed: it is set to the time of the write when a search matches the banner, and again when a re-check finds the port still listed by Shodan InternetDB, without re-reading the banner, so a patched service can stay counted while its port stays open. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "type": [ + "string", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "top_countries": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "country": { + "type": [ + "string", + "null" + ] + }, + "hosts": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "top_products": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "hosts": { + "type": [ + "number", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "tracked": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "exposure_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "exposed", + "measured_zero", + "not_assessed", + "tracking_unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "exposure_state", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_intel1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "affected_packages": { - "items": { - "additionalProperties": {}, - "properties": { - "dependents_count": { - "type": [ - "number", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - }, - "fixed": { - "description": "The range's fix: the first version past it. null where no fix is on record.", - "type": [ - "string", - "null" - ] - }, - "introduced": { - "description": "The range's lower bound, inclusive; \"0\" is the first version.", - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", - "type": [ - "string", - "null" - ] - }, - "source": { - "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; its fix is that range's fixed, or, while another range still holds that, the other range's fixed (none past a range without one); a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." - }, - "fixed_version": { - "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "version_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cve_id": { - "type": "string" - }, - "cwes": { - "items": { - "additionalProperties": {}, - "properties": { - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits": { - "items": { - "additionalProperties": {}, - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "eg_first_seen_at": { - "description": "When EchelonGraph first recorded the reference, as a UTC timestamp: a date of EchelonGraph's, not the source's.", - "type": "string" - }, - "first_seen_at": { - "description": "Deprecated: the same value as source_published_at, null when that is.", - "type": [ - "string", - "null" - ] - }, - "kind": { - "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", - "type": [ - "string", - "null" - ] - }, - "source_name": { - "type": [ - "string", - "null" - ] - }, - "source_published_at": { - "description": "The source's own date for the reference (Exploit-DB's date_published, a GitHub proof-of-concept repository's created_at, or the first commit of a nuclei template or Metasploit module where EchelonGraph derived it from the source's git history); null where the source gives none, and EchelonGraph supplies no stand-in date.", - "type": [ - "string", - "null" - ] - }, - "source_url": { - "type": [ - "string", - "null" - ] - }, - "verified_status": { - "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits_by_kind": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_by_status": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_capped": { - "description": "true: exploits lists fewer references than exploits_total.", - "type": "boolean" - }, - "exploits_total": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Every exploit reference on record for the CVE, not only those listed in exploits." - }, - "fixed_versions": { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_version": { - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "vulnerable_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline": { - "items": { - "additionalProperties": {}, - "properties": { - "enriched_at": { - "type": [ - "string", - "null" - ] - }, - "enrichment_kind": { - "type": [ - "string", - "null" - ] - }, - "fields_changed": {}, - "score_delta": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline_count_30d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_count_7d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_total": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "cve_id" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "affected_packages": { + "additionalProperties": {}, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": {}, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": {}, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": {}, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "affected_packages": { + "items": { + "additionalProperties": {}, + "properties": { + "dependents_count": { + "type": [ + "number", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + }, + "fixed": { + "description": "The range's fix: the first version past it. null where no fix is on record.", + "type": [ + "string", + "null" + ] + }, + "introduced": { + "description": "The range's lower bound, inclusive; \"0\" is the first version.", + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; its fix is that range's fixed, or, while another range still holds that, the other range's fixed (none past a range without one); a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "version_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cve_id": { + "type": "string" + }, + "cwes": { + "items": { + "additionalProperties": {}, + "properties": { + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits": { + "items": { + "additionalProperties": {}, + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "eg_first_seen_at": { + "description": "When EchelonGraph first recorded the reference, as a UTC timestamp: a date of EchelonGraph's, not the source's.", + "type": "string" + }, + "first_seen_at": { + "description": "Deprecated: the same value as source_published_at, null when that is.", + "type": [ + "string", + "null" + ] + }, + "kind": { + "description": "Exploit code: metasploit, exploit_db, github_poc or vendor_poc. A detection check, which checks whether a system is affected and is not necessarily exploit code: nuclei_template (a Nuclei detection template) or github_checker (a GitHub repository named or described as a checker or scanner). A kind not named here is one this server does not classify: the note counts it as neither.", + "type": [ + "string", + "null" + ] + }, + "source_name": { + "type": [ + "string", + "null" + ] + }, + "source_published_at": { + "description": "The source's own date for the reference (Exploit-DB's date_published, a GitHub proof-of-concept repository's created_at, or the first commit of a nuclei template or Metasploit module where EchelonGraph derived it from the source's git history); null where the source gives none, and EchelonGraph supplies no stand-in date.", + "type": [ + "string", + "null" + ] + }, + "source_url": { + "type": [ + "string", + "null" + ] + }, + "verified_status": { + "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept and checker repositories, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits_by_kind": { + "additionalProperties": { + "type": "number" + }, + "description": "Every reference on record counted by kind (the values of each exploit's kind), past the 10 listed; the counts under nuclei_template and github_checker are detection checks, not exploit code, those under metasploit, exploit_db, github_poc and vendor_poc are exploit code, and those under any other kind are of a kind this server does not classify, counted as neither.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_by_status": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_capped": { + "description": "true: exploits lists fewer references than exploits_total.", + "type": "boolean" + }, + "exploits_total": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Every exploit reference on record for the CVE, not only those listed in exploits." + }, + "fixed_versions": { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_version": { + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "vulnerable_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline": { + "items": { + "additionalProperties": {}, + "properties": { + "enriched_at": { + "type": [ + "string", + "null" + ] + }, + "enrichment_kind": { + "type": [ + "string", + "null" + ] + }, + "fields_changed": {}, + "score_delta": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline_count_30d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_count_7d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "cve_id" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_remediation1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "installed_asked": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "ecosystem": { - "type": "string" - }, - "package": { - "type": "string" - }, - "version": { - "type": "string" - } - }, - "required": [ - "ecosystem", - "package", - "version" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The installed version this call sent (in request headers), as given; null when none." - }, - "item_text_cap": { - "type": [ - "number", - "null" - ] - }, - "items_per_advisory_cap": { - "type": [ - "number", - "null" - ] - }, - "parsed_vendors": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors whose remediation EchelonGraph parses." - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API could not read (its failed_sections); null when the answer does not say." - }, - "sections_relayed": { - "items": { - "type": "string" - }, - "type": "array" - }, - "vendor_advisory_limit": { - "type": [ - "number", - "null" - ] - }, - "vendors_not_parsed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors in this answer whose remediation EchelonGraph does not parse." - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "parsed_vendors", - "vendors_not_parsed", - "vendor_advisory_limit", - "item_text_cap", - "items_per_advisory_cap", - "installed_asked" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cisa": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "due_date": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "required_action": { - "description": "CISA's requiredAction, verbatim. CISA's required_action is directed at US federal civilian agencies (under BOD 26-04, which replaced BOD 22-01 on 10 June 2026) and is not EchelonGraph's advice.", - "type": [ - "string", - "null" - ] - }, - "short_description": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "coverage": {}, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "failed_sections": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fix_references": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "source": { - "type": [ - "string", - "null" - ] - }, - "tags": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fix_status": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "basis": { - "type": [ - "string", - "null" - ] - }, - "described_by": { - "type": [ - "string", - "null" - ] - }, - "listed_in_patch_table": { - "type": [ - "boolean", - "null" - ] - }, - "solution_by": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cna": { - "type": [ - "string", - "null" - ] - }, - "section": { - "type": [ - "string", - "null" - ] - }, - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "available", - "fix_referenced", - "fix_merged", - "none_confirmed", - "unknown" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "stated_in_record": { - "type": [ - "boolean", - "null" - ] - }, - "unread_inputs": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "vendor_released": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "description": "The range's last affected version, where no fix is on record; never a fix.", - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fixed_branches_truncated": { - "additionalProperties": false, - "description": "Present only where the structured result's cut (DATA CUT) kept this package's first ranges, not all: total, its ranges in the answer; returned, the ones data keeps. The same call with full: true returns every range.", - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "fixed_version": { - "description": "One range's fix, kept for compatibility; not the fix for every affected range.", - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fixed_in": { - "description": "With an installed version: the first version above it that no affected range on record holds, always above it, as the advisory states it: the fixed bound of the range holding it, moved past any overlapping range that still holds that bound (fixed_in_detail then names it). null when no range on record holds it, no fix is on record past the ranges holding it, or the version was not assessed, with fixed_in_reason saying which. Absent when no installed version was asked.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the range holding the installed version: the overlapping ranges of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "installed": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "description": "The ecosystem asked for, in its canonical OSV spelling.", - "type": [ - "string", - "null" - ] - }, - "ecosystem_recognised": { - "type": [ - "boolean", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The affected range holding the version (fixed is exclusive, last_affected inclusive); absent when none holds it." - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "verdict": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "affected", - "not_affected", - "undetermined", - "not_assessed" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "affected (a range on record holds the version), not_affected (no range on record holds it), undetermined (a range could not be decided at it) or not_assessed (the record names no such package for this CVE, or the lookup did not run)." - }, - "version": { - "type": [ - "string", - "null" - ] - }, - "version_evidence": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The installed version asked for, as the API read it from the request headers, and its verdict against this CVE; absent when none was asked." - }, - "not_assessed_reason": { - "type": [ - "string", - "null" - ] - }, - "patches": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "state": { - "description": "assessed, or not_assessed for a CVE record rejected by its numbering authority.", - "type": [ - "string", - "null" - ] - }, - "vendor_remediations": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "items": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "fixed_build": { - "description": "MSRC's FixedBuild; null elsewhere.", - "type": [ - "string", - "null" - ] - }, - "kind": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "The vendor's own category: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other." - }, - "product_count": { - "type": [ - "number", - "null" - ] - }, - "product_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendor's own product identifiers the item applies to, the first 16." - }, - "source_category": { - "description": "The vendor's own name for the category (CSAF vendor_fix, MSRC Vendor Fix, Palo Alto work_around).", - "type": [ - "string", - "null" - ] - }, - "source_subcategory": { - "description": "MSRC's SubType, e.g. Security Update; null elsewhere.", - "type": [ - "string", - "null" - ] - }, - "text": { - "description": "The vendor's text, verbatim but for HTML markup removed, cut at coverage.item_text_cap characters (text_truncated).", - "type": [ - "string", - "null" - ] - }, - "text_chars": { - "description": "The length of the vendor's text in characters.", - "type": [ - "number", - "null" - ] - }, - "text_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "items_total": { - "type": [ - "number", - "null" - ] - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (parsed, and the advisory lists no remediation for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory); withdrawn (the vendor rescinded it)." - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "installed_asked": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "ecosystem": { - "type": "string" - }, - "package": { - "type": "string" - }, - "version": { - "type": "string" - } - }, - "required": [ - "ecosystem", - "package", - "version" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The installed version this call sent (in request headers), as given; null when none." - }, - "item_text_cap": { - "type": [ - "number", - "null" - ] - }, - "items_per_advisory_cap": { - "type": [ - "number", - "null" - ] - }, - "parsed_vendors": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors whose remediation EchelonGraph parses." - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API could not read (its failed_sections); null when the answer does not say." - }, - "sections_relayed": { - "items": { - "type": "string" - }, - "type": "array" - }, - "vendor_advisory_limit": { - "type": [ - "number", - "null" - ] - }, - "vendors_not_parsed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors in this answer whose remediation EchelonGraph does not parse." - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "parsed_vendors", - "vendors_not_parsed", - "vendor_advisory_limit", - "item_text_cap", - "items_per_advisory_cap", - "installed_asked" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "installed_asked": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "ecosystem", + "package", + "version" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version this call sent (in request headers), as given; null when none." + }, + "item_text_cap": { + "type": [ + "number", + "null" + ] + }, + "items_per_advisory_cap": { + "type": [ + "number", + "null" + ] + }, + "parsed_vendors": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors whose remediation EchelonGraph parses." + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API could not read (its failed_sections); null when the answer does not say." + }, + "sections_relayed": { + "items": { + "type": "string" + }, + "type": "array" + }, + "vendor_advisory_limit": { + "type": [ + "number", + "null" + ] + }, + "vendors_not_parsed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors in this answer whose remediation EchelonGraph does not parse." + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "parsed_vendors", + "vendors_not_parsed", + "vendor_advisory_limit", + "item_text_cap", + "items_per_advisory_cap", + "installed_asked" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cisa": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "due_date": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "required_action": { + "description": "CISA's requiredAction, verbatim. CISA's required_action is directed at US federal civilian agencies (under BOD 26-04, which replaced BOD 22-01 on 10 June 2026) and is not EchelonGraph's advice.", + "type": [ + "string", + "null" + ] + }, + "short_description": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "coverage": {}, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "failed_sections": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fix_references": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "source": { + "type": [ + "string", + "null" + ] + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "section": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "vendor_released": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fixed_branches_truncated": { + "additionalProperties": {}, + "description": "Present only where the structured result's cut (DATA CUT) kept this package's first ranges, not all: total, its ranges in the answer; returned, the ones data keeps. The same call with full: true returns every range.", + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fixed_in": { + "description": "With an installed version: the first version above it that no affected range on record holds, always above it, as the advisory states it: the fixed bound of the range holding it, moved past any overlapping range that still holds that bound (fixed_in_detail then names it). null when no range on record holds it, no fix is on record past the ranges holding it, or the version was not assessed, with fixed_in_reason saying which. Absent when no installed version was asked.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the range holding the installed version: the overlapping ranges of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "installed": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "description": "The ecosystem asked for, in its canonical OSV spelling.", + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The affected range holding the version (fixed is exclusive, last_affected inclusive); absent when none holds it." + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "verdict": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "affected", + "not_affected", + "undetermined", + "not_assessed" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "affected (a range on record holds the version), not_affected (no range on record holds it), undetermined (a range could not be decided at it) or not_assessed (the record names no such package for this CVE, or the lookup did not run)." + }, + "version": { + "type": [ + "string", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version asked for, as the API read it from the request headers, and its verdict against this CVE; absent when none was asked." + }, + "not_assessed_reason": { + "type": [ + "string", + "null" + ] + }, + "patches": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "state": { + "description": "assessed, or not_assessed for a CVE record rejected by its numbering authority.", + "type": [ + "string", + "null" + ] + }, + "vendor_remediations": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "items": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "fixed_build": { + "description": "MSRC's FixedBuild; null elsewhere.", + "type": [ + "string", + "null" + ] + }, + "kind": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "The vendor's own category: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other." + }, + "product_count": { + "type": [ + "number", + "null" + ] + }, + "product_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendor's own product identifiers the item applies to, the first 16." + }, + "source_category": { + "description": "The vendor's own name for the category (CSAF vendor_fix, MSRC Vendor Fix, Palo Alto work_around).", + "type": [ + "string", + "null" + ] + }, + "source_subcategory": { + "description": "MSRC's SubType, e.g. Security Update; null elsewhere.", + "type": [ + "string", + "null" + ] + }, + "text": { + "description": "The vendor's text, verbatim but for HTML markup removed, cut at coverage.item_text_cap characters (text_truncated).", + "type": [ + "string", + "null" + ] + }, + "text_chars": { + "description": "The length of the vendor's text in characters.", + "type": [ + "number", + "null" + ] + }, + "text_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "items_total": { + "type": [ + "number", + "null" + ] + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (parsed, and the advisory lists no remediation for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory); withdrawn (the vendor rescinded it)." + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "installed_asked": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "ecosystem": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "ecosystem", + "package", + "version" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version this call sent (in request headers), as given; null when none." + }, + "item_text_cap": { + "type": [ + "number", + "null" + ] + }, + "items_per_advisory_cap": { + "type": [ + "number", + "null" + ] + }, + "parsed_vendors": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors whose remediation EchelonGraph parses." + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API could not read (its failed_sections); null when the answer does not say." + }, + "sections_relayed": { + "items": { + "type": "string" + }, + "type": "array" + }, + "vendor_advisory_limit": { + "type": [ + "number", + "null" + ] + }, + "vendors_not_parsed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors in this answer whose remediation EchelonGraph does not parse." + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "parsed_vendors", + "vendors_not_parsed", + "vendor_advisory_limit", + "item_text_cap", + "items_per_advisory_cap", + "installed_asked" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_summary1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "poller": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cves_ingested": { - "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", - "type": [ - "number", - "null" - ] - }, - "cves_skipped": { - "description": "CVE records this instance's NVD poller skipped since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "http_retries": { - "description": "HTTP retries this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "interval": { - "description": "How often this instance's NVD poller polls.", - "type": [ - "string", - "null" - ] - }, - "last_poll_at": { - "description": "When this instance's NVD poller last polled: never the feed's freshness.", - "type": [ - "string", - "null" - ] - }, - "last_poll_dur_ms": { - "description": "How long that poll took, in milliseconds.", - "type": [ - "number", - "null" - ] - }, - "poll_count": { - "description": "Polls this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "poll_errors": { - "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." - }, - "summary": { - "additionalProperties": {}, - "description": "summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label (v3.x, else v4.0; before NVD's record arrives, or where it gives none, a pre-NVD label from the CVE.org record or a GitHub advisory can stand in): provenance, never EchelonGraph's severity band. summary.nvd_none counts the active CVEs with no Critical, High, Medium or Low label there, CVEs NVD never labelled under CVSS v3 among them, and many of those carry an NVD CVSS v2 score instead: it is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. Whenever summary.nvd_none is above zero the note says what it counts, with its count.", - "properties": { - "critical": { - "type": [ - "number", - "null" - ] - }, - "high": { - "type": [ - "number", - "null" - ] - }, - "last_updated": { - "type": [ - "string", - "null" - ] - }, - "low": { - "type": [ - "number", - "null" - ] - }, - "medium": { - "type": [ - "number", - "null" - ] - }, - "none": { - "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", - "type": [ - "number", - "null" - ] - }, - "nvd_critical": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_high": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_low": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_medium": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_none": { - "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", - "type": [ - "number", - "null" - ] - }, - "rejected": { - "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "unscored": { - "description": "The same count as none, under its own name.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "nvd_poll": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "interval": { + "description": "The poll's configured interval, a Go duration such as 20m0s." + }, + "last_completed_at": { + "description": "When the fleet last completed an NVD poll, in RFC 3339: the end of the last window fetched and stored without an error." + }, + "scope": { + "description": "Whose poll it is: fleet, every API instance's, never the answering instance's alone." + } + }, + "type": "object" + }, + {} + ], + "description": "When the fleet of API instances last completed an NVD poll: last_completed_at (RFC 3339; the end of the last window fetched and stored without an error), scope fleet, and interval, the poll's interval. The answer leaves it out where that time is unknown. freshness.nvd_poll relays it where scope is fleet and last_completed_at is a real RFC 3339 time at most 5 minutes after this server's clock." + }, + "poller": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cves_ingested": { + "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", + "type": [ + "number", + "null" + ] + }, + "cves_skipped": { + "description": "CVE records this instance's NVD poller skipped since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "http_retries": { + "description": "HTTP retries this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "interval": { + "description": "How often this instance's NVD poller polls.", + "type": [ + "string", + "null" + ] + }, + "last_poll_at": { + "description": "When this instance's NVD poller last polled: never the feed's freshness.", + "type": [ + "string", + "null" + ] + }, + "last_poll_dur_ms": { + "description": "How long that poll took, in milliseconds.", + "type": [ + "number", + "null" + ] + }, + "poll_count": { + "description": "Polls this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "poll_errors": { + "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." + }, + "summary": { + "additionalProperties": {}, + "description": "summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label (v3.x, else v4.0; before NVD's record arrives, or where it gives none, a pre-NVD label from the CVE.org record or a GitHub advisory can stand in): provenance, never EchelonGraph's severity band. summary.nvd_none counts the active CVEs with no Critical, High, Medium or Low label there, CVEs NVD never labelled under CVSS v3 among them, and many of those carry an NVD CVSS v2 score instead: it is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. Whenever summary.nvd_none is above zero the note says what it counts, with its count.", + "properties": { + "critical": { + "type": [ + "number", + "null" + ] + }, + "high": { + "type": [ + "number", + "null" + ] + }, + "last_updated": { + "type": [ + "string", + "null" + ] + }, + "low": { + "type": [ + "number", + "null" + ] + }, + "medium": { + "type": [ + "number", + "null" + ] + }, + "none": { + "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", + "type": [ + "number", + "null" + ] + }, + "nvd_critical": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_high": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_low": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_medium": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_none": { + "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", + "type": [ + "number", + "null" + ] + }, + "rejected": { + "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "unscored": { + "description": "The same count as none, under its own name.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "nvd_poll": { + "additionalProperties": {}, + "description": "The fleet's last completed NVD poll, from data.nvd_poll. freshness is null where the answer carries no nvd_poll, or one without such a time.", + "properties": { + "interval": { + "description": "data.nvd_poll.interval as the API sent it, a Go duration such as 20m0s: the interval the NVD poll runs at; null where the answer gives none in that form.", + "type": [ + "string", + "null" + ] + }, + "last_run_at": { + "description": "data.nvd_poll.last_completed_at as the API sent it: the end of the window the fleet's last completed NVD poll stored, whichever API instance ran it; never the answering instance's poller.last_poll_at.", + "type": "string" + }, + "scope": { + "anyOf": [ + { + "const": "fleet", + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Whose poll it is: the fleet's, as data.nvd_poll.scope says." + } + }, + "required": [ + "last_run_at", + "scope", + "interval" + ], + "type": "object" + } + }, + "required": [ + "nvd_poll" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
epss_history1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day the record holds; null when none are listed." - }, - "days_missing": { - "description": "Score dates from first_day to last_day the record does not hold.", - "items": { - "type": "string" - }, - "type": "array" - }, - "days_partial": { - "description": "Score dates held for some CVEs only.", - "items": { - "type": "string" - }, - "type": "array" - }, - "first_day": { - "description": "The earliest FIRST score date the run log lists; null when it lists none.", - "type": [ - "string", - "null" - ] - }, - "last_day": { - "type": [ - "string", - "null" - ] - }, - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "How many of them fall where changes are missing; null when the API did not say." - }, - "points_truncated": { - "type": "boolean" - }, - "series_complete": { - "description": "True only when the API says nothing in the record predates complete_since.", - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "complete_since", - "series_complete", - "points", - "points_before_complete_since", - "points_truncated", - "first_day", - "last_day", - "days_held", - "days_partial", - "days_missing" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when the record holds every change a refresh applied. Between series_starts_at and complete_since changes are missing, so a missing point there does not mean unchanged. Absent from an API older than #2867." - }, - "coverage": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From here on every change a refresh applied is a point; before it changes are missing." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day that a refresh applied completely." - }, - "days_missing": { - "anyOf": [ - { - "items": { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day that no refresh applied." - }, - "days_partial": { - "anyOf": [ - { - "items": { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Score dates whose refreshes all failed part-way: some CVEs hold that day, some do not." - }, - "first_day": { - "anyOf": [ - { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The earliest score date in the run log." - }, - "last_day": { - "anyOf": [ - { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The latest score date in the run log." - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "This CVE's points in the part of the record that misses changes." - }, - "recorded_from": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "series_starts_at: when recording began." - }, - "refresh_runs_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "run_log_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The first logged refresh: score dates before it are not listed, held or missing." - }, - "runs_undated": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ] - }, - "series_complete": { - "description": "True only when nothing in the record predates complete_since.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Which part of the record is complete and which FIRST score dates it holds." - }, - "current": { - "additionalProperties": {}, - "properties": { - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The record's EPSS probability now; null when it holds none.", - "type": [ - "number", - "null" - ] - }, - "epss_updated_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." - } - }, - "type": "object" - }, - "cve_id": { - "type": "string" - }, - "history_rows": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Raw history rows read, before repeated records of one change were collapsed." - }, - "latest_point_matches_current": { - "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", - "type": [ - "boolean", - "null" - ] - }, - "points": { - "description": "Recorded changes, oldest first. Never a daily series.", - "items": { - "additionalProperties": {}, - "properties": { - "at": { - "description": "When EchelonGraph recorded this change.", - "type": "string" - }, - "epss_percentile": { - "description": "Its percentile (0 to 1), null where the record held none.", - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The EPSS probability (0 to 1) from that change on.", - "type": "number" - }, - "score_date": { - "description": "FIRST's score date (YYYY-MM-DD) of the logged refresh that wrote this point; null where no logged refresh covers it.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "at", - "epss_score" - ], - "type": "object" - }, - "type": "array" - }, - "points_truncated": { - "description": "True when only the newest rows were read, so the earliest points are missing.", - "type": [ - "boolean", - "null" - ] - }, - "series_kind": { - "description": "Always change_only: one point per recorded change, none for a day without one.", - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." - } - }, - "required": [ - "cve_id", - "series_kind", - "series_starts_at", - "current", - "points" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day the record holds; null when none are listed." - }, - "days_missing": { - "description": "Score dates from first_day to last_day the record does not hold.", - "items": { - "type": "string" - }, - "type": "array" - }, - "days_partial": { - "description": "Score dates held for some CVEs only.", - "items": { - "type": "string" - }, - "type": "array" - }, - "first_day": { - "description": "The earliest FIRST score date the run log lists; null when it lists none.", - "type": [ - "string", - "null" - ] - }, - "last_day": { - "type": [ - "string", - "null" - ] - }, - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "How many of them fall where changes are missing; null when the API did not say." - }, - "points_truncated": { - "type": "boolean" - }, - "series_complete": { - "description": "True only when the API says nothing in the record predates complete_since.", - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "complete_since", - "series_complete", - "points", - "points_before_complete_since", - "points_truncated", - "first_day", - "last_day", - "days_held", - "days_partial", - "days_missing" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_in_progress": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates a refresh that has not finished is applying (#3143): held for some CVEs so far. A date an earlier refresh failed part-way on is in days_partial too. Null when the API did not say." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only, because their refreshes failed part-way.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "refresh_runs_truncated": { + "description": "True when only the newest refreshes of the run log were read, so the earliest score dates are not listed; null when the API did not say.", + "type": [ + "boolean", + "null" + ] + }, + "runs_undated": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Logged refreshes with no score date (#3143): the days they applied are not counted, so a day in days_missing may be held for the CVEs they changed, and their points carry no score_date. Null when the API did not say." + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "anyOf": [ + { + "enum": [ + "change_only" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing", + "days_in_progress", + "runs_undated", + "refresh_runs_truncated" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when the record holds every change a refresh applied. Between series_starts_at and complete_since changes are missing, so a missing point there does not mean unchanged. Absent from an API older than #2867." + }, + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From here on every change a refresh applied is a point; before it changes are missing." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that a refresh applied completely." + }, + "days_in_progress": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates no refresh completed and one that has not finished is applying: some CVEs hold that day so far. Not counted held or missing; also in days_partial when an earlier refresh of it failed part-way." + }, + "days_missing": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that no refresh applied." + }, + "days_partial": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates no refresh completed and one failed part-way: some CVEs hold that day, some do not. Also in days_in_progress while a retry of it has not finished." + }, + "first_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest score date in the run log." + }, + "last_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The latest score date in the run log." + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "This CVE's points in the part of the record that misses changes." + }, + "recorded_from": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "series_starts_at: when recording began." + }, + "refresh_runs_truncated": { + "description": "True when only the newest refreshes of the run log were read, so the earliest score dates are not listed.", + "type": [ + "boolean", + "null" + ] + }, + "run_log_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The first logged refresh: score dates before it are not listed, held or missing." + }, + "runs_undated": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Logged refreshes with no score date: the days they applied are not counted held, partial or in progress, and their points carry no score_date." + }, + "series_complete": { + "description": "True only when nothing in the record predates complete_since.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Which part of the record is complete and which FIRST score dates it holds." + }, + "current": { + "additionalProperties": {}, + "properties": { + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The record's EPSS probability now; null when it holds none.", + "type": [ + "number", + "null" + ] + }, + "epss_updated_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." + } + }, + "type": "object" + }, + "cve_id": { + "type": "string" + }, + "history_rows": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Raw history rows read, before repeated records of one change were collapsed." + }, + "latest_point_matches_current": { + "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", + "type": [ + "boolean", + "null" + ] + }, + "points": { + "description": "Recorded changes, oldest first. Never a daily series.", + "items": { + "additionalProperties": {}, + "properties": { + "at": { + "description": "When EchelonGraph recorded this change.", + "type": "string" + }, + "epss_percentile": { + "description": "Its percentile (0 to 1), null where the record held none.", + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The EPSS probability (0 to 1) from that change on.", + "type": "number" + }, + "score_date": { + "description": "FIRST's score date (YYYY-MM-DD) of the logged refresh that wrote this point; null where no logged refresh covers it.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "at", + "epss_score" + ], + "type": "object" + }, + "type": "array" + }, + "points_truncated": { + "description": "True when only the newest rows were read, so the earliest points are missing.", + "type": [ + "boolean", + "null" + ] + }, + "series_kind": { + "anyOf": [ + { + "enum": [ + "change_only" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Always change_only: one point per recorded change, none for a day without one." + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." + } + }, + "required": [ + "cve_id", + "series_kind", + "series_starts_at", + "current", + "points" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_in_progress": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates a refresh that has not finished is applying (#3143): held for some CVEs so far. A date an earlier refresh failed part-way on is in days_partial too. Null when the API did not say." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only, because their refreshes failed part-way.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "refresh_runs_truncated": { + "description": "True when only the newest refreshes of the run log were read, so the earliest score dates are not listed; null when the API did not say.", + "type": [ + "boolean", + "null" + ] + }, + "runs_undated": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Logged refreshes with no score date (#3143): the days they applied are not counted, so a day in days_missing may be held for the CVEs they changed, and their points carry no score_date. Null when the API did not say." + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing", + "days_in_progress", + "runs_undated", + "refresh_runs_truncated" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
exposure_radar1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "description": "A field this version cannot label is left out of data and named in the note. Each of the kev_exposure, exposed_databases and leaked_credentials radars also carries generated_at, when the API computed its totals, and, when the API can tell, last_run_at. kev_exposure.last_run_at, exposed_databases.last_run_at and leaked_credentials.last_run_at are timestamps, not counts: each is when that radar last completed a check, a cycle whose reads succeeded, among them a Shodan search (for exposed_databases, or its LeakIX fallback) that answered at least one query, or for leaked_credentials a read of the public GitHub event stream. A cycle that read nothing does not move it, and it is not the time of every record a radar's numbers count, which cover everything still on record, not only what the last check found. A radar whose answer carries no last_run_at has none in the result, and the note says nothing about it. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "exposed_databases": { - "additionalProperties": false, - "description": "exposed_databases: exposed_databases.distinct_hosts counts distinct ip:port services the check confirmed answering without authentication, and exposed_databases.engines the distinct engine types among them; exposed_databases.top_engines and exposed_databases.top_countries rank up to 15 engines and 10 countries by those services. exposed_databases.pii_likely and exposed_databases.pci_likely count services whose schema names (never record values) pass a high-confidence, precision-first gate for personal or payment-card data, so a service outside them is not shown to hold no such data. exposed_databases.window.from and exposed_databases.window.to are timestamps, not counts: when EchelonGraph's check last confirmed the oldest and the newest of the services counted, a span of checks made at different times; with a counted service that has no such time on record there is no window.", - "properties": { - "distinct_hosts": { - "type": "number" - }, - "engines": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "pci_likely": { - "type": "number" - }, - "pii_likely": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_engines": { - "items": { - "additionalProperties": false, - "properties": { - "engine": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "engine", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "description": "kev_exposure: kev_exposure.distinct_hosts counts distinct ip:port services, not machines (a machine answering on two ports counts twice), with at least one CISA-KEV-listed CVE on record, and kev_exposure.ransomware_hosts those with a ransomware-linked one; kev_exposure.kev_cves_exposed and kev_exposure.ransomware_cves count distinct CVEs with at least one such service; kev_exposure.correlations counts service×CVE pairs, not services, so a service with three KEV CVEs counts three times. kev_exposure.top_products, kev_exposure.top_countries and kev_exposure.top_cves rank up to 12 products, 10 countries and 12 CVEs by those services; kev_exposure.top_cves[].cvss_v3_score and kev_exposure.top_cves[].epss_score are the highest CVSS v3 base score and EPSS probability recorded on that CVE's observations. kev_exposure.trend counts service×CVE pairs still on record by the week in which each was first recorded, over 12 weeks, so earlier weeks read low. kev_exposure.newest_kev lists the 15 CVEs that EchelonGraph's CVE records most recently mark as CISA-KEV-listed, each with an exposure_state: exposed, where kev_exposure.newest_kev[].exposed_hosts counts distinct ip:port services on record with it; or not_assessed, where the API's answer holds no measurement for that CVE (its 0 is not one) and no count is relayed, and this answer does not say whether the radar tracks that CVE: tracking is answered per CVE. kev_exposure.newest_kev[].cvss_v3_score and kev_exposure.newest_kev[].epss_score are the CVE record's CVSS v3 base score and EPSS probability. kev_exposure.window.from and kev_exposure.window.to are timestamps, not counts: when Shodan collected the banners of the oldest and the newest of the service×CVE pairs counted, a span of observations made at different times; with a counted pair that has no such time on record there is no window. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "correlations": { - "type": "number" - }, - "distinct_hosts": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "kev_cves_exposed": { - "type": "number" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "newest_kev": { - "items": { - "additionalProperties": false, - "properties": { - "added_date": { - "type": "string" - }, - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "exposed_hosts": { - "type": "number" - }, - "exposure_state": { - "enum": [ - "exposed", - "measured_zero", - "not_assessed" - ], - "type": "string" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - }, - "vuln_name": { - "type": "string" - } - }, - "required": [ - "cve_id", - "exposure_state" - ], - "type": "object" - }, - "type": "array" - }, - "ransomware_cves": { - "type": "number" - }, - "ransomware_hosts": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_cves": { - "items": { - "additionalProperties": false, - "properties": { - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "hosts": { - "type": "number" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - } - }, - "required": [ - "cve_id", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "hosts": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "trend": { - "items": { - "additionalProperties": false, - "properties": { - "new_exposures": { - "type": "number" - }, - "week": { - "type": "string" - } - }, - "required": [ - "week", - "new_exposures" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "description": "leaked_credentials: leaked_credentials.total counts (repository, secret) pairs, not distinct secrets, so one secret in three repositories counts three times; leaked_credentials.distinct_secrets counts each secret once and leaked_credentials.distinct_repos counts repositories; leaked_credentials.top_providers and leaked_credentials.top_types rank up to 15 providers and secret types by those pairs. None is validated: each is a credential-shaped string that passed EchelonGraph's filters, at most structurally checked and never tested against its provider. leaked_credentials.window.from and leaked_credentials.window.to are timestamps, not counts: when EchelonGraph's detector last found the oldest and the newest of the pairs counted.", - "properties": { - "distinct_repos": { - "type": "number" - }, - "distinct_secrets": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_providers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "provider": { - "type": "string" - } - }, - "required": [ - "provider", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_types": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "secret_type": { - "type": "string" - } - }, - "required": [ - "secret_type", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "description": "mcp_servers: counts and timestamps only, no hostname. mcp_servers.total counts hostnames the AI-exposure radar has checked for an MCP server, each once by its latest verdict on record, and not every one is an MCP server; EchelonGraph's own control servers are left out, and mcp_servers.own_controls_excluded counts them; hostnames whose owner opted out of scanning are not checked again while the opt-out stands, so their last verdict is left out too, and mcp_servers.withheld_opted_out counts them. mcp_servers.total is mcp_servers.protected plus mcp_servers.pending_readjudication plus mcp_servers.not_assessed. mcp_servers.protected counts hostnames whose /mcp endpoint asked for credentials and whose OAuth protected-resource metadata validated under RFC 9728; mcp_servers.prm_via divides them by where that document was found: mcp_servers.prm_via.header, mcp_servers.prm_via.wellknown_path and mcp_servers.prm_via.wellknown_root. mcp_servers.pending_readjudication counts verdicts of a rule since replaced, not yet re-checked. mcp_servers.not_assessed counts the rest, whose protection the radar could not assess (not assessed does not mean unprotected), and mcp_servers.not_assessed_by_reason puts each in one bucket. mcp_servers.not_assessed_by_reason.identified_no_challenge holds servers that identified themselves as MCP servers and did not ask for credentials at the handshake. That is normal in MCP: authorization is optional in the spec, and a server can enforce it at tools/call instead, which EchelonGraph never sends, so this bucket is not a finding of exposure. mcp_servers.not_assessed_by_reason.resource_mismatch, mcp_servers.not_assessed_by_reason.cross_origin_pointer, mcp_servers.not_assessed_by_reason.bare_challenge_no_prm, mcp_servers.not_assessed_by_reason.pointer_unreachable, mcp_servers.not_assessed_by_reason.pointer_invalid, mcp_servers.not_assessed_by_reason.no_authorization_servers, mcp_servers.not_assessed_by_reason.wellknown_unreachable and mcp_servers.not_assessed_by_reason.metadata_invalid hold endpoints that asked for credentials but whose RFC 9728 metadata did not validate, by why, so none of them is shown to lack protection; mcp_servers.not_assessed_by_reason.challenge_unadjudicated holds endpoints that asked for credentials before that check existed, not yet re-checked. mcp_servers.not_assessed_by_reason.no_http_answer holds hostnames that gave no HTTP answer, and mcp_servers.not_assessed_by_reason.not_identified_as_mcp hostnames whose HTTP answer identified no MCP server. mcp_servers.era divides every counted hostname by protocol era: mcp_servers.era.legacy; mcp_servers.era.dual, a lower bound; mcp_servers.era.modern, not proven modern-only; mcp_servers.era.unknown; and mcp_servers.era.not_measured, recorded before the era probe and not re-checked since. mcp_servers.transport divides them by transport: mcp_servers.transport.streamable_http, mcp_servers.transport.legacy_sse, mcp_servers.transport.unknown and mcp_servers.transport.not_measured. mcp_servers.window.from and mcp_servers.window.to are when the oldest and the newest of the verdicts counted were last checked. mcp_servers.last_run_at is a timestamp, not a count: when the AI-exposure radar, which checks other AI services too, last completed a check; mcp_servers.enabled is whether one completed within 45 minutes of the answer, and mcp_servers.counted_at is when the API read the counts. A partition whose buckets do not add up to the count it divides is left out and named; an answer that does not say it is the MCP-server counts, or whose mcp_servers.total, mcp_servers.protected, mcp_servers.pending_readjudication and mcp_servers.not_assessed are missing or contradict each other, is a failure.", - "properties": { - "counted_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "era": { - "additionalProperties": false, - "properties": { - "dual": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "legacy": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "modern": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "legacy", - "dual", - "modern", - "unknown", - "not_measured" - ], - "type": "object" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "not_assessed": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_assessed_by_reason": { - "additionalProperties": false, - "properties": { - "bare_challenge_no_prm": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "challenge_unadjudicated": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "cross_origin_pointer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "identified_no_challenge": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "metadata_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_authorization_servers": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_http_answer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_identified_as_mcp": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "resource_mismatch": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "identified_no_challenge", - "resource_mismatch", - "cross_origin_pointer", - "bare_challenge_no_prm", - "pointer_unreachable", - "pointer_invalid", - "no_authorization_servers", - "wellknown_unreachable", - "metadata_invalid", - "challenge_unadjudicated", - "no_http_answer", - "not_identified_as_mcp" - ], - "type": "object" - }, - "own_controls_excluded": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pending_readjudication": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "prm_via": { - "additionalProperties": false, - "properties": { - "header": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_path": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_root": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "header", - "wellknown_path", - "wellknown_root" - ], - "type": "object" - }, - "protected": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "transport": { - "additionalProperties": false, - "properties": { - "legacy_sse": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "streamable_http": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "streamable_http", - "legacy_sse", - "unknown", - "not_measured" - ], - "type": "object" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "withheld_opted_out": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "protected", - "pending_readjudication", - "not_assessed" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "description": "shadow_ai: the result is regrouped by what each number counts. shadow_ai.confirmed_exposed counts services EchelonGraph's probes found answering without an authentication gate (liveness active, or rechecking during a re-check): confirmed_exposed.total is the sum of confirmed_exposed.by_category, and confirmed_exposed.last_24h counts those first recorded in the last 24 h. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. confirmed_exposed.window.from and confirmed_exposed.window.to are timestamps, not counts: when EchelonGraph's verifier ran the probe that last decided the oldest and the newest of those services, a span of probes made at different times. shadow_ai.observed counts every Certificate Transparency or Shodan observation on record, whatever its verification state: its numbers are observed, not exposed. They are observed.total; observed.by_category (the same observations by category); observed.last_24h (those first recorded in the last 24 h); observed.trend_30d (observations per UTC day over the last 30 days); and observed.top_products, observed.top_countries and observed.top_issuers (up to ten products, countries and issuers ranked by observations, where an issuer is the certificate's CA for a Certificate Transparency observation and the hosting operator Shodan reports for a Shodan one). shadow_ai.authentication counts observations by probe outcome: authentication.observed where a probe observed an authentication gate (a 401/403, a login page or an auth marker), and authentication.not_determined where the service answered but no probe could tell. Neither authentication count is part of confirmed_exposed, and observed.total minus confirmed_exposed.total is not a count of secured services. The shadow-AI poller block carries only running and last_run_at: last_run_at is when the radar's leader last completed a Certificate Transparency (crt.sh) cycle, and its running is true only when that was within 30 minutes of the answer. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "authentication": { - "additionalProperties": false, - "properties": { - "not_determined": { - "type": "number" - }, - "observed": { - "type": "number" - } - }, - "type": "object" - }, - "confirmed_exposed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "observed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "last_observation": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "country": { - "type": "string" - } - }, - "required": [ - "country", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_issuers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "issuer": { - "type": "string" - } - }, - "required": [ - "issuer", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "trend_30d": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "date": { - "type": "string" - } - }, - "required": [ - "date", - "count" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "poller": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "running": { - "type": "boolean" - } - }, - "required": [ - "running", - "last_run_at" - ], - "type": "object" - } - }, - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at", - "enabled" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - }, - "running": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "last_run_at", - "running" - ], - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "radars": { - "description": "Each radar that could not be read, and why.", - "items": { - "additionalProperties": false, - "properties": { - "kind": { - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "unexpected_shape" - ], - "type": "string" - }, - "message": { - "type": "string" - }, - "path": { - "type": "string" - }, - "radar": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "radar", - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "type": "array" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "description": "A field this version cannot label is left out of data and named in the note. Each of the kev_exposure, exposed_databases and leaked_credentials radars also carries generated_at, when the API computed its totals, and, when the API can tell, last_run_at. kev_exposure.last_run_at, exposed_databases.last_run_at and leaked_credentials.last_run_at are timestamps, not counts: each is when that radar last completed a check, a cycle whose reads succeeded, among them a Shodan search (for exposed_databases, or its LeakIX fallback) that answered at least one query, or for leaked_credentials a read of the public GitHub event stream. A cycle that read nothing does not move it, and it is not the time of every record a radar's numbers count, which cover everything still on record, not only what the last check found. A radar whose answer carries no last_run_at has none in the result, and the note says nothing about it. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "exposed_databases": { + "additionalProperties": {}, + "description": "exposed_databases: exposed_databases.distinct_hosts counts distinct ip:port services the check confirmed answering without authentication, and exposed_databases.engines the distinct engine types among them; exposed_databases.top_engines and exposed_databases.top_countries rank up to 15 engines and 10 countries by those services. exposed_databases.pii_likely and exposed_databases.pci_likely count services whose schema names (never record values) pass a high-confidence, precision-first gate for personal or payment-card data, so a service outside them is not shown to hold no such data. exposed_databases.window.from and exposed_databases.window.to are timestamps, not counts: when EchelonGraph's check last confirmed the oldest and the newest of the services counted, a span of checks made at different times; with a counted service that has no such time on record there is no window, and exposed_databases.dated_window.from and exposed_databases.dated_window.to span the dated services only, while exposed_databases.dated_window.undated counts those with none.", + "properties": { + "dated_window": { + "additionalProperties": {}, + "description": "Timestamps over the dated rows only, relayed when some counted rows carry no observation time: a span of observations made at different times, never one observation time and never a count.", + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "undated": { + "description": "How many of the rows the counts count have no observation time on record. from and to do not describe them.", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "from", + "to", + "undated" + ], + "type": "object" + }, + "distinct_hosts": { + "type": "number" + }, + "engines": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "pci_likely": { + "type": "number" + }, + "pii_likely": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": {}, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_engines": { + "items": { + "additionalProperties": {}, + "properties": { + "engine": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "engine", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": {}, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "kev_exposure": { + "additionalProperties": {}, + "description": "kev_exposure: kev_exposure.distinct_hosts counts distinct ip:port services, not machines (a machine answering on two ports counts twice), with at least one CISA-KEV-listed CVE on record, and kev_exposure.ransomware_hosts those with a ransomware-linked one; kev_exposure.kev_cves_exposed and kev_exposure.ransomware_cves count distinct CVEs with at least one such service; kev_exposure.correlations counts service×CVE pairs, not services, so a service with three KEV CVEs counts three times. kev_exposure.top_products, kev_exposure.top_countries and kev_exposure.top_cves rank up to 12 products, 10 countries and 12 CVEs by those services; kev_exposure.top_cves[].cvss_v3_score and kev_exposure.top_cves[].epss_score are the highest CVSS v3 base score and EPSS probability recorded on that CVE's observations. kev_exposure.trend counts service×CVE pairs still on record by the week in which each was first recorded, over 12 weeks, so earlier weeks read low. kev_exposure.newest_kev lists the 15 CVEs that EchelonGraph's CVE records most recently mark as CISA-KEV-listed, each with an exposure_state: exposed, where kev_exposure.newest_kev[].exposed_hosts counts distinct ip:port services on record with it; or not_assessed, where the API's answer holds no measurement for that CVE (its 0 is not one) and no count is relayed, and this answer does not say whether the radar tracks that CVE: tracking is answered per CVE. kev_exposure.newest_kev[].cvss_v3_score and kev_exposure.newest_kev[].epss_score are the CVE record's CVSS v3 base score and EPSS probability. kev_exposure.window.from and kev_exposure.window.to are timestamps, not counts: when Shodan collected the banners of the oldest and the newest of the service×CVE pairs counted, a span of observations made at different times; with a counted pair that has no such time on record there is no window, and kev_exposure.dated_window.from and kev_exposure.dated_window.to span the dated pairs only, while kev_exposure.dated_window.undated counts the pairs with none. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "correlations": { + "type": "number" + }, + "dated_window": { + "additionalProperties": {}, + "description": "Timestamps over the dated rows only, relayed when some counted rows carry no observation time: a span of observations made at different times, never one observation time and never a count.", + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "undated": { + "description": "How many of the rows the counts count have no observation time on record. from and to do not describe them.", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "from", + "to", + "undated" + ], + "type": "object" + }, + "distinct_hosts": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "kev_cves_exposed": { + "type": "number" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "newest_kev": { + "items": { + "additionalProperties": {}, + "properties": { + "added_date": { + "type": "string" + }, + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "exposed_hosts": { + "type": "number" + }, + "exposure_state": { + "anyOf": [ + { + "enum": [ + "exposed", + "measured_zero", + "not_assessed" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "vuln_name": { + "type": "string" + } + }, + "required": [ + "cve_id", + "exposure_state" + ], + "type": "object" + }, + "type": "array" + }, + "ransomware_cves": { + "type": "number" + }, + "ransomware_hosts": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": {}, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "hosts": { + "type": "number" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + }, + "required": [ + "cve_id", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": {}, + "properties": { + "hosts": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "trend": { + "items": { + "additionalProperties": {}, + "properties": { + "new_exposures": { + "type": "number" + }, + "week": { + "type": "string" + } + }, + "required": [ + "week", + "new_exposures" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": {}, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": {}, + "description": "leaked_credentials: leaked_credentials.total counts (repository, secret) pairs, not distinct secrets, so one secret in three repositories counts three times; leaked_credentials.distinct_secrets counts each secret once and leaked_credentials.distinct_repos counts repositories; leaked_credentials.top_providers and leaked_credentials.top_types rank up to 15 providers and secret types by those pairs. None is validated: each is a credential-shaped string that passed EchelonGraph's filters, at most structurally checked and never tested against its provider. leaked_credentials.window.from and leaked_credentials.window.to are timestamps, not counts: when EchelonGraph's detector last found the oldest and the newest of the pairs counted; with a counted pair that has no such time on record there is no window, and leaked_credentials.dated_window.from and leaked_credentials.dated_window.to span the dated pairs only, while leaked_credentials.dated_window.undated counts those with none.", + "properties": { + "dated_window": { + "additionalProperties": {}, + "description": "Timestamps over the dated rows only, relayed when some counted rows carry no observation time: a span of observations made at different times, never one observation time and never a count.", + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "undated": { + "description": "How many of the rows the counts count have no observation time on record. from and to do not describe them.", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "from", + "to", + "undated" + ], + "type": "object" + }, + "distinct_repos": { + "type": "number" + }, + "distinct_secrets": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_providers": { + "items": { + "additionalProperties": {}, + "properties": { + "count": { + "type": "number" + }, + "provider": { + "type": "string" + } + }, + "required": [ + "provider", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_types": { + "items": { + "additionalProperties": {}, + "properties": { + "count": { + "type": "number" + }, + "secret_type": { + "type": "string" + } + }, + "required": [ + "secret_type", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": {}, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "mcp_servers": { + "additionalProperties": {}, + "description": "mcp_servers: counts and timestamps only, no hostname. mcp_servers.total counts hostnames the AI-exposure radar has checked for an MCP server, each once by its latest verdict on record, and not every one is an MCP server; EchelonGraph's own control servers are left out, and mcp_servers.own_controls_excluded counts them; hostnames whose owner opted out of scanning are not checked again while the opt-out stands, so their last verdict is left out too, and mcp_servers.withheld_opted_out counts them. mcp_servers.total is mcp_servers.protected plus mcp_servers.pending_readjudication plus mcp_servers.not_assessed. mcp_servers.protected counts hostnames whose /mcp endpoint asked for credentials and whose OAuth protected-resource metadata validated under RFC 9728; mcp_servers.prm_via divides them by where that document was found: mcp_servers.prm_via.header, mcp_servers.prm_via.wellknown_path and mcp_servers.prm_via.wellknown_root. mcp_servers.pending_readjudication counts verdicts of a rule since replaced, not yet re-checked. mcp_servers.not_assessed counts the rest, whose protection the radar could not assess (not assessed does not mean unprotected), and mcp_servers.not_assessed_by_reason puts each in one bucket. mcp_servers.not_assessed_by_reason.identified_no_challenge holds servers that identified themselves as MCP servers and did not ask for credentials at the handshake. That is normal in MCP: authorization is optional in the spec, and a server can enforce it at tools/call instead, which EchelonGraph never sends, so this bucket is not a finding of exposure. mcp_servers.not_assessed_by_reason.resource_mismatch, mcp_servers.not_assessed_by_reason.cross_origin_pointer, mcp_servers.not_assessed_by_reason.bare_challenge_no_prm, mcp_servers.not_assessed_by_reason.pointer_unreachable, mcp_servers.not_assessed_by_reason.pointer_invalid, mcp_servers.not_assessed_by_reason.no_authorization_servers, mcp_servers.not_assessed_by_reason.wellknown_unreachable and mcp_servers.not_assessed_by_reason.metadata_invalid hold endpoints that asked for credentials but whose RFC 9728 metadata did not validate, by why, so none of them is shown to lack protection; mcp_servers.not_assessed_by_reason.challenge_unadjudicated holds endpoints that asked for credentials before that check existed, not yet re-checked. mcp_servers.not_assessed_by_reason.no_http_answer holds hostnames that gave no HTTP answer, and mcp_servers.not_assessed_by_reason.not_identified_as_mcp hostnames whose HTTP answer identified no MCP server. mcp_servers.era divides every counted hostname by protocol era: mcp_servers.era.legacy; mcp_servers.era.dual, a lower bound; mcp_servers.era.modern, not proven modern-only; mcp_servers.era.unknown; and mcp_servers.era.not_measured, recorded before the era probe and not re-checked since. mcp_servers.transport divides them by transport: mcp_servers.transport.streamable_http, mcp_servers.transport.legacy_sse, mcp_servers.transport.unknown and mcp_servers.transport.not_measured. mcp_servers.window.from and mcp_servers.window.to are when the oldest and the newest of the verdicts counted were last checked. mcp_servers.last_run_at is a timestamp, not a count: when the AI-exposure radar, which checks other AI services too, last completed a check; mcp_servers.enabled is whether one completed within 45 minutes of the answer, and mcp_servers.counted_at is when the API read the counts. A partition whose buckets do not add up to the count it divides is left out and named; an answer that does not say it is the MCP-server counts, or whose mcp_servers.total, mcp_servers.protected, mcp_servers.pending_readjudication and mcp_servers.not_assessed are missing or contradict each other, is a failure.", + "properties": { + "counted_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "era": { + "additionalProperties": {}, + "properties": { + "dual": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "legacy": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "modern": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "legacy", + "dual", + "modern", + "unknown", + "not_measured" + ], + "type": "object" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "not_assessed": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_assessed_by_reason": { + "additionalProperties": {}, + "properties": { + "bare_challenge_no_prm": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "challenge_unadjudicated": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "cross_origin_pointer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "identified_no_challenge": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "metadata_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_authorization_servers": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_http_answer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_identified_as_mcp": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "resource_mismatch": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "identified_no_challenge", + "resource_mismatch", + "cross_origin_pointer", + "bare_challenge_no_prm", + "pointer_unreachable", + "pointer_invalid", + "no_authorization_servers", + "wellknown_unreachable", + "metadata_invalid", + "challenge_unadjudicated", + "no_http_answer", + "not_identified_as_mcp" + ], + "type": "object" + }, + "own_controls_excluded": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pending_readjudication": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "prm_via": { + "additionalProperties": {}, + "properties": { + "header": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_path": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_root": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "header", + "wellknown_path", + "wellknown_root" + ], + "type": "object" + }, + "protected": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "transport": { + "additionalProperties": {}, + "properties": { + "legacy_sse": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "streamable_http": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "streamable_http", + "legacy_sse", + "unknown", + "not_measured" + ], + "type": "object" + }, + "window": { + "additionalProperties": {}, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "withheld_opted_out": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "protected", + "pending_readjudication", + "not_assessed" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": {}, + "description": "shadow_ai: the result is regrouped by what each number counts. shadow_ai.confirmed_exposed counts services EchelonGraph's probes found answering without an authentication gate (liveness active, or rechecking during a re-check): confirmed_exposed.total is the sum of confirmed_exposed.by_category, and confirmed_exposed.last_24h counts those first recorded in the last 24 h. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. confirmed_exposed.window.from and confirmed_exposed.window.to are timestamps, not counts: when EchelonGraph's verifier ran the probe that last decided the oldest and the newest of those services, a span of probes made at different times; with one that has no such time there is no window, and confirmed_exposed.dated_window.from and confirmed_exposed.dated_window.to span the dated ones only, while confirmed_exposed.dated_window.undated counts those with none. shadow_ai.observed counts every Certificate Transparency or Shodan observation on record, whatever its verification state: its numbers are observed, not exposed. They are observed.total; observed.by_category (the same observations by category); observed.last_24h (those first recorded in the last 24 h); observed.trend_30d (observations per UTC day over the last 30 days); and observed.top_products, observed.top_countries and observed.top_issuers (up to ten products, countries and issuers ranked by observations, where an issuer is the certificate's CA for a Certificate Transparency observation and the hosting operator Shodan reports for a Shodan one). shadow_ai.authentication counts observations by probe outcome: authentication.observed where a probe observed an authentication gate (a 401/403, a login page or an auth marker), and authentication.not_determined where the service answered but no probe could tell. Neither authentication count is part of confirmed_exposed, and observed.total minus confirmed_exposed.total is not a count of secured services. The shadow-AI poller block carries only running and last_run_at: last_run_at is when the radar's leader last completed a Certificate Transparency (crt.sh) cycle, and its running is true only when that was within 30 minutes of the answer. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "authentication": { + "additionalProperties": {}, + "properties": { + "not_determined": { + "type": "number" + }, + "observed": { + "type": "number" + } + }, + "type": "object" + }, + "confirmed_exposed": { + "additionalProperties": {}, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "dated_window": { + "additionalProperties": {}, + "description": "Timestamps over the dated rows only, relayed when some counted rows carry no observation time: a span of observations made at different times, never one observation time and never a count.", + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "undated": { + "description": "How many of the rows the counts count have no observation time on record. from and to do not describe them.", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "from", + "to", + "undated" + ], + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": {}, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "observed": { + "additionalProperties": {}, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "last_observation": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_countries": { + "items": { + "additionalProperties": {}, + "properties": { + "count": { + "type": "number" + }, + "country": { + "type": "string" + } + }, + "required": [ + "country", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_issuers": { + "items": { + "additionalProperties": {}, + "properties": { + "count": { + "type": "number" + }, + "issuer": { + "type": "string" + } + }, + "required": [ + "issuer", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": {}, + "properties": { + "count": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "trend_30d": { + "items": { + "additionalProperties": {}, + "properties": { + "count": { + "type": "number" + }, + "date": { + "type": "string" + } + }, + "required": [ + "date", + "count" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "poller": { + "additionalProperties": {}, + "properties": { + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "running": { + "type": "boolean" + } + }, + "required": [ + "running", + "last_run_at" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "exposed_databases": { + "additionalProperties": {}, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "kev_exposure": { + "additionalProperties": {}, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": {}, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "mcp_servers": { + "additionalProperties": {}, + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + }, + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at", + "enabled" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": {}, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "running": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "last_run_at", + "running" + ], + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "radars": { + "description": "Each radar that could not be read, and why.", + "items": { + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "unexpected_shape" + ], + "type": "string" + }, + "message": { + "type": "string" + }, + "path": { + "type": "string" + }, + "radar": { + "type": "string" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "radar", + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "cna": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "name": { - "type": [ - "string", - "null" - ] - }, - "short_name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." - }, - "cna_solution": { - "description": "The sentence of the CVE record's solutions or workarounds, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. cna_solution_section says which of the two sections it is. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "cna_solution_section": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "solution", - "workaround" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "Which section of the CVE record cna_solution was read from: solution (the record's solutions) or workaround (its workarounds, read only where its solutions name no fix: a temporary measure the CNA lists beside its fix). A workaround's sentence is the record's workaround, never its solution. Present whenever cna_solution is; absent from an API older than the field." - }, - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "date_public": { - "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "date_public_source": { - "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "echelongraph_ssvc_decision": { - "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_required_action": { - "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "kev_short_description": { - "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds, or once held, evidence of a fix for the CVE; patch_evidence names the sources it holds now. true beside an empty patch_evidence means evidence of a fix once held has since been withdrawn (patch_available is never set back to false), and fix_status (remediation.fix_status in the CVE's record) is the current reading, not patch_available. false: no fix evidence is on record, which is not a finding that no fix exists. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "release_reference", - "vendor_advisory_fix", - "nvd_patch_reference", - "cna_patch_reference", - "cna_solution", - "description_fix", - "vendor_fix_released" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions or workarounds, written by its CNA, that names a fixed version; relayed as cna_solution), description_fix (a sentence of the CVE description that names a fixed version) and vendor_fix_released (the vendor states, in the CVE record, that a fix is released and the record names no fixed version; check the vendor's advisory). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fix_status": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "basis": { - "type": [ - "string", - "null" - ] - }, - "described_by": { - "type": [ - "string", - "null" - ] - }, - "listed_in_patch_table": { - "type": [ - "boolean", - "null" - ] - }, - "solution_by": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cna": { - "type": [ - "string", - "null" - ] - }, - "section": { - "type": [ - "string", - "null" - ] - }, - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "available", - "fix_referenced", - "fix_merged", - "none_confirmed", - "unknown" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "stated_in_record": { - "type": [ - "boolean", - "null" - ] - }, - "unread_inputs": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "vendor_released": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", - "type": [ - "string", - "null" - ] - }, - "score_factors": { - "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cna": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "name": { + "type": [ + "string", + "null" + ] + }, + "short_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." + }, + "cna_solution": { + "description": "The sentence of the CVE record's solutions or workarounds, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. cna_solution_section says which of the two sections it is. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "cna_solution_section": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "solution", + "workaround" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "Which section of the CVE record cna_solution was read from: solution (the record's solutions) or workaround (its workarounds, read only where its solutions name no fix: a temporary measure the CNA lists beside its fix). A workaround's sentence is the record's workaround, never its solution. Present whenever cna_solution is; absent from an API older than the field." + }, + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "date_public": { + "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "date_public_source": { + "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from impact severity (eg_severity, from scorer v4.0; the score before it), exploitation and automatability, with EchelonGraph's hand-set weights: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: severity, escalated by confirmed exploitation (a CISA KEV listing floors it at 9.0) and lifted toward 9.0 by EPSS; eg_severity is the impact severity alone. A score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "echelongraph_ssvc_decision": { + "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", + "type": [ + "string", + "null" + ] + }, + "eg_likelihood": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "exploited": { + "type": [ + "boolean", + "null" + ] + }, + "exploited_sources": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "horizon_days": { + "type": [ + "number", + "null" + ] + }, + "null_reason": { + "type": [ + "string", + "null" + ] + }, + "probability": { + "type": [ + "number", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A probability with a horizon (scorer v4.0): probability is FIRST's EPSS probability of exploitation activity in the next 30 days (source first_epss, horizon_days 30, with epss_percentile, epss_score_date and epss_model_version where stored), not EchelonGraph's own model. null, with null_reason no_epss_on_record, where no EPSS is on record: the likelihood is unknown, not low. exploited (true when CISA KEV lists the CVE or EG-KEV rates it Tier 1) and exploited_sources report confirmed exploitation apart from it; it is never folded into probability. Absent from a record scored before v4.0." + }, + "eg_priority": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "bod_26_04": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "if_not_publicly_exposed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "if_publicly_exposed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "inputs": {}, + "ssvc": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "decision": { + "type": [ + "string", + "null" + ] + }, + "mission": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The decision (scorer v4.0): ssvc, the decision CISA's SSVC table gives as EchelonGraph applies it (decision at medium mission impact, as echelongraph_ssvc_decision, and by_mission), null with null_reason not_assessed for a CVE EchelonGraph has not assessed; bod_26_04, CISA BOD 26-04's timeline if_publicly_exposed and if_not_publicly_exposed (CERT/CC's keys 3DF, 3D, 14D, 60D, FSU); inputs, kev, exploitation, automatable and technical_impact, each with its source. Absent from a record scored before v4.0." + }, + "eg_severity": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "assessed": { + "type": [ + "boolean", + "null" + ] + }, + "provider": { + "type": [ + "string", + "null" + ] + }, + "score": { + "type": [ + "number", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "unassessed_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Impact severity alone (scorer v4.0): the CVSS base score from the best-provenance CVSS EchelonGraph holds, which no CISA KEV listing, EPSS probability or EG-KEV tier raises. score (0-10) and severity (the CVSS band), with metric cvss_base, cvss_version, vector, source and provider. assessed false, with score and severity null and unassessed_reason, where no CVSS of any version is published: kev_listed_no_cvss reads exploited, severity not yet published. Absent from a record scored before v4.0." + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds, or once held, evidence of a fix for the CVE; patch_evidence names the sources it holds now. true beside an empty patch_evidence means evidence of a fix once held has since been withdrawn (patch_available is never set back to false), and fix_status (remediation.fix_status in the CVE's record) is the current reading, not patch_available. false: no fix evidence is on record, which is not a finding that no fix exists. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "vendor_advisory_fix", + "nvd_patch_reference", + "cna_patch_reference", + "cna_solution", + "description_fix", + "vendor_fix_released" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions or workarounds, written by its CNA, that names a fixed version; relayed as cna_solution), description_fix (a sentence of the CVE description that names a fixed version) and vendor_fix_released (the vendor states, in the CVE record, that a fix is released and the record names no fixed version; check the vendor's advisory). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "section": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "vendor_released": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_factors": { + "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed. eg_severity, eg_likelihood and eg_priority (scorer v4.0): the same objects as the record's top-level fields. eg_risk.severity_source (v4.0): what EG Risk's severity term read, eg_severity, vendor_severity, or unknown_kev_most_urgent (no severity published for a CISA KEV CVE, so the most urgent value)." + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_cwe1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max_page": { - "type": [ - "number", - "null" - ] - }, - "page": { - "description": "The page served.", - "type": [ - "number", - "null" - ] - }, - "page_requested": { - "description": "The page asked for.", - "type": "number" - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "page", - "page_requested", - "page_size", - "max_page" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "catalog_version": { - "description": "The version of the MITRE CWE catalog name and description come from.", - "type": [ - "string", - "null" - ] - }, - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v2_severity": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: a score only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE; false: NOT YET SCORED, not scored 0.", - "type": [ - "boolean", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "max_page": { - "description": "The last page the API serves; a later page is answered as this one.", - "type": [ - "number", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "order": { - "description": "How cves is sorted, as the API states it; absent from an API older than the field, which sorted by CVE id.", - "type": [ - "string", - "null" - ] - }, - "page": { - "type": [ - "number", - "null" - ] - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "The active CVEs classified under the CWE, rejected and reserved records left out.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max_page": { - "type": [ - "number", - "null" - ] - }, - "page": { - "description": "The page served.", - "type": [ - "number", - "null" - ] - }, - "page_requested": { - "description": "The page asked for.", - "type": "number" - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "page", - "page_requested", - "page_size", - "max_page" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "max_page": { + "type": [ + "number", + "null" + ] + }, + "page": { + "description": "The page served.", + "type": [ + "number", + "null" + ] + }, + "page_requested": { + "description": "The page asked for.", + "type": "number" + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "total", + "returned", + "page", + "page_requested", + "page_size", + "max_page" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "catalog_version": { + "description": "The version of the MITRE CWE catalog name and description come from.", + "type": [ + "string", + "null" + ] + }, + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v2_severity": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: a score only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE; false: NOT YET SCORED, not scored 0.", + "type": [ + "boolean", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "max_page": { + "description": "The last page the API serves; a later page is answered as this one.", + "type": [ + "number", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "order": { + "description": "How cves is sorted, as the API states it; absent from an API older than the field, which sorted by CVE id.", + "type": [ + "string", + "null" + ] + }, + "page": { + "type": [ + "number", + "null" + ] + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "The active CVEs classified under the CWE, rejected and reserved records left out.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max_page": { + "type": [ + "number", + "null" + ] + }, + "page": { + "description": "The page served.", + "type": [ + "number", + "null" + ] + }, + "page_requested": { + "description": "The page asked for.", + "type": "number" + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "total", + "returned", + "page", + "page_requested", + "page_size", + "max_page" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_vendor_advisory2 fields changed- changed
Input schema / properties / advisory_id / descriptionPrevious value: -"the vendor's advisory ID, e.g. RHSA-2024:1234 or GHSA-xxxx-xxxx-xxxx"New value: +"the vendor's own advisory ID, a row's vendor_advisory_id, e.g. RHSA-2024:1234, GHSA-xxxx-xxxx-xxxx or CVE-2024-3400; not a row's advisory_id, EchelonGraph's internal UUID" - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "known_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "references": {}, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation": { - "description": "The vendor's remediation as one text (the legacy field), beside remediations.", - "type": [ - "string", - "null" - ] - }, - "remediation_items_not_stored": { - "description": "Items past the 64 stored per advisory.", - "type": [ - "number", - "null" - ] - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "remediations": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVEs the item covers; [] for the whole advisory." - }, - "fixed_build": { - "type": [ - "string", - "null" - ] - }, - "kind": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "product_count": { - "type": [ - "number", - "null" - ] - }, - "product_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "source_category": { - "description": "The vendor's own name for the category.", - "type": [ - "string", - "null" - ] - }, - "source_subcategory": { - "type": [ - "string", - "null" - ] - }, - "text": { - "description": "The vendor's text, verbatim but for HTML markup removed, untested by EchelonGraph; at most 2,000 characters (text_truncated, text_chars).", - "type": [ - "string", - "null" - ] - }, - "text_chars": { - "type": [ - "number", - "null" - ] - }, - "text_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each remediation the vendor lists, with its kind, the vendor's own category." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_modified_at": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - }, - "withdrawn_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn_reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": {}, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "EchelonGraph's internal ID for this advisory, a UUID. It is not the vendor's advisory ID (vendor_advisory_id), and an advisory's detail is not looked up by it: the detail is keyed on vendor and vendor_advisory_id.", + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "known_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "references": {}, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation": { + "description": "The vendor's remediation as one text (the legacy field), beside remediations.", + "type": [ + "string", + "null" + ] + }, + "remediation_items_not_stored": { + "description": "Items past the 64 stored per advisory.", + "type": [ + "number", + "null" + ] + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "remediations": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVEs the item covers; [] for the whole advisory." + }, + "fixed_build": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "product_count": { + "type": [ + "number", + "null" + ] + }, + "product_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "source_category": { + "description": "The vendor's own name for the category.", + "type": [ + "string", + "null" + ] + }, + "source_subcategory": { + "type": [ + "string", + "null" + ] + }, + "text": { + "description": "The vendor's text, verbatim but for HTML markup removed, untested by EchelonGraph; at most 2,000 characters (text_truncated, text_chars).", + "type": [ + "string", + "null" + ] + }, + "text_chars": { + "type": [ + "number", + "null" + ] + }, + "text_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each remediation the vendor lists, with its kind, the vendor's own category." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "description": "The vendor's own ID for the advisory (e.g. RHSA-2024:1234, GHSA-xxxx-xxxx-xxxx, or the CVE ID for Microsoft and Palo Alto Networks). With vendor, it is the key an advisory's detail is looked up by, as its advisory_id argument.", + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_modified_at": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
kev_recent1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "catalog": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "catalog_count": { - "type": [ - "number", - "null" - ] - }, - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "feed_url": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "filters": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": {}, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev": { - "description": "Newest kev_added_date first; rows within one date are ordered by cve_id.", - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "eg_kev_tier": { - "type": [ - "number", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "type": [ - "string", - "null" - ] - }, - "kev_product": { - "type": [ - "string", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_vendor": { - "type": [ - "string", - "null" - ] - }, - "kev_vuln_name": { - "type": [ - "string", - "null" - ] - }, - "our_first_seen_kev": { - "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "kev_listed_total": { - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - }, - "notes": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "order": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "last_successful_fetch_at", - "catalog_version", - "date_released" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "catalog": { + "anyOf": [ + { + "const": "CISA KEV catalog", + "type": "string" + }, + { + "type": "string" + } + ] + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "catalog": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "catalog_count": { + "type": [ + "number", + "null" + ] + }, + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "feed_url": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "filters": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev": { + "description": "Newest kev_added_date first; rows within one date are ordered by cve_id.", + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "eg_kev_tier": { + "type": [ + "number", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "type": [ + "string", + "null" + ] + }, + "kev_product": { + "type": [ + "string", + "null" + ] + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_vendor": { + "type": [ + "string", + "null" + ] + }, + "kev_vuln_name": { + "type": [ + "string", + "null" + ] + }, + "our_first_seen_kev": { + "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "kev_listed_total": { + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "next_cursor": { + "type": [ + "string", + "null" + ] + }, + "notes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "order": { + "type": [ + "string", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "last_successful_fetch_at", + "catalog_version", + "date_released" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog": { + "const": "CISA KEV catalog", + "type": "string" + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
scan_manifest2 fields changed- added
Input schema / properties / files / maxItemsAdded value: +20 - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls read more than once (the same package and version in two places) and sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "entries_pinned": { - "description": "Entries pinned to one version across the files, duplicates included.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files": { - "description": "Files passed.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_not_read": { - "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_read": { - "description": "Of those, the ones read.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_checked": { - "description": "Entries not sent (data.not_checked): not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_checked_by_reason": { - "additionalProperties": false, - "description": "not_checked, counted by reason.", - "properties": { - "local_path": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "unsupported_line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "vcs_source": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unpinned": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unresolved": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "object" - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "files", - "files_read", - "files_not_read", - "entries_pinned", - "duplicates_removed", - "not_checked", - "not_checked_by_reason", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "manifest": { - "additionalProperties": false, - "description": "Each file passed, in order, and how it was read. Filenames and contents are not sent to the API.", - "properties": { - "files": { - "items": { - "additionalProperties": false, - "properties": { - "ecosystem": { - "description": "The OSV ecosystem of the purls read from it.", - "type": [ - "string", - "null" - ] - }, - "filename": { - "type": "string" - }, - "format": { - "anyOf": [ - { - "enum": [ - "requirements.txt", - "go.mod", - "package-lock.json", - "Cargo.lock", - "Gemfile.lock", - "composer.lock", - "poetry.lock", - "gradle.lockfile" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The format the file was read as: set by format, or read from the filename; null when it was not read." - }, - "not_checked": { - "description": "Entries not sent, listed in data.not_checked: not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "notes": { - "description": "How this file was read where that limits what its verdicts cover (a go.mod below go 1.17).", - "items": { - "type": "string" - }, - "type": "array" - }, - "purls": { - "description": "Entries pinned to one version, read as purls (duplicates included).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "read": { - "description": "false: the file was refused or could not be read, and nothing in it is checked (not clean).", - "type": "boolean" - }, - "refused": { - "description": "Why the file was not read, and the file to pass instead where there is one; null when it was read.", - "type": [ - "string", - "null" - ] - }, - "replaced": { - "description": "go.mod replace directives applied: the module required, and the module and version checked instead.", - "items": { - "additionalProperties": false, - "properties": { - "from": { - "type": "string" - }, - "to": { - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "type": "array" - }, - "skipped": { - "description": "Entries that are not dependencies (a package-lock's root entry, the project itself).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "filename", - "format", - "ecosystem", - "read", - "refused", - "purls", - "not_checked", - "skipped", - "notes", - "replaced" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "files" - ], - "type": "object" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_checked": { - "description": "Each entry not sent to the API, with its file, line and reason: not checked, and not clean.", - "items": { - "additionalProperties": false, - "properties": { - "detail": { - "type": "string" - }, - "file": { - "type": "string" - }, - "line": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "1-based line; null in a JSON lockfile, whose entries spec names by key." - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "description": "version_unpinned: a range or wildcard, not one version; version_unresolved: no single registry version (none given, a branch, or an excluded go.mod version); local_path: a directory, file or workspace member; vcs_source: a VCS checkout; unsupported_line: a line or entry this tool does not read (another file named by -r or -c, a direct URL, another registry).", - "enum": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "string" - }, - "spec": { - "description": "What the file says for the entry: its line, or its lockfile key and version (at most 200 characters).", - "type": "string" - } - }, - "required": [ - "file", - "name", - "spec", - "reason", - "line", - "detail" - ], - "type": "object" - }, - "type": "array" - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matched_package": { - "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", - "type": [ - "string", - "null" - ] - }, - "matched_version_from": { - "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", - "type": [ - "string", - "null" - ] - }, - "matched_via": { - "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", - "type": [ - "boolean", - "null" - ] - }, - "match_reason": { - "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "matches_truncated": { - "additionalProperties": false, - "description": "Present only on a row whose matches the structured result's cut (DATA CUT) shortened or left out: total, the row's matches in the answer; returned, the ones data keeps (its first, highest effective_score first); and, while they fit, of all its matches, the CVE IDs KEV-listed (kev_listed_cve_ids) or used in ransomware (ransomware_cve_ids), and the distinct fixed_in versions (fixed_in_versions). The same call with full: true returns every match.", - "properties": { - "fixed_in_versions": { - "items": { - "type": "string" - }, - "type": "array" - }, - "kev_listed_cve_ids": { - "items": { - "type": "string" - }, - "type": "array" - }, - "ransomware_cve_ids": { - "items": { - "type": "string" - }, - "type": "array" - }, - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "purl_name": { - "description": "Upstream rows: the purl's own (binary) package name, not looked up.", - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "required": [ - "manifest", - "not_checked" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls read more than once (the same package and version in two places) and sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "entries_pinned": { - "description": "Entries pinned to one version across the files, duplicates included.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files": { - "description": "Files passed.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_not_read": { - "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_read": { - "description": "Of those, the ones read.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_checked": { - "description": "Entries not sent (data.not_checked): not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_checked_by_reason": { - "additionalProperties": false, - "description": "not_checked, counted by reason.", - "properties": { - "local_path": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "unsupported_line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "vcs_source": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unpinned": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unresolved": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "object" - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "files", - "files_read", - "files_not_read", - "entries_pinned", - "duplicates_removed", - "not_checked", - "not_checked_by_reason", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls read more than once (the same package and version in two places) and sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entries_pinned": { + "description": "Entries pinned to one version across the files, duplicates included.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files": { + "description": "Files passed.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_not_read": { + "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_read": { + "description": "Of those, the ones read.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_checked": { + "description": "Entries not sent (data.not_checked): not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_checked_by_reason": { + "additionalProperties": {}, + "description": "not_checked, counted by reason.", + "properties": { + "local_path": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "unsupported_line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "vcs_source": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unpinned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unresolved": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "object" + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "files", + "files_read", + "files_not_read", + "entries_pinned", + "duplicates_removed", + "not_checked", + "not_checked_by_reason", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "manifest": { + "additionalProperties": {}, + "description": "Each file passed, in order, and how it was read. Filenames and contents are not sent to the API.", + "properties": { + "files": { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "description": "The OSV ecosystem of the purls read from it.", + "type": [ + "string", + "null" + ] + }, + "filename": { + "type": "string" + }, + "format": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "requirements.txt", + "go.mod", + "package-lock.json", + "Cargo.lock", + "Gemfile.lock", + "composer.lock", + "poetry.lock", + "gradle.lockfile" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "The format the file was read as: set by format, or read from the filename; null when it was not read." + }, + "not_checked": { + "description": "Entries not sent, listed in data.not_checked: not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "notes": { + "description": "How this file was read where that limits what its verdicts cover (a go.mod below go 1.17).", + "items": { + "type": "string" + }, + "type": "array" + }, + "purls": { + "description": "Entries pinned to one version, read as purls (duplicates included).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "read": { + "description": "false: the file was refused or could not be read, and nothing in it is checked (not clean).", + "type": "boolean" + }, + "refused": { + "description": "Why the file was not read, and the file to pass instead where there is one; null when it was read.", + "type": [ + "string", + "null" + ] + }, + "replaced": { + "description": "go.mod replace directives applied: the module required, and the module and version checked instead.", + "items": { + "additionalProperties": {}, + "properties": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "skipped": { + "description": "Entries that are not dependencies (a package-lock's root entry, the project itself).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "filename", + "format", + "ecosystem", + "read", + "refused", + "purls", + "not_checked", + "skipped", + "notes", + "replaced" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "files" + ], + "type": "object" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_checked": { + "description": "Each entry not sent to the API, with its file, line and reason: not checked, and not clean.", + "items": { + "additionalProperties": {}, + "properties": { + "detail": { + "type": "string" + }, + "file": { + "type": "string" + }, + "line": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "1-based line; null in a JSON lockfile, whose entries spec names by key." + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "anyOf": [ + { + "enum": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "version_unpinned: a range or wildcard, not one version; version_unresolved: no single registry version (none given, a branch, or an excluded go.mod version); local_path: a directory, file or workspace member; vcs_source: a VCS checkout; unsupported_line: a line or entry this tool does not read (another file named by -r or -c, a direct URL, another registry)." + }, + "spec": { + "description": "What the file says for the entry: its line, or its lockfile key and version (at most 200 characters).", + "type": "string" + } + }, + "required": [ + "file", + "name", + "spec", + "reason", + "line", + "detail" + ], + "type": "object" + }, + "type": "array" + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matched_package": { + "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", + "type": [ + "string", + "null" + ] + }, + "matched_version_from": { + "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", + "type": [ + "string", + "null" + ] + }, + "matched_via": { + "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", + "type": [ + "boolean", + "null" + ] + }, + "match_reason": { + "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "matches_truncated": { + "additionalProperties": {}, + "description": "Present only on a row whose matches the structured result's cut (DATA CUT) shortened or left out: total, the row's matches in the answer; returned, the ones data keeps (chosen used in ransomware first, then the other KEV-listed ones, then highest effective_score, and listed in the API's order); and, while they fit, of all its matches, the CVE IDs KEV-listed (kev_listed_cve_ids) or used in ransomware (ransomware_cve_ids), and the distinct fixed_in versions (fixed_in_versions). The same call with full: true returns every match.", + "properties": { + "fixed_in_versions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "kev_listed_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ransomware_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "purl_name": { + "description": "Upstream rows: the purl's own (binary) package name, not looked up.", + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "required": [ + "manifest", + "not_checked" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls read more than once (the same package and version in two places) and sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entries_pinned": { + "description": "Entries pinned to one version across the files, duplicates included.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files": { + "description": "Files passed.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_not_read": { + "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_read": { + "description": "Of those, the ones read.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_checked": { + "description": "Entries not sent (data.not_checked): not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_checked_by_reason": { + "additionalProperties": false, + "description": "not_checked, counted by reason.", + "properties": { + "local_path": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "unsupported_line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "vcs_source": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unpinned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unresolved": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "object" + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "files", + "files_read", + "files_not_read", + "entries_pinned", + "duplicates_removed", + "not_checked", + "not_checked_by_reason", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_cves1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "The rows in this page.", - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cna": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "name": { - "type": [ - "string", - "null" - ] - }, - "short_name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." - }, - "cna_solution": { - "description": "The sentence of the CVE record's solutions or workarounds, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. cna_solution_section says which of the two sections it is. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "cna_solution_section": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "solution", - "workaround" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "Which section of the CVE record cna_solution was read from: solution (the record's solutions) or workaround (its workarounds, read only where its solutions name no fix: a temporary measure the CNA lists beside its fix). A workaround's sentence is the record's workaround, never its solution. Present whenever cna_solution is; absent from an API older than the field." - }, - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "date_public": { - "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "date_public_source": { - "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "echelongraph_ssvc_decision": { - "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_required_action": { - "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "kev_short_description": { - "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds, or once held, evidence of a fix for the CVE; patch_evidence names the sources it holds now. true beside an empty patch_evidence means evidence of a fix once held has since been withdrawn (patch_available is never set back to false), and fix_status (remediation.fix_status in the CVE's record) is the current reading, not patch_available. false: no fix evidence is on record, which is not a finding that no fix exists. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "release_reference", - "vendor_advisory_fix", - "nvd_patch_reference", - "cna_patch_reference", - "cna_solution", - "description_fix", - "vendor_fix_released" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions or workarounds, written by its CNA, that names a fixed version; relayed as cna_solution), description_fix (a sentence of the CVE description that names a fixed version) and vendor_fix_released (the vendor states, in the CVE record, that a fix is released and the record names no fixed version; check the vendor's advisory). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fix_status": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "basis": { - "type": [ - "string", - "null" - ] - }, - "described_by": { - "type": [ - "string", - "null" - ] - }, - "listed_in_patch_table": { - "type": [ - "boolean", - "null" - ] - }, - "solution_by": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cna": { - "type": [ - "string", - "null" - ] - }, - "section": { - "type": [ - "string", - "null" - ] - }, - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "available", - "fix_referenced", - "fix_merged", - "none_confirmed", - "unknown" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "stated_in_record": { - "type": [ - "boolean", - "null" - ] - }, - "unread_inputs": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "vendor_released": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", - "type": [ - "string", - "null" - ] - }, - "score_factors": { - "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "description": "true: a search phrase was relaxed to all of its words.", - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "description": "false: the matches were not counted, so total is not a count.", - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "description": "true: there are at least total matches.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "The rows in this page.", - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cna": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "name": { + "type": [ + "string", + "null" + ] + }, + "short_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." + }, + "cna_solution": { + "description": "The sentence of the CVE record's solutions or workarounds, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. cna_solution_section says which of the two sections it is. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "cna_solution_section": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "solution", + "workaround" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "Which section of the CVE record cna_solution was read from: solution (the record's solutions) or workaround (its workarounds, read only where its solutions name no fix: a temporary measure the CNA lists beside its fix). A workaround's sentence is the record's workaround, never its solution. Present whenever cna_solution is; absent from an API older than the field." + }, + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "date_public": { + "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "date_public_source": { + "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from impact severity (eg_severity, from scorer v4.0; the score before it), exploitation and automatability, with EchelonGraph's hand-set weights: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: severity, escalated by confirmed exploitation (a CISA KEV listing floors it at 9.0) and lifted toward 9.0 by EPSS; eg_severity is the impact severity alone. A score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "echelongraph_ssvc_decision": { + "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", + "type": [ + "string", + "null" + ] + }, + "eg_likelihood": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "exploited": { + "type": [ + "boolean", + "null" + ] + }, + "exploited_sources": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "horizon_days": { + "type": [ + "number", + "null" + ] + }, + "null_reason": { + "type": [ + "string", + "null" + ] + }, + "probability": { + "type": [ + "number", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A probability with a horizon (scorer v4.0): probability is FIRST's EPSS probability of exploitation activity in the next 30 days (source first_epss, horizon_days 30, with epss_percentile, epss_score_date and epss_model_version where stored), not EchelonGraph's own model. null, with null_reason no_epss_on_record, where no EPSS is on record: the likelihood is unknown, not low. exploited (true when CISA KEV lists the CVE or EG-KEV rates it Tier 1) and exploited_sources report confirmed exploitation apart from it; it is never folded into probability. Absent from a record scored before v4.0." + }, + "eg_priority": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "bod_26_04": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "if_not_publicly_exposed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "if_publicly_exposed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "inputs": {}, + "ssvc": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "decision": { + "type": [ + "string", + "null" + ] + }, + "mission": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The decision (scorer v4.0): ssvc, the decision CISA's SSVC table gives as EchelonGraph applies it (decision at medium mission impact, as echelongraph_ssvc_decision, and by_mission), null with null_reason not_assessed for a CVE EchelonGraph has not assessed; bod_26_04, CISA BOD 26-04's timeline if_publicly_exposed and if_not_publicly_exposed (CERT/CC's keys 3DF, 3D, 14D, 60D, FSU); inputs, kev, exploitation, automatable and technical_impact, each with its source. Absent from a record scored before v4.0." + }, + "eg_severity": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "assessed": { + "type": [ + "boolean", + "null" + ] + }, + "provider": { + "type": [ + "string", + "null" + ] + }, + "score": { + "type": [ + "number", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "unassessed_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Impact severity alone (scorer v4.0): the CVSS base score from the best-provenance CVSS EchelonGraph holds, which no CISA KEV listing, EPSS probability or EG-KEV tier raises. score (0-10) and severity (the CVSS band), with metric cvss_base, cvss_version, vector, source and provider. assessed false, with score and severity null and unassessed_reason, where no CVSS of any version is published: kev_listed_no_cvss reads exploited, severity not yet published. Absent from a record scored before v4.0." + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds, or once held, evidence of a fix for the CVE; patch_evidence names the sources it holds now. true beside an empty patch_evidence means evidence of a fix once held has since been withdrawn (patch_available is never set back to false), and fix_status (remediation.fix_status in the CVE's record) is the current reading, not patch_available. false: no fix evidence is on record, which is not a finding that no fix exists. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "vendor_advisory_fix", + "nvd_patch_reference", + "cna_patch_reference", + "cna_solution", + "description_fix", + "vendor_fix_released" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions or workarounds, written by its CNA, that names a fixed version; relayed as cna_solution), description_fix (a sentence of the CVE description that names a fixed version) and vendor_fix_released (the vendor states, in the CVE record, that a fix is released and the record names no fixed version; check the vendor's advisory). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "section": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "vendor_released": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_factors": { + "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed. eg_severity, eg_likelihood and eg_priority (scorer v4.0): the same objects as the record's top-level fields. eg_risk.severity_source (v4.0): what EG Risk's severity term read, eg_severity, vendor_severity, or unknown_kev_most_urgent (no severity published for a CISA KEV CVE, so the most urgent value)." + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "description": "true: a search phrase was relaxed to all of its words.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "description": "false: the matches were not counted, so total is not a count.", + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "description": "true: there are at least total matches.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_vendor_advisories1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "description": "Whether a free-text search filtered this answer.", - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, vendor_advisory_id, affected_products and cve_ids (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word): it must equal, ignoring case, a whole word (a run of letters and digits) of one of those, so xz finds xz-utils but not xzibit, and a 1- or 2-character query with any other character, such as c#, matches nothing.", - "type": [ - "string", - "null" - ] - }, - "total": { - "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000; paging past it still works. Without a query, total is the exact count and total_capped is false.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "EchelonGraph's internal ID for this advisory, a UUID. It is not the vendor's advisory ID (vendor_advisory_id), and an advisory's detail is not looked up by it: the detail is keyed on vendor and vendor_advisory_id.", + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "description": "The vendor's own ID for the advisory (e.g. RHSA-2024:1234, GHSA-xxxx-xxxx-xxxx, or the CVE ID for Microsoft and Palo Alto Networks). With vendor, it is the key an advisory's detail is looked up by, as its advisory_id argument.", + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "description": "Whether a free-text search filtered this answer.", + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, vendor_advisory_id, affected_products and cve_ids (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word): it must equal, ignoring case, a whole word (a run of letters and digits) of one of those, so xz finds xz-utils but not xzibit, and a 1- or 2-character query with any other character, such as c#, matches nothing.", + "type": [ + "string", + "null" + ] + }, + "total": { + "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000; paging past it still works. Without a query, total is the exact count and total_capped is false.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
vendor_advisories_for_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": {}, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cve_rejected": { - "description": "true: the CVE record of cve_id was rejected (withdrawn) by its numbering authority, so these advisories name a rejected record, not an active vulnerability; null when that could not be checked.", - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "EchelonGraph's internal ID for this advisory, a UUID. It is not the vendor's advisory ID (vendor_advisory_id), and an advisory's detail is not looked up by it: the detail is keyed on vendor and vendor_advisory_id.", + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "description": "The vendor's own ID for the advisory (e.g. RHSA-2024:1234, GHSA-xxxx-xxxx-xxxx, or the CVE ID for Microsoft and Palo Alto Networks). With vendor, it is the key an advisory's detail is looked up by, as its advisory_id argument.", + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cve_rejected": { + "description": "true: the CVE record of cve_id was rejected (withdrawn) by its numbering authority, so these advisories name a rejected record, not an active vulnerability; null when that could not be checked.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": {}, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
16 tool updates
- Changed
check_affected1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", - "type": [ - "boolean", - "null" - ] - }, - "candidate_count": { - "type": [ - "number", - "null" - ] - }, - "candidates_capped": { - "description": "true: not every candidate CVE was loaded.", - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "description": "true: the match list stopped at its cap.", - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "degraded": { - "description": "true: the lookup ran out of time.", - "type": [ - "boolean", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "ecosystem_recognised": { - "type": [ - "boolean", - "null" - ] - }, - "excluded": {}, - "excluded_count": { - "description": "CPE candidates suppressed by the vendor or platform gate.", - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "description": "Which lookup path answered.", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_vendor": { - "description": "The vendor NVD's CPE asserts for this match.", - "type": [ - "string", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "effective_score": { - "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", - "type": [ - "number", - "null" - ] - }, - "effective_severity": { - "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "EPSS exploitation probability, 0 to 1.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "Registry match: the lowest version above this one that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds this version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which. Absent on a CPE match.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the interval that holds this version: the overlapping intervals of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Registry match: the advisory interval that holds this version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Listed in CISA-KEV: known to be exploited.", - "type": [ - "boolean", - "null" - ] - }, - "match_confidence": { - "type": [ - "number", - "null" - ] - }, - "match_method": { - "type": [ - "string", - "null" - ] - }, - "match_reason": { - "type": [ - "string", - "null" - ] - }, - "matched_criteria": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "description": "CISA-KEV records known use in ransomware campaigns.", - "type": [ - "boolean", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", - "type": [ - "boolean", - "null" - ] - }, - "score_unassessed_reason": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", - "type": [ - "string", - "null" - ] - }, - "vendor_severity": { - "type": [ - "string", - "null" - ] - }, - "vendor_unknown": { - "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", - "type": [ - "boolean", - "null" - ] - }, - "version_evidence": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "description": "Advisories decided as not affecting this version.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - }, - "product_named_count": { - "type": [ - "number", - "null" - ] - }, - "undecidable_excluded_count": { - "type": [ - "number", - "null" - ] - }, - "undecided_candidate_count": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "detail": { - "type": [ - "string", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_count": { - "type": [ - "number", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", + "type": [ + "boolean", + "null" + ] + }, + "candidate_count": { + "type": [ + "number", + "null" + ] + }, + "candidates_capped": { + "description": "true: not every candidate CVE was loaded.", + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "description": "true: the match list stopped at its cap.", + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "degraded": { + "description": "true: the lookup ran out of time.", + "type": [ + "boolean", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "excluded": {}, + "excluded_count": { + "description": "CPE candidates suppressed by the vendor or platform gate.", + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "description": "Which lookup path answered.", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cpe_vendor": { + "description": "The vendor NVD's CPE asserts for this match.", + "type": [ + "string", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "effective_score": { + "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", + "type": [ + "number", + "null" + ] + }, + "effective_severity": { + "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "EPSS exploitation probability, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "Registry match: the lowest version above this one that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds this version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which. Absent on a CPE match.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds this version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Registry match: the advisory interval that holds this version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Listed in CISA-KEV: known to be exploited.", + "type": [ + "boolean", + "null" + ] + }, + "match_confidence": { + "type": [ + "number", + "null" + ] + }, + "match_method": { + "type": [ + "string", + "null" + ] + }, + "match_reason": { + "type": [ + "string", + "null" + ] + }, + "matched_criteria": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "description": "CISA-KEV records known use in ransomware campaigns.", + "type": [ + "boolean", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", + "type": [ + "boolean", + "null" + ] + }, + "score_unassessed_reason": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", + "type": [ + "string", + "null" + ] + }, + "vendor_severity": { + "type": [ + "string", + "null" + ] + }, + "vendor_unknown": { + "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", + "type": [ + "boolean", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "description": "Advisories decided as not affecting this version.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + }, + "product_named_count": { + "type": [ + "number", + "null" + ] + }, + "undecidable_excluded_count": { + "type": [ + "number", + "null" + ] + }, + "undecided_candidate_count": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "detail": { + "type": [ + "string", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_count": { + "type": [ + "number", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
check_sbom1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matched_package": { - "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", - "type": [ - "string", - "null" - ] - }, - "matched_version_from": { - "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", - "type": [ - "string", - "null" - ] - }, - "matched_via": { - "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", - "type": [ - "boolean", - "null" - ] - }, - "match_reason": { - "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "purl_name": { - "description": "Upstream rows: the purl's own (binary) package name, not looked up.", - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matched_package": { + "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", + "type": [ + "string", + "null" + ] + }, + "matched_version_from": { + "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", + "type": [ + "string", + "null" + ] + }, + "matched_via": { + "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", + "type": [ + "boolean", + "null" + ] + }, + "match_reason": { + "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "matches_truncated": { + "additionalProperties": false, + "description": "Present only on a row whose matches the structured result's cut (DATA CUT) shortened or left out: total, the row's matches in the answer; returned, the ones data keeps (its first, highest effective_score first); and, while they fit, of all its matches, the CVE IDs KEV-listed (kev_listed_cve_ids) or used in ransomware (ransomware_cve_ids), and the distinct fixed_in versions (fixed_in_versions). The same call with full: true returns every match.", + "properties": { + "fixed_in_versions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "kev_listed_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ransomware_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "purl_name": { + "description": "Upstream rows: the purl's own (binary) package name, not looked up.", + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_exposure1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "countries": { - "type": [ - "number", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "exposed_hosts": { - "type": [ - "number", - "null" - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev_catalog_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_seen_in_observations": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "description": "When EchelonGraph last wrote or refreshed a service's row, not when the service was observed and not when its vulnerable version was last confirmed: it is set to the time of the write when a search matches the banner, and again when a re-check finds the port still listed by Shodan InternetDB, without re-reading the banner, so a patched service can stay counted while its port stays open. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "type": [ - "string", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "top_countries": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "country": { - "type": [ - "string", - "null" - ] - }, - "hosts": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "top_products": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "hosts": { - "type": [ - "number", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "tracked": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "exposure_state": { - "anyOf": [ - { - "enum": [ - "exposed", - "measured_zero", - "not_assessed", - "tracking_unknown" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "exposure_state", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "countries": { + "type": [ + "number", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "exposed_hosts": { + "type": [ + "number", + "null" + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev_catalog_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_seen_in_observations": { + "type": [ + "boolean", + "null" + ] + }, + "last_seen": { + "description": "When EchelonGraph last wrote or refreshed a service's row, not when the service was observed and not when its vulnerable version was last confirmed: it is set to the time of the write when a search matches the banner, and again when a re-check finds the port still listed by Shodan InternetDB, without re-reading the banner, so a patched service can stay counted while its port stays open. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "type": [ + "string", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "top_countries": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "country": { + "type": [ + "string", + "null" + ] + }, + "hosts": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "top_products": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "hosts": { + "type": [ + "number", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "tracked": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "exposure_state": { + "anyOf": [ + { + "enum": [ + "exposed", + "measured_zero", + "not_assessed", + "tracking_unknown" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "exposure_state", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_intel1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "affected_packages": { - "items": { - "additionalProperties": {}, - "properties": { - "dependents_count": { - "type": [ - "number", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - }, - "fixed": { - "description": "The range's fix: the first version past it. null where no fix is on record.", - "type": [ - "string", - "null" - ] - }, - "introduced": { - "description": "The range's lower bound, inclusive; \"0\" is the first version.", - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", - "type": [ - "string", - "null" - ] - }, - "source": { - "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; its fix is that range's fixed, or, while another range still holds that, the other range's fixed (none past a range without one); a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." - }, - "fixed_version": { - "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "version_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cve_id": { - "type": "string" - }, - "cwes": { - "items": { - "additionalProperties": {}, - "properties": { - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits": { - "items": { - "additionalProperties": {}, - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "eg_first_seen_at": { - "description": "When EchelonGraph first recorded the reference, as a UTC timestamp: a date of EchelonGraph's, not the source's.", - "type": "string" - }, - "first_seen_at": { - "description": "Deprecated: the same value as source_published_at, null when that is.", - "type": [ - "string", - "null" - ] - }, - "kind": { - "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", - "type": [ - "string", - "null" - ] - }, - "source_name": { - "type": [ - "string", - "null" - ] - }, - "source_published_at": { - "description": "The source's own date for the reference (Exploit-DB's date_published, a GitHub proof-of-concept repository's created_at, or the first commit of a nuclei template or Metasploit module where EchelonGraph derived it from the source's git history); null where the source gives none, and EchelonGraph supplies no stand-in date.", - "type": [ - "string", - "null" - ] - }, - "source_url": { - "type": [ - "string", - "null" - ] - }, - "verified_status": { - "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits_by_kind": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_by_status": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_capped": { - "description": "true: exploits lists fewer references than exploits_total.", - "type": "boolean" - }, - "exploits_total": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Every exploit reference on record for the CVE, not only those listed in exploits." - }, - "fixed_versions": { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_version": { - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "vulnerable_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline": { - "items": { - "additionalProperties": {}, - "properties": { - "enriched_at": { - "type": [ - "string", - "null" - ] - }, - "enrichment_kind": { - "type": [ - "string", - "null" - ] - }, - "fields_changed": {}, - "score_delta": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline_count_30d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_count_7d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_total": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "cve_id" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "properties": { + "affected_packages": { + "items": { + "additionalProperties": {}, + "properties": { + "dependents_count": { + "type": [ + "number", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + }, + "fixed": { + "description": "The range's fix: the first version past it. null where no fix is on record.", + "type": [ + "string", + "null" + ] + }, + "introduced": { + "description": "The range's lower bound, inclusive; \"0\" is the first version.", + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; its fix is that range's fixed, or, while another range still holds that, the other range's fixed (none past a range without one); a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "version_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cve_id": { + "type": "string" + }, + "cwes": { + "items": { + "additionalProperties": {}, + "properties": { + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits": { + "items": { + "additionalProperties": {}, + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "eg_first_seen_at": { + "description": "When EchelonGraph first recorded the reference, as a UTC timestamp: a date of EchelonGraph's, not the source's.", + "type": "string" + }, + "first_seen_at": { + "description": "Deprecated: the same value as source_published_at, null when that is.", + "type": [ + "string", + "null" + ] + }, + "kind": { + "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", + "type": [ + "string", + "null" + ] + }, + "source_name": { + "type": [ + "string", + "null" + ] + }, + "source_published_at": { + "description": "The source's own date for the reference (Exploit-DB's date_published, a GitHub proof-of-concept repository's created_at, or the first commit of a nuclei template or Metasploit module where EchelonGraph derived it from the source's git history); null where the source gives none, and EchelonGraph supplies no stand-in date.", + "type": [ + "string", + "null" + ] + }, + "source_url": { + "type": [ + "string", + "null" + ] + }, + "verified_status": { + "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits_by_kind": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_by_status": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_capped": { + "description": "true: exploits lists fewer references than exploits_total.", + "type": "boolean" + }, + "exploits_total": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Every exploit reference on record for the CVE, not only those listed in exploits." + }, + "fixed_versions": { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_version": { + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "vulnerable_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline": { + "items": { + "additionalProperties": {}, + "properties": { + "enriched_at": { + "type": [ + "string", + "null" + ] + }, + "enrichment_kind": { + "type": [ + "string", + "null" + ] + }, + "fields_changed": {}, + "score_delta": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline_count_30d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_count_7d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "cve_id" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_remediation1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "installed_asked": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "ecosystem": { - "type": "string" - }, - "package": { - "type": "string" - }, - "version": { - "type": "string" - } - }, - "required": [ - "ecosystem", - "package", - "version" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The installed version this call sent (in request headers), as given; null when none." - }, - "item_text_cap": { - "type": [ - "number", - "null" - ] - }, - "items_per_advisory_cap": { - "type": [ - "number", - "null" - ] - }, - "parsed_vendors": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors whose remediation EchelonGraph parses." - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API could not read (its failed_sections); null when the answer does not say." - }, - "sections_relayed": { - "items": { - "type": "string" - }, - "type": "array" - }, - "vendor_advisory_limit": { - "type": [ - "number", - "null" - ] - }, - "vendors_not_parsed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors in this answer whose remediation EchelonGraph does not parse." - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "parsed_vendors", - "vendors_not_parsed", - "vendor_advisory_limit", - "item_text_cap", - "items_per_advisory_cap", - "installed_asked" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cisa": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "due_date": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "required_action": { - "description": "CISA's requiredAction, verbatim. CISA's required_action is directed at US federal civilian agencies (under BOD 26-04, which replaced BOD 22-01 on 10 June 2026) and is not EchelonGraph's advice.", - "type": [ - "string", - "null" - ] - }, - "short_description": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "coverage": {}, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "failed_sections": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fix_references": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "source": { - "type": [ - "string", - "null" - ] - }, - "tags": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fix_status": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "basis": { - "type": [ - "string", - "null" - ] - }, - "described_by": { - "type": [ - "string", - "null" - ] - }, - "listed_in_patch_table": { - "type": [ - "boolean", - "null" - ] - }, - "solution_by": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cna": { - "type": [ - "string", - "null" - ] - }, - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "available", - "fix_referenced", - "fix_merged", - "none_confirmed", - "unknown" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "stated_in_record": { - "type": [ - "boolean", - "null" - ] - }, - "unread_inputs": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read." - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "description": "The range's last affected version, where no fix is on record; never a fix.", - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fixed_version": { - "description": "One range's fix, kept for compatibility; not the fix for every affected range.", - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fixed_in": { - "description": "With an installed version: the first version above it that no affected range on record holds, always above it, as the advisory states it: the fixed bound of the range holding it, moved past any overlapping range that still holds that bound (fixed_in_detail then names it). null when no range on record holds it, no fix is on record past the ranges holding it, or the version was not assessed, with fixed_in_reason saying which. Absent when no installed version was asked.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the range holding the installed version: the overlapping ranges of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "installed": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "description": "The ecosystem asked for, in its canonical OSV spelling.", - "type": [ - "string", - "null" - ] - }, - "ecosystem_recognised": { - "type": [ - "boolean", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The affected range holding the version (fixed is exclusive, last_affected inclusive); absent when none holds it." - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "verdict": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "affected", - "not_affected", - "undetermined", - "not_assessed" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "affected (a range on record holds the version), not_affected (no range on record holds it), undetermined (a range could not be decided at it) or not_assessed (the record names no such package for this CVE, or the lookup did not run)." - }, - "version": { - "type": [ - "string", - "null" - ] - }, - "version_evidence": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The installed version asked for, as the API read it from the request headers, and its verdict against this CVE; absent when none was asked." - }, - "not_assessed_reason": { - "type": [ - "string", - "null" - ] - }, - "patches": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "state": { - "description": "assessed, or not_assessed for a CVE record rejected by its numbering authority.", - "type": [ - "string", - "null" - ] - }, - "vendor_remediations": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "items": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "fixed_build": { - "description": "MSRC's FixedBuild; null elsewhere.", - "type": [ - "string", - "null" - ] - }, - "kind": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "The vendor's own category: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other." - }, - "product_count": { - "type": [ - "number", - "null" - ] - }, - "product_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendor's own product identifiers the item applies to, the first 16." - }, - "source_category": { - "description": "The vendor's own name for the category (CSAF vendor_fix, MSRC Vendor Fix, Palo Alto work_around).", - "type": [ - "string", - "null" - ] - }, - "source_subcategory": { - "description": "MSRC's SubType, e.g. Security Update; null elsewhere.", - "type": [ - "string", - "null" - ] - }, - "text": { - "description": "The vendor's text, verbatim but for HTML markup removed, cut at coverage.item_text_cap characters (text_truncated).", - "type": [ - "string", - "null" - ] - }, - "text_chars": { - "description": "The length of the vendor's text in characters.", - "type": [ - "number", - "null" - ] - }, - "text_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "items_total": { - "type": [ - "number", - "null" - ] - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (parsed, and the advisory lists no remediation for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory); withdrawn (the vendor rescinded it)." - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "installed_asked": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "ecosystem": { - "type": "string" - }, - "package": { - "type": "string" - }, - "version": { - "type": "string" - } - }, - "required": [ - "ecosystem", - "package", - "version" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The installed version this call sent (in request headers), as given; null when none." - }, - "item_text_cap": { - "type": [ - "number", - "null" - ] - }, - "items_per_advisory_cap": { - "type": [ - "number", - "null" - ] - }, - "parsed_vendors": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors whose remediation EchelonGraph parses." - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API could not read (its failed_sections); null when the answer does not say." - }, - "sections_relayed": { - "items": { - "type": "string" - }, - "type": "array" - }, - "vendor_advisory_limit": { - "type": [ - "number", - "null" - ] - }, - "vendors_not_parsed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors in this answer whose remediation EchelonGraph does not parse." - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "parsed_vendors", - "vendors_not_parsed", - "vendor_advisory_limit", - "item_text_cap", - "items_per_advisory_cap", - "installed_asked" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "installed_asked": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "ecosystem": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "ecosystem", + "package", + "version" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version this call sent (in request headers), as given; null when none." + }, + "item_text_cap": { + "type": [ + "number", + "null" + ] + }, + "items_per_advisory_cap": { + "type": [ + "number", + "null" + ] + }, + "parsed_vendors": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors whose remediation EchelonGraph parses." + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API could not read (its failed_sections); null when the answer does not say." + }, + "sections_relayed": { + "items": { + "type": "string" + }, + "type": "array" + }, + "vendor_advisory_limit": { + "type": [ + "number", + "null" + ] + }, + "vendors_not_parsed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors in this answer whose remediation EchelonGraph does not parse." + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "parsed_vendors", + "vendors_not_parsed", + "vendor_advisory_limit", + "item_text_cap", + "items_per_advisory_cap", + "installed_asked" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cisa": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "due_date": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "required_action": { + "description": "CISA's requiredAction, verbatim. CISA's required_action is directed at US federal civilian agencies (under BOD 26-04, which replaced BOD 22-01 on 10 June 2026) and is not EchelonGraph's advice.", + "type": [ + "string", + "null" + ] + }, + "short_description": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "coverage": {}, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "failed_sections": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fix_references": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "source": { + "type": [ + "string", + "null" + ] + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "section": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "vendor_released": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fixed_branches_truncated": { + "additionalProperties": false, + "description": "Present only where the structured result's cut (DATA CUT) kept this package's first ranges, not all: total, its ranges in the answer; returned, the ones data keeps. The same call with full: true returns every range.", + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fixed_in": { + "description": "With an installed version: the first version above it that no affected range on record holds, always above it, as the advisory states it: the fixed bound of the range holding it, moved past any overlapping range that still holds that bound (fixed_in_detail then names it). null when no range on record holds it, no fix is on record past the ranges holding it, or the version was not assessed, with fixed_in_reason saying which. Absent when no installed version was asked.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the range holding the installed version: the overlapping ranges of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "installed": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "description": "The ecosystem asked for, in its canonical OSV spelling.", + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The affected range holding the version (fixed is exclusive, last_affected inclusive); absent when none holds it." + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "verdict": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "affected", + "not_affected", + "undetermined", + "not_assessed" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "affected (a range on record holds the version), not_affected (no range on record holds it), undetermined (a range could not be decided at it) or not_assessed (the record names no such package for this CVE, or the lookup did not run)." + }, + "version": { + "type": [ + "string", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version asked for, as the API read it from the request headers, and its verdict against this CVE; absent when none was asked." + }, + "not_assessed_reason": { + "type": [ + "string", + "null" + ] + }, + "patches": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "state": { + "description": "assessed, or not_assessed for a CVE record rejected by its numbering authority.", + "type": [ + "string", + "null" + ] + }, + "vendor_remediations": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "items": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "fixed_build": { + "description": "MSRC's FixedBuild; null elsewhere.", + "type": [ + "string", + "null" + ] + }, + "kind": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "The vendor's own category: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other." + }, + "product_count": { + "type": [ + "number", + "null" + ] + }, + "product_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendor's own product identifiers the item applies to, the first 16." + }, + "source_category": { + "description": "The vendor's own name for the category (CSAF vendor_fix, MSRC Vendor Fix, Palo Alto work_around).", + "type": [ + "string", + "null" + ] + }, + "source_subcategory": { + "description": "MSRC's SubType, e.g. Security Update; null elsewhere.", + "type": [ + "string", + "null" + ] + }, + "text": { + "description": "The vendor's text, verbatim but for HTML markup removed, cut at coverage.item_text_cap characters (text_truncated).", + "type": [ + "string", + "null" + ] + }, + "text_chars": { + "description": "The length of the vendor's text in characters.", + "type": [ + "number", + "null" + ] + }, + "text_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "items_total": { + "type": [ + "number", + "null" + ] + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (parsed, and the advisory lists no remediation for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory); withdrawn (the vendor rescinded it)." + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "installed_asked": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "ecosystem": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "ecosystem", + "package", + "version" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version this call sent (in request headers), as given; null when none." + }, + "item_text_cap": { + "type": [ + "number", + "null" + ] + }, + "items_per_advisory_cap": { + "type": [ + "number", + "null" + ] + }, + "parsed_vendors": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors whose remediation EchelonGraph parses." + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API could not read (its failed_sections); null when the answer does not say." + }, + "sections_relayed": { + "items": { + "type": "string" + }, + "type": "array" + }, + "vendor_advisory_limit": { + "type": [ + "number", + "null" + ] + }, + "vendors_not_parsed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors in this answer whose remediation EchelonGraph does not parse." + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "parsed_vendors", + "vendors_not_parsed", + "vendor_advisory_limit", + "item_text_cap", + "items_per_advisory_cap", + "installed_asked" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_summary1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "poller": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cves_ingested": { - "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", - "type": [ - "number", - "null" - ] - }, - "cves_skipped": { - "description": "CVE records this instance's NVD poller skipped since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "http_retries": { - "description": "HTTP retries this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "interval": { - "description": "How often this instance's NVD poller polls.", - "type": [ - "string", - "null" - ] - }, - "last_poll_at": { - "description": "When this instance's NVD poller last polled: never the feed's freshness.", - "type": [ - "string", - "null" - ] - }, - "last_poll_dur_ms": { - "description": "How long that poll took, in milliseconds.", - "type": [ - "number", - "null" - ] - }, - "poll_count": { - "description": "Polls this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "poll_errors": { - "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." - }, - "summary": { - "additionalProperties": {}, - "description": "summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label (v3.x, else v4.0; before NVD's record arrives, or where it gives none, a pre-NVD label from the CVE.org record or a GitHub advisory can stand in): provenance, never EchelonGraph's severity band. summary.nvd_none counts the active CVEs with no Critical, High, Medium or Low label there, CVEs NVD never labelled under CVSS v3 among them, and many of those carry an NVD CVSS v2 score instead: it is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. Whenever summary.nvd_none is above zero the note says what it counts, with its count.", - "properties": { - "critical": { - "type": [ - "number", - "null" - ] - }, - "high": { - "type": [ - "number", - "null" - ] - }, - "last_updated": { - "type": [ - "string", - "null" - ] - }, - "low": { - "type": [ - "number", - "null" - ] - }, - "medium": { - "type": [ - "number", - "null" - ] - }, - "none": { - "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", - "type": [ - "number", - "null" - ] - }, - "nvd_critical": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_high": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_low": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_medium": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_none": { - "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", - "type": [ - "number", - "null" - ] - }, - "rejected": { - "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "unscored": { - "description": "The same count as none, under its own name.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "poller": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cves_ingested": { + "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", + "type": [ + "number", + "null" + ] + }, + "cves_skipped": { + "description": "CVE records this instance's NVD poller skipped since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "http_retries": { + "description": "HTTP retries this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "interval": { + "description": "How often this instance's NVD poller polls.", + "type": [ + "string", + "null" + ] + }, + "last_poll_at": { + "description": "When this instance's NVD poller last polled: never the feed's freshness.", + "type": [ + "string", + "null" + ] + }, + "last_poll_dur_ms": { + "description": "How long that poll took, in milliseconds.", + "type": [ + "number", + "null" + ] + }, + "poll_count": { + "description": "Polls this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "poll_errors": { + "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." + }, + "summary": { + "additionalProperties": {}, + "description": "summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label (v3.x, else v4.0; before NVD's record arrives, or where it gives none, a pre-NVD label from the CVE.org record or a GitHub advisory can stand in): provenance, never EchelonGraph's severity band. summary.nvd_none counts the active CVEs with no Critical, High, Medium or Low label there, CVEs NVD never labelled under CVSS v3 among them, and many of those carry an NVD CVSS v2 score instead: it is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. Whenever summary.nvd_none is above zero the note says what it counts, with its count.", + "properties": { + "critical": { + "type": [ + "number", + "null" + ] + }, + "high": { + "type": [ + "number", + "null" + ] + }, + "last_updated": { + "type": [ + "string", + "null" + ] + }, + "low": { + "type": [ + "number", + "null" + ] + }, + "medium": { + "type": [ + "number", + "null" + ] + }, + "none": { + "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", + "type": [ + "number", + "null" + ] + }, + "nvd_critical": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_high": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_low": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_medium": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_none": { + "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", + "type": [ + "number", + "null" + ] + }, + "rejected": { + "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "unscored": { + "description": "The same count as none, under its own name.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
epss_history1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day the record holds; null when none are listed." - }, - "days_missing": { - "description": "Score dates from first_day to last_day the record does not hold.", - "items": { - "type": "string" - }, - "type": "array" - }, - "days_partial": { - "description": "Score dates held for some CVEs only.", - "items": { - "type": "string" - }, - "type": "array" - }, - "first_day": { - "description": "The earliest FIRST score date the run log lists; null when it lists none.", - "type": [ - "string", - "null" - ] - }, - "last_day": { - "type": [ - "string", - "null" - ] - }, - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "How many of them fall where changes are missing; null when the API did not say." - }, - "points_truncated": { - "type": "boolean" - }, - "series_complete": { - "description": "True only when the API says nothing in the record predates complete_since.", - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "complete_since", - "series_complete", - "points", - "points_before_complete_since", - "points_truncated", - "first_day", - "last_day", - "days_held", - "days_partial", - "days_missing" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when the record holds every change a refresh applied. Between series_starts_at and complete_since changes are missing, so a missing point there does not mean unchanged. Absent from an API older than #2867." - }, - "coverage": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From here on every change a refresh applied is a point; before it changes are missing." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day that a refresh applied completely." - }, - "days_missing": { - "anyOf": [ - { - "items": { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day that no refresh applied." - }, - "days_partial": { - "anyOf": [ - { - "items": { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Score dates whose refreshes all failed part-way: some CVEs hold that day, some do not." - }, - "first_day": { - "anyOf": [ - { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The earliest score date in the run log." - }, - "last_day": { - "anyOf": [ - { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The latest score date in the run log." - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "This CVE's points in the part of the record that misses changes." - }, - "recorded_from": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "series_starts_at: when recording began." - }, - "refresh_runs_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "run_log_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The first logged refresh: score dates before it are not listed, held or missing." - }, - "runs_undated": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ] - }, - "series_complete": { - "description": "True only when nothing in the record predates complete_since.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Which part of the record is complete and which FIRST score dates it holds." - }, - "current": { - "additionalProperties": {}, - "properties": { - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The record's EPSS probability now; null when it holds none.", - "type": [ - "number", - "null" - ] - }, - "epss_updated_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." - } - }, - "type": "object" - }, - "cve_id": { - "type": "string" - }, - "history_rows": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Raw history rows read, before repeated records of one change were collapsed." - }, - "latest_point_matches_current": { - "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", - "type": [ - "boolean", - "null" - ] - }, - "points": { - "description": "Recorded changes, oldest first. Never a daily series.", - "items": { - "additionalProperties": {}, - "properties": { - "at": { - "description": "When EchelonGraph recorded this change.", - "type": "string" - }, - "epss_percentile": { - "description": "Its percentile (0 to 1), null where the record held none.", - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The EPSS probability (0 to 1) from that change on.", - "type": "number" - }, - "score_date": { - "description": "FIRST's score date (YYYY-MM-DD) of the logged refresh that wrote this point; null where no logged refresh covers it.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "at", - "epss_score" - ], - "type": "object" - }, - "type": "array" - }, - "points_truncated": { - "description": "True when only the newest rows were read, so the earliest points are missing.", - "type": [ - "boolean", - "null" - ] - }, - "series_kind": { - "description": "Always change_only: one point per recorded change, none for a day without one.", - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." - } - }, - "required": [ - "cve_id", - "series_kind", - "series_starts_at", - "current", - "points" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day the record holds; null when none are listed." - }, - "days_missing": { - "description": "Score dates from first_day to last_day the record does not hold.", - "items": { - "type": "string" - }, - "type": "array" - }, - "days_partial": { - "description": "Score dates held for some CVEs only.", - "items": { - "type": "string" - }, - "type": "array" - }, - "first_day": { - "description": "The earliest FIRST score date the run log lists; null when it lists none.", - "type": [ - "string", - "null" - ] - }, - "last_day": { - "type": [ - "string", - "null" - ] - }, - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "How many of them fall where changes are missing; null when the API did not say." - }, - "points_truncated": { - "type": "boolean" - }, - "series_complete": { - "description": "True only when the API says nothing in the record predates complete_since.", - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "complete_since", - "series_complete", - "points", - "points_before_complete_since", - "points_truncated", - "first_day", - "last_day", - "days_held", - "days_partial", - "days_missing" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when the record holds every change a refresh applied. Between series_starts_at and complete_since changes are missing, so a missing point there does not mean unchanged. Absent from an API older than #2867." + }, + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From here on every change a refresh applied is a point; before it changes are missing." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that a refresh applied completely." + }, + "days_missing": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that no refresh applied." + }, + "days_partial": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates whose refreshes all failed part-way: some CVEs hold that day, some do not." + }, + "first_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest score date in the run log." + }, + "last_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The latest score date in the run log." + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "This CVE's points in the part of the record that misses changes." + }, + "recorded_from": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "series_starts_at: when recording began." + }, + "refresh_runs_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "run_log_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The first logged refresh: score dates before it are not listed, held or missing." + }, + "runs_undated": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "series_complete": { + "description": "True only when nothing in the record predates complete_since.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Which part of the record is complete and which FIRST score dates it holds." + }, + "current": { + "additionalProperties": {}, + "properties": { + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The record's EPSS probability now; null when it holds none.", + "type": [ + "number", + "null" + ] + }, + "epss_updated_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." + } + }, + "type": "object" + }, + "cve_id": { + "type": "string" + }, + "history_rows": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Raw history rows read, before repeated records of one change were collapsed." + }, + "latest_point_matches_current": { + "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", + "type": [ + "boolean", + "null" + ] + }, + "points": { + "description": "Recorded changes, oldest first. Never a daily series.", + "items": { + "additionalProperties": {}, + "properties": { + "at": { + "description": "When EchelonGraph recorded this change.", + "type": "string" + }, + "epss_percentile": { + "description": "Its percentile (0 to 1), null where the record held none.", + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The EPSS probability (0 to 1) from that change on.", + "type": "number" + }, + "score_date": { + "description": "FIRST's score date (YYYY-MM-DD) of the logged refresh that wrote this point; null where no logged refresh covers it.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "at", + "epss_score" + ], + "type": "object" + }, + "type": "array" + }, + "points_truncated": { + "description": "True when only the newest rows were read, so the earliest points are missing.", + "type": [ + "boolean", + "null" + ] + }, + "series_kind": { + "description": "Always change_only: one point per recorded change, none for a day without one.", + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." + } + }, + "required": [ + "cve_id", + "series_kind", + "series_starts_at", + "current", + "points" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
exposure_radar1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "description": "A field this version cannot label is left out of data and named in the note. Each of the kev_exposure, exposed_databases and leaked_credentials radars also carries generated_at, when the API computed its totals, and, when the API can tell, last_run_at. kev_exposure.last_run_at, exposed_databases.last_run_at and leaked_credentials.last_run_at are timestamps, not counts: each is when that radar last completed a check, a cycle whose reads succeeded, among them a Shodan search (for exposed_databases, or its LeakIX fallback) that answered at least one query, or for leaked_credentials a read of the public GitHub event stream. A cycle that read nothing does not move it, and it is not the time of every record a radar's numbers count, which cover everything still on record, not only what the last check found. A radar whose answer carries no last_run_at has none in the result, and the note says nothing about it. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "exposed_databases": { - "additionalProperties": false, - "description": "exposed_databases: exposed_databases.distinct_hosts counts distinct ip:port services the check confirmed answering without authentication, and exposed_databases.engines the distinct engine types among them; exposed_databases.top_engines and exposed_databases.top_countries rank up to 15 engines and 10 countries by those services. exposed_databases.pii_likely and exposed_databases.pci_likely count services whose schema names (never record values) pass a high-confidence, precision-first gate for personal or payment-card data, so a service outside them is not shown to hold no such data. exposed_databases.window.from and exposed_databases.window.to are timestamps, not counts: when EchelonGraph's check last confirmed the oldest and the newest of the services counted, a span of checks made at different times; with a counted service that has no such time on record there is no window.", - "properties": { - "distinct_hosts": { - "type": "number" - }, - "engines": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "pci_likely": { - "type": "number" - }, - "pii_likely": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_engines": { - "items": { - "additionalProperties": false, - "properties": { - "engine": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "engine", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "description": "kev_exposure: kev_exposure.distinct_hosts counts distinct ip:port services, not machines (a machine answering on two ports counts twice), with at least one CISA-KEV-listed CVE on record, and kev_exposure.ransomware_hosts those with a ransomware-linked one; kev_exposure.kev_cves_exposed and kev_exposure.ransomware_cves count distinct CVEs with at least one such service; kev_exposure.correlations counts service×CVE pairs, not services, so a service with three KEV CVEs counts three times. kev_exposure.top_products, kev_exposure.top_countries and kev_exposure.top_cves rank up to 12 products, 10 countries and 12 CVEs by those services; kev_exposure.top_cves[].cvss_v3_score and kev_exposure.top_cves[].epss_score are the highest CVSS v3 base score and EPSS probability recorded on that CVE's observations. kev_exposure.trend counts service×CVE pairs still on record by the week in which each was first recorded, over 12 weeks, so earlier weeks read low. kev_exposure.newest_kev lists the 15 CVEs that EchelonGraph's CVE records most recently mark as CISA-KEV-listed, each with an exposure_state: exposed, where kev_exposure.newest_kev[].exposed_hosts counts distinct ip:port services on record with it; or not_assessed, where the API's answer holds no measurement for that CVE (its 0 is not one) and no count is relayed, and this answer does not say whether the radar tracks that CVE: tracking is answered per CVE. kev_exposure.newest_kev[].cvss_v3_score and kev_exposure.newest_kev[].epss_score are the CVE record's CVSS v3 base score and EPSS probability. kev_exposure.window.from and kev_exposure.window.to are timestamps, not counts: when Shodan collected the banners of the oldest and the newest of the service×CVE pairs counted, a span of observations made at different times; with a counted pair that has no such time on record there is no window. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "correlations": { - "type": "number" - }, - "distinct_hosts": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "kev_cves_exposed": { - "type": "number" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "newest_kev": { - "items": { - "additionalProperties": false, - "properties": { - "added_date": { - "type": "string" - }, - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "exposed_hosts": { - "type": "number" - }, - "exposure_state": { - "enum": [ - "exposed", - "measured_zero", - "not_assessed" - ], - "type": "string" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - }, - "vuln_name": { - "type": "string" - } - }, - "required": [ - "cve_id", - "exposure_state" - ], - "type": "object" - }, - "type": "array" - }, - "ransomware_cves": { - "type": "number" - }, - "ransomware_hosts": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_cves": { - "items": { - "additionalProperties": false, - "properties": { - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "hosts": { - "type": "number" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - } - }, - "required": [ - "cve_id", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "hosts": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "trend": { - "items": { - "additionalProperties": false, - "properties": { - "new_exposures": { - "type": "number" - }, - "week": { - "type": "string" - } - }, - "required": [ - "week", - "new_exposures" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "description": "leaked_credentials: leaked_credentials.total counts (repository, secret) pairs, not distinct secrets, so one secret in three repositories counts three times; leaked_credentials.distinct_secrets counts each secret once and leaked_credentials.distinct_repos counts repositories; leaked_credentials.top_providers and leaked_credentials.top_types rank up to 15 providers and secret types by those pairs. None is validated: each is a credential-shaped string that passed EchelonGraph's filters, at most structurally checked and never tested against its provider. leaked_credentials.window.from and leaked_credentials.window.to are timestamps, not counts: when EchelonGraph's detector last found the oldest and the newest of the pairs counted.", - "properties": { - "distinct_repos": { - "type": "number" - }, - "distinct_secrets": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_providers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "provider": { - "type": "string" - } - }, - "required": [ - "provider", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_types": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "secret_type": { - "type": "string" - } - }, - "required": [ - "secret_type", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "description": "mcp_servers: counts and timestamps only, no hostname. mcp_servers.total counts hostnames the AI-exposure radar has checked for an MCP server, each once by its latest verdict on record, and not every one is an MCP server; EchelonGraph's own control servers are left out, and mcp_servers.own_controls_excluded counts them; hostnames whose owner opted out of scanning are not checked again while the opt-out stands, so their last verdict is left out too, and mcp_servers.withheld_opted_out counts them. mcp_servers.total is mcp_servers.protected plus mcp_servers.pending_readjudication plus mcp_servers.not_assessed. mcp_servers.protected counts hostnames whose /mcp endpoint asked for credentials and whose OAuth protected-resource metadata validated under RFC 9728; mcp_servers.prm_via divides them by where that document was found: mcp_servers.prm_via.header, mcp_servers.prm_via.wellknown_path and mcp_servers.prm_via.wellknown_root. mcp_servers.pending_readjudication counts verdicts of a rule since replaced, not yet re-checked. mcp_servers.not_assessed counts the rest, whose protection the radar could not assess (not assessed does not mean unprotected), and mcp_servers.not_assessed_by_reason puts each in one bucket. mcp_servers.not_assessed_by_reason.identified_no_challenge holds servers that identified themselves as MCP servers and did not ask for credentials at the handshake. That is normal in MCP: authorization is optional in the spec, and a server can enforce it at tools/call instead, which EchelonGraph never sends, so this bucket is not a finding of exposure. mcp_servers.not_assessed_by_reason.resource_mismatch, mcp_servers.not_assessed_by_reason.cross_origin_pointer, mcp_servers.not_assessed_by_reason.bare_challenge_no_prm, mcp_servers.not_assessed_by_reason.pointer_unreachable, mcp_servers.not_assessed_by_reason.pointer_invalid, mcp_servers.not_assessed_by_reason.no_authorization_servers, mcp_servers.not_assessed_by_reason.wellknown_unreachable and mcp_servers.not_assessed_by_reason.metadata_invalid hold endpoints that asked for credentials but whose RFC 9728 metadata did not validate, by why, so none of them is shown to lack protection; mcp_servers.not_assessed_by_reason.challenge_unadjudicated holds endpoints that asked for credentials before that check existed, not yet re-checked. mcp_servers.not_assessed_by_reason.no_http_answer holds hostnames that gave no HTTP answer, and mcp_servers.not_assessed_by_reason.not_identified_as_mcp hostnames whose HTTP answer identified no MCP server. mcp_servers.era divides every counted hostname by protocol era: mcp_servers.era.legacy; mcp_servers.era.dual, a lower bound; mcp_servers.era.modern, not proven modern-only; mcp_servers.era.unknown; and mcp_servers.era.not_measured, recorded before the era probe and not re-checked since. mcp_servers.transport divides them by transport: mcp_servers.transport.streamable_http, mcp_servers.transport.legacy_sse, mcp_servers.transport.unknown and mcp_servers.transport.not_measured. mcp_servers.window.from and mcp_servers.window.to are when the oldest and the newest of the verdicts counted were last checked. mcp_servers.last_run_at is a timestamp, not a count: when the AI-exposure radar, which checks other AI services too, last completed a check; mcp_servers.enabled is whether one completed within 45 minutes of the answer, and mcp_servers.counted_at is when the API read the counts. A partition whose buckets do not add up to the count it divides is left out and named; an answer that does not say it is the MCP-server counts, or whose mcp_servers.total, mcp_servers.protected, mcp_servers.pending_readjudication and mcp_servers.not_assessed are missing or contradict each other, is a failure.", - "properties": { - "counted_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "era": { - "additionalProperties": false, - "properties": { - "dual": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "legacy": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "modern": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "legacy", - "dual", - "modern", - "unknown", - "not_measured" - ], - "type": "object" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "not_assessed": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_assessed_by_reason": { - "additionalProperties": false, - "properties": { - "bare_challenge_no_prm": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "challenge_unadjudicated": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "cross_origin_pointer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "identified_no_challenge": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "metadata_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_authorization_servers": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_http_answer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_identified_as_mcp": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "resource_mismatch": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "identified_no_challenge", - "resource_mismatch", - "cross_origin_pointer", - "bare_challenge_no_prm", - "pointer_unreachable", - "pointer_invalid", - "no_authorization_servers", - "wellknown_unreachable", - "metadata_invalid", - "challenge_unadjudicated", - "no_http_answer", - "not_identified_as_mcp" - ], - "type": "object" - }, - "own_controls_excluded": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pending_readjudication": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "prm_via": { - "additionalProperties": false, - "properties": { - "header": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_path": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_root": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "header", - "wellknown_path", - "wellknown_root" - ], - "type": "object" - }, - "protected": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "transport": { - "additionalProperties": false, - "properties": { - "legacy_sse": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "streamable_http": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "streamable_http", - "legacy_sse", - "unknown", - "not_measured" - ], - "type": "object" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "withheld_opted_out": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "protected", - "pending_readjudication", - "not_assessed" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "description": "shadow_ai: the result is regrouped by what each number counts. shadow_ai.confirmed_exposed counts services EchelonGraph's probes found answering without an authentication gate (liveness active, or rechecking during a re-check): confirmed_exposed.total is the sum of confirmed_exposed.by_category, and confirmed_exposed.last_24h counts those first recorded in the last 24 h. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. confirmed_exposed.window.from and confirmed_exposed.window.to are timestamps, not counts: when EchelonGraph's verifier ran the probe that last decided the oldest and the newest of those services, a span of probes made at different times. shadow_ai.observed counts every Certificate Transparency or Shodan observation on record, whatever its verification state: its numbers are observed, not exposed. They are observed.total; observed.by_category (the same observations by category); observed.last_24h (those first recorded in the last 24 h); observed.trend_30d (observations per UTC day over the last 30 days); and observed.top_products, observed.top_countries and observed.top_issuers (up to ten products, countries and issuers ranked by observations, where an issuer is the certificate's CA for a Certificate Transparency observation and the hosting operator Shodan reports for a Shodan one). shadow_ai.authentication counts observations by probe outcome: authentication.observed where a probe observed an authentication gate (a 401/403, a login page or an auth marker), and authentication.not_determined where the service answered but no probe could tell. Neither authentication count is part of confirmed_exposed, and observed.total minus confirmed_exposed.total is not a count of secured services. The shadow-AI poller block carries only running and last_run_at: last_run_at is when the radar's leader last completed a Certificate Transparency (crt.sh) cycle, and its running is true only when that was within 30 minutes of the answer. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "authentication": { - "additionalProperties": false, - "properties": { - "not_determined": { - "type": "number" - }, - "observed": { - "type": "number" - } - }, - "type": "object" - }, - "confirmed_exposed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "observed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "last_observation": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "country": { - "type": "string" - } - }, - "required": [ - "country", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_issuers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "issuer": { - "type": "string" - } - }, - "required": [ - "issuer", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "trend_30d": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "date": { - "type": "string" - } - }, - "required": [ - "date", - "count" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "poller": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "running": { - "type": "boolean" - } - }, - "required": [ - "running", - "last_run_at" - ], - "type": "object" - } - }, - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at", - "enabled" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - }, - "running": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "last_run_at", - "running" - ], - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "radars": { - "description": "Each radar that could not be read, and why.", - "items": { - "additionalProperties": false, - "properties": { - "kind": { - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "unexpected_shape" - ], - "type": "string" - }, - "message": { - "type": "string" - }, - "path": { - "type": "string" - }, - "radar": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "radar", - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "type": "array" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "description": "A field this version cannot label is left out of data and named in the note. Each of the kev_exposure, exposed_databases and leaked_credentials radars also carries generated_at, when the API computed its totals, and, when the API can tell, last_run_at. kev_exposure.last_run_at, exposed_databases.last_run_at and leaked_credentials.last_run_at are timestamps, not counts: each is when that radar last completed a check, a cycle whose reads succeeded, among them a Shodan search (for exposed_databases, or its LeakIX fallback) that answered at least one query, or for leaked_credentials a read of the public GitHub event stream. A cycle that read nothing does not move it, and it is not the time of every record a radar's numbers count, which cover everything still on record, not only what the last check found. A radar whose answer carries no last_run_at has none in the result, and the note says nothing about it. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "exposed_databases": { + "additionalProperties": false, + "description": "exposed_databases: exposed_databases.distinct_hosts counts distinct ip:port services the check confirmed answering without authentication, and exposed_databases.engines the distinct engine types among them; exposed_databases.top_engines and exposed_databases.top_countries rank up to 15 engines and 10 countries by those services. exposed_databases.pii_likely and exposed_databases.pci_likely count services whose schema names (never record values) pass a high-confidence, precision-first gate for personal or payment-card data, so a service outside them is not shown to hold no such data. exposed_databases.window.from and exposed_databases.window.to are timestamps, not counts: when EchelonGraph's check last confirmed the oldest and the newest of the services counted, a span of checks made at different times; with a counted service that has no such time on record there is no window.", + "properties": { + "distinct_hosts": { + "type": "number" + }, + "engines": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "pci_likely": { + "type": "number" + }, + "pii_likely": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_engines": { + "items": { + "additionalProperties": false, + "properties": { + "engine": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "engine", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "description": "kev_exposure: kev_exposure.distinct_hosts counts distinct ip:port services, not machines (a machine answering on two ports counts twice), with at least one CISA-KEV-listed CVE on record, and kev_exposure.ransomware_hosts those with a ransomware-linked one; kev_exposure.kev_cves_exposed and kev_exposure.ransomware_cves count distinct CVEs with at least one such service; kev_exposure.correlations counts service×CVE pairs, not services, so a service with three KEV CVEs counts three times. kev_exposure.top_products, kev_exposure.top_countries and kev_exposure.top_cves rank up to 12 products, 10 countries and 12 CVEs by those services; kev_exposure.top_cves[].cvss_v3_score and kev_exposure.top_cves[].epss_score are the highest CVSS v3 base score and EPSS probability recorded on that CVE's observations. kev_exposure.trend counts service×CVE pairs still on record by the week in which each was first recorded, over 12 weeks, so earlier weeks read low. kev_exposure.newest_kev lists the 15 CVEs that EchelonGraph's CVE records most recently mark as CISA-KEV-listed, each with an exposure_state: exposed, where kev_exposure.newest_kev[].exposed_hosts counts distinct ip:port services on record with it; or not_assessed, where the API's answer holds no measurement for that CVE (its 0 is not one) and no count is relayed, and this answer does not say whether the radar tracks that CVE: tracking is answered per CVE. kev_exposure.newest_kev[].cvss_v3_score and kev_exposure.newest_kev[].epss_score are the CVE record's CVSS v3 base score and EPSS probability. kev_exposure.window.from and kev_exposure.window.to are timestamps, not counts: when Shodan collected the banners of the oldest and the newest of the service×CVE pairs counted, a span of observations made at different times; with a counted pair that has no such time on record there is no window. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "correlations": { + "type": "number" + }, + "distinct_hosts": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "kev_cves_exposed": { + "type": "number" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "newest_kev": { + "items": { + "additionalProperties": false, + "properties": { + "added_date": { + "type": "string" + }, + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "exposed_hosts": { + "type": "number" + }, + "exposure_state": { + "enum": [ + "exposed", + "measured_zero", + "not_assessed" + ], + "type": "string" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "vuln_name": { + "type": "string" + } + }, + "required": [ + "cve_id", + "exposure_state" + ], + "type": "object" + }, + "type": "array" + }, + "ransomware_cves": { + "type": "number" + }, + "ransomware_hosts": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_cves": { + "items": { + "additionalProperties": false, + "properties": { + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "hosts": { + "type": "number" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + }, + "required": [ + "cve_id", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "hosts": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "trend": { + "items": { + "additionalProperties": false, + "properties": { + "new_exposures": { + "type": "number" + }, + "week": { + "type": "string" + } + }, + "required": [ + "week", + "new_exposures" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "description": "leaked_credentials: leaked_credentials.total counts (repository, secret) pairs, not distinct secrets, so one secret in three repositories counts three times; leaked_credentials.distinct_secrets counts each secret once and leaked_credentials.distinct_repos counts repositories; leaked_credentials.top_providers and leaked_credentials.top_types rank up to 15 providers and secret types by those pairs. None is validated: each is a credential-shaped string that passed EchelonGraph's filters, at most structurally checked and never tested against its provider. leaked_credentials.window.from and leaked_credentials.window.to are timestamps, not counts: when EchelonGraph's detector last found the oldest and the newest of the pairs counted.", + "properties": { + "distinct_repos": { + "type": "number" + }, + "distinct_secrets": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_providers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "provider": { + "type": "string" + } + }, + "required": [ + "provider", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_types": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "secret_type": { + "type": "string" + } + }, + "required": [ + "secret_type", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "description": "mcp_servers: counts and timestamps only, no hostname. mcp_servers.total counts hostnames the AI-exposure radar has checked for an MCP server, each once by its latest verdict on record, and not every one is an MCP server; EchelonGraph's own control servers are left out, and mcp_servers.own_controls_excluded counts them; hostnames whose owner opted out of scanning are not checked again while the opt-out stands, so their last verdict is left out too, and mcp_servers.withheld_opted_out counts them. mcp_servers.total is mcp_servers.protected plus mcp_servers.pending_readjudication plus mcp_servers.not_assessed. mcp_servers.protected counts hostnames whose /mcp endpoint asked for credentials and whose OAuth protected-resource metadata validated under RFC 9728; mcp_servers.prm_via divides them by where that document was found: mcp_servers.prm_via.header, mcp_servers.prm_via.wellknown_path and mcp_servers.prm_via.wellknown_root. mcp_servers.pending_readjudication counts verdicts of a rule since replaced, not yet re-checked. mcp_servers.not_assessed counts the rest, whose protection the radar could not assess (not assessed does not mean unprotected), and mcp_servers.not_assessed_by_reason puts each in one bucket. mcp_servers.not_assessed_by_reason.identified_no_challenge holds servers that identified themselves as MCP servers and did not ask for credentials at the handshake. That is normal in MCP: authorization is optional in the spec, and a server can enforce it at tools/call instead, which EchelonGraph never sends, so this bucket is not a finding of exposure. mcp_servers.not_assessed_by_reason.resource_mismatch, mcp_servers.not_assessed_by_reason.cross_origin_pointer, mcp_servers.not_assessed_by_reason.bare_challenge_no_prm, mcp_servers.not_assessed_by_reason.pointer_unreachable, mcp_servers.not_assessed_by_reason.pointer_invalid, mcp_servers.not_assessed_by_reason.no_authorization_servers, mcp_servers.not_assessed_by_reason.wellknown_unreachable and mcp_servers.not_assessed_by_reason.metadata_invalid hold endpoints that asked for credentials but whose RFC 9728 metadata did not validate, by why, so none of them is shown to lack protection; mcp_servers.not_assessed_by_reason.challenge_unadjudicated holds endpoints that asked for credentials before that check existed, not yet re-checked. mcp_servers.not_assessed_by_reason.no_http_answer holds hostnames that gave no HTTP answer, and mcp_servers.not_assessed_by_reason.not_identified_as_mcp hostnames whose HTTP answer identified no MCP server. mcp_servers.era divides every counted hostname by protocol era: mcp_servers.era.legacy; mcp_servers.era.dual, a lower bound; mcp_servers.era.modern, not proven modern-only; mcp_servers.era.unknown; and mcp_servers.era.not_measured, recorded before the era probe and not re-checked since. mcp_servers.transport divides them by transport: mcp_servers.transport.streamable_http, mcp_servers.transport.legacy_sse, mcp_servers.transport.unknown and mcp_servers.transport.not_measured. mcp_servers.window.from and mcp_servers.window.to are when the oldest and the newest of the verdicts counted were last checked. mcp_servers.last_run_at is a timestamp, not a count: when the AI-exposure radar, which checks other AI services too, last completed a check; mcp_servers.enabled is whether one completed within 45 minutes of the answer, and mcp_servers.counted_at is when the API read the counts. A partition whose buckets do not add up to the count it divides is left out and named; an answer that does not say it is the MCP-server counts, or whose mcp_servers.total, mcp_servers.protected, mcp_servers.pending_readjudication and mcp_servers.not_assessed are missing or contradict each other, is a failure.", + "properties": { + "counted_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "era": { + "additionalProperties": false, + "properties": { + "dual": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "legacy": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "modern": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "legacy", + "dual", + "modern", + "unknown", + "not_measured" + ], + "type": "object" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "not_assessed": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_assessed_by_reason": { + "additionalProperties": false, + "properties": { + "bare_challenge_no_prm": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "challenge_unadjudicated": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "cross_origin_pointer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "identified_no_challenge": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "metadata_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_authorization_servers": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_http_answer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_identified_as_mcp": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "resource_mismatch": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "identified_no_challenge", + "resource_mismatch", + "cross_origin_pointer", + "bare_challenge_no_prm", + "pointer_unreachable", + "pointer_invalid", + "no_authorization_servers", + "wellknown_unreachable", + "metadata_invalid", + "challenge_unadjudicated", + "no_http_answer", + "not_identified_as_mcp" + ], + "type": "object" + }, + "own_controls_excluded": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pending_readjudication": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "prm_via": { + "additionalProperties": false, + "properties": { + "header": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_path": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_root": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "header", + "wellknown_path", + "wellknown_root" + ], + "type": "object" + }, + "protected": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "transport": { + "additionalProperties": false, + "properties": { + "legacy_sse": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "streamable_http": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "streamable_http", + "legacy_sse", + "unknown", + "not_measured" + ], + "type": "object" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "withheld_opted_out": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "protected", + "pending_readjudication", + "not_assessed" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "description": "shadow_ai: the result is regrouped by what each number counts. shadow_ai.confirmed_exposed counts services EchelonGraph's probes found answering without an authentication gate (liveness active, or rechecking during a re-check): confirmed_exposed.total is the sum of confirmed_exposed.by_category, and confirmed_exposed.last_24h counts those first recorded in the last 24 h. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. confirmed_exposed.window.from and confirmed_exposed.window.to are timestamps, not counts: when EchelonGraph's verifier ran the probe that last decided the oldest and the newest of those services, a span of probes made at different times. shadow_ai.observed counts every Certificate Transparency or Shodan observation on record, whatever its verification state: its numbers are observed, not exposed. They are observed.total; observed.by_category (the same observations by category); observed.last_24h (those first recorded in the last 24 h); observed.trend_30d (observations per UTC day over the last 30 days); and observed.top_products, observed.top_countries and observed.top_issuers (up to ten products, countries and issuers ranked by observations, where an issuer is the certificate's CA for a Certificate Transparency observation and the hosting operator Shodan reports for a Shodan one). shadow_ai.authentication counts observations by probe outcome: authentication.observed where a probe observed an authentication gate (a 401/403, a login page or an auth marker), and authentication.not_determined where the service answered but no probe could tell. Neither authentication count is part of confirmed_exposed, and observed.total minus confirmed_exposed.total is not a count of secured services. The shadow-AI poller block carries only running and last_run_at: last_run_at is when the radar's leader last completed a Certificate Transparency (crt.sh) cycle, and its running is true only when that was within 30 minutes of the answer. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "authentication": { + "additionalProperties": false, + "properties": { + "not_determined": { + "type": "number" + }, + "observed": { + "type": "number" + } + }, + "type": "object" + }, + "confirmed_exposed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "observed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "last_observation": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "country": { + "type": "string" + } + }, + "required": [ + "country", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_issuers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "issuer": { + "type": "string" + } + }, + "required": [ + "issuer", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "trend_30d": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "date": { + "type": "string" + } + }, + "required": [ + "date", + "count" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "poller": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "running": { + "type": "boolean" + } + }, + "required": [ + "running", + "last_run_at" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "exposed_databases": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + }, + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at", + "enabled" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "running": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "last_run_at", + "running" + ], + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "radars": { + "description": "Each radar that could not be read, and why.", + "items": { + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "unexpected_shape" + ], + "type": "string" + }, + "message": { + "type": "string" + }, + "path": { + "type": "string" + }, + "radar": { + "type": "string" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "radar", + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "cna": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "name": { - "type": [ - "string", - "null" - ] - }, - "short_name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." - }, - "cna_solution": { - "description": "The sentence of the CVE record's solutions, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "date_public": { - "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "date_public_source": { - "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "echelongraph_ssvc_decision": { - "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_required_action": { - "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "kev_short_description": { - "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "release_reference", - "vendor_advisory_fix", - "nvd_patch_reference", - "cna_patch_reference", - "cna_solution", - "description_fix" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions, written by its CNA, that names a fixed version; relayed as cna_solution) and description_fix (a sentence of the CVE description that names a fixed version). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fix_status": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "basis": { - "type": [ - "string", - "null" - ] - }, - "described_by": { - "type": [ - "string", - "null" - ] - }, - "listed_in_patch_table": { - "type": [ - "boolean", - "null" - ] - }, - "solution_by": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cna": { - "type": [ - "string", - "null" - ] - }, - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "available", - "fix_referenced", - "fix_merged", - "none_confirmed", - "unknown" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "stated_in_record": { - "type": [ - "boolean", - "null" - ] - }, - "unread_inputs": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read." - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", - "type": [ - "string", - "null" - ] - }, - "score_factors": { - "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "cna": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "name": { + "type": [ + "string", + "null" + ] + }, + "short_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." + }, + "cna_solution": { + "description": "The sentence of the CVE record's solutions or workarounds, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. cna_solution_section says which of the two sections it is. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "cna_solution_section": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "solution", + "workaround" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "Which section of the CVE record cna_solution was read from: solution (the record's solutions) or workaround (its workarounds, read only where its solutions name no fix: a temporary measure the CNA lists beside its fix). A workaround's sentence is the record's workaround, never its solution. Present whenever cna_solution is; absent from an API older than the field." + }, + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "date_public": { + "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "date_public_source": { + "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "echelongraph_ssvc_decision": { + "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds, or once held, evidence of a fix for the CVE; patch_evidence names the sources it holds now. true beside an empty patch_evidence means evidence of a fix once held has since been withdrawn (patch_available is never set back to false), and fix_status (remediation.fix_status in the CVE's record) is the current reading, not patch_available. false: no fix evidence is on record, which is not a finding that no fix exists. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "vendor_advisory_fix", + "nvd_patch_reference", + "cna_patch_reference", + "cna_solution", + "description_fix", + "vendor_fix_released" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions or workarounds, written by its CNA, that names a fixed version; relayed as cna_solution), description_fix (a sentence of the CVE description that names a fixed version) and vendor_fix_released (the vendor states, in the CVE record, that a fix is released and the record names no fixed version; check the vendor's advisory). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "section": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "vendor_released": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_factors": { + "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_cwe1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max_page": { - "type": [ - "number", - "null" - ] - }, - "page": { - "description": "The page served.", - "type": [ - "number", - "null" - ] - }, - "page_requested": { - "description": "The page asked for.", - "type": "number" - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "page", - "page_requested", - "page_size", - "max_page" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "catalog_version": { - "description": "The version of the MITRE CWE catalog name and description come from.", - "type": [ - "string", - "null" - ] - }, - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v2_severity": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: a score only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE; false: NOT YET SCORED, not scored 0.", - "type": [ - "boolean", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "max_page": { - "description": "The last page the API serves; a later page is answered as this one.", - "type": [ - "number", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "order": { - "description": "How cves is sorted, as the API states it; absent from an API older than the field, which sorted by CVE id.", - "type": [ - "string", - "null" - ] - }, - "page": { - "type": [ - "number", - "null" - ] - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "The active CVEs classified under the CWE, rejected and reserved records left out.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max_page": { - "type": [ - "number", - "null" - ] - }, - "page": { - "description": "The page served.", - "type": [ - "number", - "null" - ] - }, - "page_requested": { - "description": "The page asked for.", - "type": "number" - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "page", - "page_requested", - "page_size", - "max_page" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max_page": { + "type": [ + "number", + "null" + ] + }, + "page": { + "description": "The page served.", + "type": [ + "number", + "null" + ] + }, + "page_requested": { + "description": "The page asked for.", + "type": "number" + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "total", + "returned", + "page", + "page_requested", + "page_size", + "max_page" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "catalog_version": { + "description": "The version of the MITRE CWE catalog name and description come from.", + "type": [ + "string", + "null" + ] + }, + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v2_severity": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: a score only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE; false: NOT YET SCORED, not scored 0.", + "type": [ + "boolean", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "max_page": { + "description": "The last page the API serves; a later page is answered as this one.", + "type": [ + "number", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "order": { + "description": "How cves is sorted, as the API states it; absent from an API older than the field, which sorted by CVE id.", + "type": [ + "string", + "null" + ] + }, + "page": { + "type": [ + "number", + "null" + ] + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "The active CVEs classified under the CWE, rejected and reserved records left out.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max_page": { + "type": [ + "number", + "null" + ] + }, + "page": { + "description": "The page served.", + "type": [ + "number", + "null" + ] + }, + "page_requested": { + "description": "The page asked for.", + "type": "number" + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "total", + "returned", + "page", + "page_requested", + "page_size", + "max_page" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_vendor_advisory1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "known_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "references": {}, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation": { - "description": "The vendor's remediation as one text (the legacy field), beside remediations.", - "type": [ - "string", - "null" - ] - }, - "remediation_items_not_stored": { - "description": "Items past the 64 stored per advisory.", - "type": [ - "number", - "null" - ] - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "remediations": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVEs the item covers; [] for the whole advisory." - }, - "fixed_build": { - "type": [ - "string", - "null" - ] - }, - "kind": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "product_count": { - "type": [ - "number", - "null" - ] - }, - "product_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "source_category": { - "description": "The vendor's own name for the category.", - "type": [ - "string", - "null" - ] - }, - "source_subcategory": { - "type": [ - "string", - "null" - ] - }, - "text": { - "description": "The vendor's text, verbatim but for HTML markup removed, untested by EchelonGraph; at most 2,000 characters (text_truncated, text_chars).", - "type": [ - "string", - "null" - ] - }, - "text_chars": { - "type": [ - "number", - "null" - ] - }, - "text_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each remediation the vendor lists, with its kind, the vendor's own category." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_modified_at": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - }, - "withdrawn_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn_reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "known_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "references": {}, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation": { + "description": "The vendor's remediation as one text (the legacy field), beside remediations.", + "type": [ + "string", + "null" + ] + }, + "remediation_items_not_stored": { + "description": "Items past the 64 stored per advisory.", + "type": [ + "number", + "null" + ] + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "remediations": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVEs the item covers; [] for the whole advisory." + }, + "fixed_build": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "product_count": { + "type": [ + "number", + "null" + ] + }, + "product_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "source_category": { + "description": "The vendor's own name for the category.", + "type": [ + "string", + "null" + ] + }, + "source_subcategory": { + "type": [ + "string", + "null" + ] + }, + "text": { + "description": "The vendor's text, verbatim but for HTML markup removed, untested by EchelonGraph; at most 2,000 characters (text_truncated, text_chars).", + "type": [ + "string", + "null" + ] + }, + "text_chars": { + "type": [ + "number", + "null" + ] + }, + "text_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each remediation the vendor lists, with its kind, the vendor's own category." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_modified_at": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
kev_recent1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "catalog": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "catalog_count": { - "type": [ - "number", - "null" - ] - }, - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "feed_url": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "filters": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": {}, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev": { - "description": "Newest kev_added_date first; rows within one date are ordered by cve_id.", - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "eg_kev_tier": { - "type": [ - "number", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "type": [ - "string", - "null" - ] - }, - "kev_product": { - "type": [ - "string", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_vendor": { - "type": [ - "string", - "null" - ] - }, - "kev_vuln_name": { - "type": [ - "string", - "null" - ] - }, - "our_first_seen_kev": { - "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "kev_listed_total": { - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - }, - "notes": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "order": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "last_successful_fetch_at", - "catalog_version", - "date_released" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog": { + "const": "CISA KEV catalog", + "type": "string" + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "catalog": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "catalog_count": { + "type": [ + "number", + "null" + ] + }, + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "feed_url": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "filters": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev": { + "description": "Newest kev_added_date first; rows within one date are ordered by cve_id.", + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "eg_kev_tier": { + "type": [ + "number", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "type": [ + "string", + "null" + ] + }, + "kev_product": { + "type": [ + "string", + "null" + ] + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_vendor": { + "type": [ + "string", + "null" + ] + }, + "kev_vuln_name": { + "type": [ + "string", + "null" + ] + }, + "our_first_seen_kev": { + "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "kev_listed_total": { + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "next_cursor": { + "type": [ + "string", + "null" + ] + }, + "notes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "order": { + "type": [ + "string", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "last_successful_fetch_at", + "catalog_version", + "date_released" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog": { + "const": "CISA KEV catalog", + "type": "string" + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
scan_manifest1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls read more than once (the same package and version in two places) and sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "entries_pinned": { - "description": "Entries pinned to one version across the files, duplicates included.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files": { - "description": "Files passed.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_not_read": { - "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_read": { - "description": "Of those, the ones read.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_checked": { - "description": "Entries not sent (data.not_checked): not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_checked_by_reason": { - "additionalProperties": false, - "description": "not_checked, counted by reason.", - "properties": { - "local_path": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "unsupported_line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "vcs_source": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unpinned": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unresolved": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "object" - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "files", - "files_read", - "files_not_read", - "entries_pinned", - "duplicates_removed", - "not_checked", - "not_checked_by_reason", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "manifest": { - "additionalProperties": false, - "description": "Each file passed, in order, and how it was read. Filenames and contents are not sent to the API.", - "properties": { - "files": { - "items": { - "additionalProperties": false, - "properties": { - "ecosystem": { - "description": "The OSV ecosystem of the purls read from it.", - "type": [ - "string", - "null" - ] - }, - "filename": { - "type": "string" - }, - "format": { - "anyOf": [ - { - "enum": [ - "requirements.txt", - "go.mod", - "package-lock.json", - "Cargo.lock", - "Gemfile.lock", - "composer.lock", - "poetry.lock", - "gradle.lockfile" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The format the file was read as: set by format, or read from the filename; null when it was not read." - }, - "not_checked": { - "description": "Entries not sent, listed in data.not_checked: not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "notes": { - "description": "How this file was read where that limits what its verdicts cover (a go.mod below go 1.17).", - "items": { - "type": "string" - }, - "type": "array" - }, - "purls": { - "description": "Entries pinned to one version, read as purls (duplicates included).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "read": { - "description": "false: the file was refused or could not be read, and nothing in it is checked (not clean).", - "type": "boolean" - }, - "refused": { - "description": "Why the file was not read, and the file to pass instead where there is one; null when it was read.", - "type": [ - "string", - "null" - ] - }, - "replaced": { - "description": "go.mod replace directives applied: the module required, and the module and version checked instead.", - "items": { - "additionalProperties": false, - "properties": { - "from": { - "type": "string" - }, - "to": { - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "type": "array" - }, - "skipped": { - "description": "Entries that are not dependencies (a package-lock's root entry, the project itself).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "filename", - "format", - "ecosystem", - "read", - "refused", - "purls", - "not_checked", - "skipped", - "notes", - "replaced" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "files" - ], - "type": "object" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_checked": { - "description": "Each entry not sent to the API, with its file, line and reason: not checked, and not clean.", - "items": { - "additionalProperties": false, - "properties": { - "detail": { - "type": "string" - }, - "file": { - "type": "string" - }, - "line": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "1-based line; null in a JSON lockfile, whose entries spec names by key." - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "description": "version_unpinned: a range or wildcard, not one version; version_unresolved: no single registry version (none given, a branch, or an excluded go.mod version); local_path: a directory, file or workspace member; vcs_source: a VCS checkout; unsupported_line: a line or entry this tool does not read (another file named by -r or -c, a direct URL, another registry).", - "enum": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "string" - }, - "spec": { - "description": "What the file says for the entry: its line, or its lockfile key and version (at most 200 characters).", - "type": "string" - } - }, - "required": [ - "file", - "name", - "spec", - "reason", - "line", - "detail" - ], - "type": "object" - }, - "type": "array" - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matched_package": { - "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", - "type": [ - "string", - "null" - ] - }, - "matched_version_from": { - "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", - "type": [ - "string", - "null" - ] - }, - "matched_via": { - "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_detail": { - "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", - "type": [ - "boolean", - "null" - ] - }, - "match_reason": { - "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "purl_name": { - "description": "Upstream rows: the purl's own (binary) package name, not looked up.", - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "required": [ - "manifest", - "not_checked" - ], - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls read more than once (the same package and version in two places) and sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "entries_pinned": { - "description": "Entries pinned to one version across the files, duplicates included.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files": { - "description": "Files passed.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_not_read": { - "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_read": { - "description": "Of those, the ones read.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_checked": { - "description": "Entries not sent (data.not_checked): not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_checked_by_reason": { - "additionalProperties": false, - "description": "not_checked, counted by reason.", - "properties": { - "local_path": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "unsupported_line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "vcs_source": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unpinned": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unresolved": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "object" - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "files", - "files_read", - "files_not_read", - "entries_pinned", - "duplicates_removed", - "not_checked", - "not_checked_by_reason", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls read more than once (the same package and version in two places) and sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entries_pinned": { + "description": "Entries pinned to one version across the files, duplicates included.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files": { + "description": "Files passed.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_not_read": { + "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_read": { + "description": "Of those, the ones read.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_checked": { + "description": "Entries not sent (data.not_checked): not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_checked_by_reason": { + "additionalProperties": false, + "description": "not_checked, counted by reason.", + "properties": { + "local_path": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "unsupported_line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "vcs_source": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unpinned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unresolved": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "object" + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "files", + "files_read", + "files_not_read", + "entries_pinned", + "duplicates_removed", + "not_checked", + "not_checked_by_reason", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "manifest": { + "additionalProperties": false, + "description": "Each file passed, in order, and how it was read. Filenames and contents are not sent to the API.", + "properties": { + "files": { + "items": { + "additionalProperties": false, + "properties": { + "ecosystem": { + "description": "The OSV ecosystem of the purls read from it.", + "type": [ + "string", + "null" + ] + }, + "filename": { + "type": "string" + }, + "format": { + "anyOf": [ + { + "enum": [ + "requirements.txt", + "go.mod", + "package-lock.json", + "Cargo.lock", + "Gemfile.lock", + "composer.lock", + "poetry.lock", + "gradle.lockfile" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The format the file was read as: set by format, or read from the filename; null when it was not read." + }, + "not_checked": { + "description": "Entries not sent, listed in data.not_checked: not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "notes": { + "description": "How this file was read where that limits what its verdicts cover (a go.mod below go 1.17).", + "items": { + "type": "string" + }, + "type": "array" + }, + "purls": { + "description": "Entries pinned to one version, read as purls (duplicates included).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "read": { + "description": "false: the file was refused or could not be read, and nothing in it is checked (not clean).", + "type": "boolean" + }, + "refused": { + "description": "Why the file was not read, and the file to pass instead where there is one; null when it was read.", + "type": [ + "string", + "null" + ] + }, + "replaced": { + "description": "go.mod replace directives applied: the module required, and the module and version checked instead.", + "items": { + "additionalProperties": false, + "properties": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "skipped": { + "description": "Entries that are not dependencies (a package-lock's root entry, the project itself).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "filename", + "format", + "ecosystem", + "read", + "refused", + "purls", + "not_checked", + "skipped", + "notes", + "replaced" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "files" + ], + "type": "object" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_checked": { + "description": "Each entry not sent to the API, with its file, line and reason: not checked, and not clean.", + "items": { + "additionalProperties": false, + "properties": { + "detail": { + "type": "string" + }, + "file": { + "type": "string" + }, + "line": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "1-based line; null in a JSON lockfile, whose entries spec names by key." + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "description": "version_unpinned: a range or wildcard, not one version; version_unresolved: no single registry version (none given, a branch, or an excluded go.mod version); local_path: a directory, file or workspace member; vcs_source: a VCS checkout; unsupported_line: a line or entry this tool does not read (another file named by -r or -c, a direct URL, another registry).", + "enum": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "string" + }, + "spec": { + "description": "What the file says for the entry: its line, or its lockfile key and version (at most 200 characters).", + "type": "string" + } + }, + "required": [ + "file", + "name", + "spec", + "reason", + "line", + "detail" + ], + "type": "object" + }, + "type": "array" + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matched_package": { + "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", + "type": [ + "string", + "null" + ] + }, + "matched_version_from": { + "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", + "type": [ + "string", + "null" + ] + }, + "matched_via": { + "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", + "type": [ + "boolean", + "null" + ] + }, + "match_reason": { + "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "matches_truncated": { + "additionalProperties": false, + "description": "Present only on a row whose matches the structured result's cut (DATA CUT) shortened or left out: total, the row's matches in the answer; returned, the ones data keeps (its first, highest effective_score first); and, while they fit, of all its matches, the CVE IDs KEV-listed (kev_listed_cve_ids) or used in ransomware (ransomware_cve_ids), and the distinct fixed_in versions (fixed_in_versions). The same call with full: true returns every match.", + "properties": { + "fixed_in_versions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "kev_listed_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ransomware_cve_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "purl_name": { + "description": "Upstream rows: the purl's own (binary) package name, not looked up.", + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "required": [ + "manifest", + "not_checked" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls read more than once (the same package and version in two places) and sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entries_pinned": { + "description": "Entries pinned to one version across the files, duplicates included.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files": { + "description": "Files passed.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_not_read": { + "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_read": { + "description": "Of those, the ones read.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_checked": { + "description": "Entries not sent (data.not_checked): not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_checked_by_reason": { + "additionalProperties": false, + "description": "not_checked, counted by reason.", + "properties": { + "local_path": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "unsupported_line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "vcs_source": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unpinned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unresolved": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "object" + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "files", + "files_read", + "files_not_read", + "entries_pinned", + "duplicates_removed", + "not_checked", + "not_checked_by_reason", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_cves1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "The rows in this page.", - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cna": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "name": { - "type": [ - "string", - "null" - ] - }, - "short_name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." - }, - "cna_solution": { - "description": "The sentence of the CVE record's solutions, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "date_public": { - "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", - "type": [ - "string", - "null" - ] - }, - "date_public_source": { - "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "echelongraph_ssvc_decision": { - "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_required_action": { - "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "kev_short_description": { - "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "release_reference", - "vendor_advisory_fix", - "nvd_patch_reference", - "cna_patch_reference", - "cna_solution", - "description_fix" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions, written by its CNA, that names a fixed version; relayed as cna_solution) and description_fix (a sentence of the CVE description that names a fixed version). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fix_status": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "basis": { - "type": [ - "string", - "null" - ] - }, - "described_by": { - "type": [ - "string", - "null" - ] - }, - "listed_in_patch_table": { - "type": [ - "boolean", - "null" - ] - }, - "solution_by": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cna": { - "type": [ - "string", - "null" - ] - }, - "statement": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "available", - "fix_referenced", - "fix_merged", - "none_confirmed", - "unknown" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "stated_in_record": { - "type": [ - "boolean", - "null" - ] - }, - "unread_inputs": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read." - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", - "type": [ - "string", - "null" - ] - }, - "score_factors": { - "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "description": "true: a search phrase was relaxed to all of its words.", - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "description": "false: the matches were not counted, so total is not a count.", - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "description": "true: there are at least total matches.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "The rows in this page.", - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cna": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "name": { + "type": [ + "string", + "null" + ] + }, + "short_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." + }, + "cna_solution": { + "description": "The sentence of the CVE record's solutions or workarounds, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. cna_solution_section says which of the two sections it is. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "cna_solution_section": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "solution", + "workaround" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "Which section of the CVE record cna_solution was read from: solution (the record's solutions) or workaround (its workarounds, read only where its solutions name no fix: a temporary measure the CNA lists beside its fix). A workaround's sentence is the record's workaround, never its solution. Present whenever cna_solution is; absent from an API older than the field." + }, + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "date_public": { + "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "date_public_source": { + "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "echelongraph_ssvc_decision": { + "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds, or once held, evidence of a fix for the CVE; patch_evidence names the sources it holds now. true beside an empty patch_evidence means evidence of a fix once held has since been withdrawn (patch_available is never set back to false), and fix_status (remediation.fix_status in the CVE's record) is the current reading, not patch_available. false: no fix evidence is on record, which is not a finding that no fix exists. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "vendor_advisory_fix", + "nvd_patch_reference", + "cna_patch_reference", + "cna_solution", + "description_fix", + "vendor_fix_released" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions or workarounds, written by its CNA, that names a fixed version; relayed as cna_solution), description_fix (a sentence of the CVE description that names a fixed version) and vendor_fix_released (the vendor states, in the CVE record, that a fix is released and the record names no fixed version; check the vendor's advisory). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "section": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "vendor_released": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read. vendor_released (basis vendor_fix_released) is the vendor's own statement that a fix is released where the CVE record names no fixed version: its sentence, verbatim (statement, or null), never a version, so the fixed release is the vendor advisory's to name. solution_by's section is workarounds when the fix sentence is the record's workaround, not its solution." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_factors": { + "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "description": "true: a search phrase was relaxed to all of its words.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "description": "false: the matches were not counted, so total is not a count.", + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "description": "true: there are at least total matches.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_vendor_advisories1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "description": "Whether a free-text search filtered this answer.", - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, vendor_advisory_id, affected_products and cve_ids (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word): it must equal, ignoring case, a whole word (a run of letters and digits) of one of those, so xz finds xz-utils but not xzibit, and a 1- or 2-character query with any other character, such as c#, matches nothing.", - "type": [ - "string", - "null" - ] - }, - "total": { - "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000; paging past it still works. Without a query, total is the exact count and total_capped is false.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "description": "Whether a free-text search filtered this answer.", + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, vendor_advisory_id, affected_products and cve_ids (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word): it must equal, ignoring case, a whole word (a run of letters and digits) of one of those, so xz finds xz-utils but not xzibit, and a 1- or 2-character query with any other character, such as c#, matches nothing.", + "type": [ + "string", + "null" + ] + }, + "total": { + "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000; paging past it still works. Without a query, total is the exact count and total_capped is false.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
vendor_advisories_for_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cve_rejected": { - "description": "true: the CVE record of cve_id was rejected (withdrawn) by its numbering authority, so these advisories name a rejected record, not an active vulnerability; null when that could not be checked.", - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "data_truncated": { - "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", - "type": "boolean" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - }, - "truncated": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "returned": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "thinned": { - "const": true, - "type": "boolean" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "returned" - ], - "type": "object" - }, - "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data_truncated", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": {}, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cve_rejected": { + "description": "true: the CVE record of cve_id was rejected (withdrawn) by its numbering authority, so these advisories name a rejected record, not an active vulnerability; null when that could not be checked.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
16 tool updates
- Changed
check_affected2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", - "type": [ - "boolean", - "null" - ] - }, - "candidate_count": { - "type": [ - "number", - "null" - ] - }, - "candidates_capped": { - "description": "true: not every candidate CVE was loaded.", - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "description": "true: the match list stopped at its cap.", - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "degraded": { - "description": "true: the lookup ran out of time.", - "type": [ - "boolean", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "ecosystem_recognised": { - "type": [ - "boolean", - "null" - ] - }, - "excluded": {}, - "excluded_count": { - "description": "CPE candidates suppressed by the vendor or platform gate.", - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "description": "Which lookup path answered.", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_vendor": { - "description": "The vendor NVD's CPE asserts for this match.", - "type": [ - "string", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "effective_score": { - "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", - "type": [ - "number", - "null" - ] - }, - "effective_severity": { - "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "EPSS exploitation probability, 0 to 1.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "Registry match: the fixed bound of the advisory interval that holds this version, always above it. null when that interval records no fix (it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which. Absent on a CPE match.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Registry match: the advisory interval that holds this version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Listed in CISA-KEV: known to be exploited.", - "type": [ - "boolean", - "null" - ] - }, - "match_confidence": { - "type": [ - "number", - "null" - ] - }, - "match_method": { - "type": [ - "string", - "null" - ] - }, - "match_reason": { - "type": [ - "string", - "null" - ] - }, - "matched_criteria": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "description": "CISA-KEV records known use in ransomware campaigns.", - "type": [ - "boolean", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", - "type": [ - "boolean", - "null" - ] - }, - "score_unassessed_reason": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", - "type": [ - "string", - "null" - ] - }, - "vendor_severity": { - "type": [ - "string", - "null" - ] - }, - "vendor_unknown": { - "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", - "type": [ - "boolean", - "null" - ] - }, - "version_evidence": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "description": "Advisories decided as not affecting this version.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - }, - "product_named_count": { - "type": [ - "number", - "null" - ] - }, - "undecidable_excluded_count": { - "type": [ - "number", - "null" - ] - }, - "undecided_candidate_count": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "detail": { - "type": [ - "string", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_count": { - "type": [ - "number", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", + "type": [ + "boolean", + "null" + ] + }, + "candidate_count": { + "type": [ + "number", + "null" + ] + }, + "candidates_capped": { + "description": "true: not every candidate CVE was loaded.", + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "description": "true: the match list stopped at its cap.", + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "degraded": { + "description": "true: the lookup ran out of time.", + "type": [ + "boolean", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "excluded": {}, + "excluded_count": { + "description": "CPE candidates suppressed by the vendor or platform gate.", + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "description": "Which lookup path answered.", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cpe_vendor": { + "description": "The vendor NVD's CPE asserts for this match.", + "type": [ + "string", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "effective_score": { + "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", + "type": [ + "number", + "null" + ] + }, + "effective_severity": { + "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "EPSS exploitation probability, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "Registry match: the lowest version above this one that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds this version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which. Absent on a CPE match.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds this version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Registry match: the advisory interval that holds this version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Listed in CISA-KEV: known to be exploited.", + "type": [ + "boolean", + "null" + ] + }, + "match_confidence": { + "type": [ + "number", + "null" + ] + }, + "match_method": { + "type": [ + "string", + "null" + ] + }, + "match_reason": { + "type": [ + "string", + "null" + ] + }, + "matched_criteria": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "description": "CISA-KEV records known use in ransomware campaigns.", + "type": [ + "boolean", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", + "type": [ + "boolean", + "null" + ] + }, + "score_unassessed_reason": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", + "type": [ + "string", + "null" + ] + }, + "vendor_severity": { + "type": [ + "string", + "null" + ] + }, + "vendor_unknown": { + "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", + "type": [ + "boolean", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "description": "Advisories decided as not affecting this version.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + }, + "product_named_count": { + "type": [ + "number", + "null" + ] + }, + "undecidable_excluded_count": { + "type": [ + "number", + "null" + ] + }, + "undecided_candidate_count": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "detail": { + "type": [ + "string", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_count": { + "type": [ + "number", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
check_sbom2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matched_package": { - "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", - "type": [ - "string", - "null" - ] - }, - "matched_version_from": { - "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", - "type": [ - "string", - "null" - ] - }, - "matched_via": { - "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "The fixed bound of the advisory interval that holds this component's version, always above it. null when that interval records no fix (it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", - "type": [ - "boolean", - "null" - ] - }, - "match_reason": { - "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names the fixed version B, \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "purl_name": { - "description": "Upstream rows: the purl's own (binary) package name, not looked up.", - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matched_package": { + "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", + "type": [ + "string", + "null" + ] + }, + "matched_version_from": { + "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", + "type": [ + "string", + "null" + ] + }, + "matched_via": { + "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", + "type": [ + "boolean", + "null" + ] + }, + "match_reason": { + "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "purl_name": { + "description": "Upstream rows: the purl's own (binary) package name, not looked up.", + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_exposure2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "countries": { - "type": [ - "number", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "exposed_hosts": { - "type": [ - "number", - "null" - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev_catalog_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_seen_in_observations": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "description": "When EchelonGraph last wrote or refreshed a service's row, not when the service was observed and not when its vulnerable version was last confirmed: it is set to the time of the write when a search matches the banner, and again when a re-check finds the port still listed by Shodan InternetDB, without re-reading the banner, so a patched service can stay counted while its port stays open. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "type": [ - "string", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "top_countries": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "country": { - "type": [ - "string", - "null" - ] - }, - "hosts": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "top_products": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "hosts": { - "type": [ - "number", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "tracked": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "exposure_state": { - "anyOf": [ - { - "enum": [ - "exposed", - "measured_zero", - "not_assessed", - "tracking_unknown" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "exposure_state", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "countries": { + "type": [ + "number", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "exposed_hosts": { + "type": [ + "number", + "null" + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev_catalog_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_seen_in_observations": { + "type": [ + "boolean", + "null" + ] + }, + "last_seen": { + "description": "When EchelonGraph last wrote or refreshed a service's row, not when the service was observed and not when its vulnerable version was last confirmed: it is set to the time of the write when a search matches the banner, and again when a re-check finds the port still listed by Shodan InternetDB, without re-reading the banner, so a patched service can stay counted while its port stays open. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "type": [ + "string", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "top_countries": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "country": { + "type": [ + "string", + "null" + ] + }, + "hosts": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "top_products": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "hosts": { + "type": [ + "number", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "tracked": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "exposure_state": { + "anyOf": [ + { + "enum": [ + "exposed", + "measured_zero", + "not_assessed", + "tracking_unknown" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "exposure_state", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_intel2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "affected_packages": { - "items": { - "additionalProperties": {}, - "properties": { - "dependents_count": { - "type": [ - "number", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - }, - "fixed": { - "description": "The range's fix: the first version past it. null where no fix is on record.", - "type": [ - "string", - "null" - ] - }, - "introduced": { - "description": "The range's lower bound, inclusive; \"0\" is the first version.", - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", - "type": [ - "string", - "null" - ] - }, - "source": { - "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; that range's fixed is the fix for it, and a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." - }, - "fixed_version": { - "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "version_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cve_id": { - "type": "string" - }, - "cwes": { - "items": { - "additionalProperties": {}, - "properties": { - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits": { - "items": { - "additionalProperties": {}, - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "eg_first_seen_at": { - "description": "When EchelonGraph first recorded the reference, as a UTC timestamp: a date of EchelonGraph's, not the source's.", - "type": "string" - }, - "first_seen_at": { - "description": "Deprecated: the same value as source_published_at, null when that is.", - "type": [ - "string", - "null" - ] - }, - "kind": { - "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", - "type": [ - "string", - "null" - ] - }, - "source_name": { - "type": [ - "string", - "null" - ] - }, - "source_published_at": { - "description": "The source's own date for the reference (Exploit-DB's date_published, a GitHub proof-of-concept repository's created_at, or the first commit of a nuclei template or Metasploit module where EchelonGraph derived it from the source's git history); null where the source gives none, and EchelonGraph supplies no stand-in date.", - "type": [ - "string", - "null" - ] - }, - "source_url": { - "type": [ - "string", - "null" - ] - }, - "verified_status": { - "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits_by_kind": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_by_status": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_capped": { - "description": "true: exploits lists fewer references than exploits_total.", - "type": "boolean" - }, - "exploits_total": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Every exploit reference on record for the CVE, not only those listed in exploits." - }, - "fixed_versions": { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_version": { - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "vulnerable_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline": { - "items": { - "additionalProperties": {}, - "properties": { - "enriched_at": { - "type": [ - "string", - "null" - ] - }, - "enrichment_kind": { - "type": [ - "string", - "null" - ] - }, - "fields_changed": {}, - "score_delta": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline_count_30d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_count_7d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_total": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "cve_id" - ], - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "properties": { + "affected_packages": { + "items": { + "additionalProperties": {}, + "properties": { + "dependents_count": { + "type": [ + "number", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + }, + "fixed": { + "description": "The range's fix: the first version past it. null where no fix is on record.", + "type": [ + "string", + "null" + ] + }, + "introduced": { + "description": "The range's lower bound, inclusive; \"0\" is the first version.", + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; its fix is that range's fixed, or, while another range still holds that, the other range's fixed (none past a range without one); a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "version_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cve_id": { + "type": "string" + }, + "cwes": { + "items": { + "additionalProperties": {}, + "properties": { + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits": { + "items": { + "additionalProperties": {}, + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "eg_first_seen_at": { + "description": "When EchelonGraph first recorded the reference, as a UTC timestamp: a date of EchelonGraph's, not the source's.", + "type": "string" + }, + "first_seen_at": { + "description": "Deprecated: the same value as source_published_at, null when that is.", + "type": [ + "string", + "null" + ] + }, + "kind": { + "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", + "type": [ + "string", + "null" + ] + }, + "source_name": { + "type": [ + "string", + "null" + ] + }, + "source_published_at": { + "description": "The source's own date for the reference (Exploit-DB's date_published, a GitHub proof-of-concept repository's created_at, or the first commit of a nuclei template or Metasploit module where EchelonGraph derived it from the source's git history); null where the source gives none, and EchelonGraph supplies no stand-in date.", + "type": [ + "string", + "null" + ] + }, + "source_url": { + "type": [ + "string", + "null" + ] + }, + "verified_status": { + "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits_by_kind": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_by_status": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_capped": { + "description": "true: exploits lists fewer references than exploits_total.", + "type": "boolean" + }, + "exploits_total": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Every exploit reference on record for the CVE, not only those listed in exploits." + }, + "fixed_versions": { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_version": { + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "vulnerable_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline": { + "items": { + "additionalProperties": {}, + "properties": { + "enriched_at": { + "type": [ + "string", + "null" + ] + }, + "enrichment_kind": { + "type": [ + "string", + "null" + ] + }, + "fields_changed": {}, + "score_delta": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline_count_30d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_count_7d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "cve_id" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_remediation5 fields changed- added
Input schema / properties / ecosystemAdded value: +{ + "description": "Installed version, with package and version: the package's ecosystem, such as npm, PyPI or Maven. Sent in a request header.", + "type": "string" +} - added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - added
Input schema / properties / packageAdded value: +{ + "description": "Installed version, with ecosystem and version: the package name in that ecosystem, such as org.apache.logging.log4j:log4j-core. Sent in a request header.", + "type": "string" +} - added
Input schema / properties / versionAdded value: +{ + "description": "Installed version, with ecosystem and package: the version installed, such as 2.14.1. Sent in a request header.", + "type": "string" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "item_text_cap": { - "type": [ - "number", - "null" - ] - }, - "items_per_advisory_cap": { - "type": [ - "number", - "null" - ] - }, - "parsed_vendors": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors whose remediation EchelonGraph parses." - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API could not read (its failed_sections); null when the answer does not say." - }, - "sections_relayed": { - "items": { - "type": "string" - }, - "type": "array" - }, - "vendor_advisory_limit": { - "type": [ - "number", - "null" - ] - }, - "vendors_not_parsed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors in this answer whose remediation EchelonGraph does not parse." - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "parsed_vendors", - "vendors_not_parsed", - "vendor_advisory_limit", - "item_text_cap", - "items_per_advisory_cap" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cisa": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "due_date": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "required_action": { - "description": "CISA's requiredAction, verbatim. CISA's required_action is directed at US federal civilian agencies (BOD 22-01) and is not EchelonGraph's advice.", - "type": [ - "string", - "null" - ] - }, - "short_description": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "coverage": {}, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "failed_sections": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fix_references": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "source": { - "type": [ - "string", - "null" - ] - }, - "tags": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "description": "The range's last affected version, where no fix is on record; never a fix.", - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "fixed_version": { - "description": "One range's fix, kept for compatibility; not the fix for every affected range.", - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_assessed_reason": { - "type": [ - "string", - "null" - ] - }, - "patches": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "state": { - "description": "assessed, or not_assessed for a CVE record rejected by its numbering authority.", - "type": [ - "string", - "null" - ] - }, - "vendor_remediations": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "items": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "fixed_build": { - "description": "MSRC's FixedBuild; null elsewhere.", - "type": [ - "string", - "null" - ] - }, - "kind": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "The vendor's own category: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other." - }, - "product_count": { - "type": [ - "number", - "null" - ] - }, - "product_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendor's own product identifiers the item applies to, the first 16." - }, - "source_category": { - "description": "The vendor's own name for the category (CSAF vendor_fix, MSRC Vendor Fix, Palo Alto work_around).", - "type": [ - "string", - "null" - ] - }, - "source_subcategory": { - "description": "MSRC's SubType, e.g. Security Update; null elsewhere.", - "type": [ - "string", - "null" - ] - }, - "text": { - "description": "The vendor's text, verbatim but for HTML markup removed, cut at coverage.item_text_cap characters (text_truncated).", - "type": [ - "string", - "null" - ] - }, - "text_chars": { - "description": "The length of the vendor's text in characters.", - "type": [ - "number", - "null" - ] - }, - "text_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "items_total": { - "type": [ - "number", - "null" - ] - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (parsed, and the advisory lists no remediation for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory); withdrawn (the vendor rescinded it)." - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "item_text_cap": { - "type": [ - "number", - "null" - ] - }, - "items_per_advisory_cap": { - "type": [ - "number", - "null" - ] - }, - "parsed_vendors": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors whose remediation EchelonGraph parses." - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API could not read (its failed_sections); null when the answer does not say." - }, - "sections_relayed": { - "items": { - "type": "string" - }, - "type": "array" - }, - "vendor_advisory_limit": { - "type": [ - "number", - "null" - ] - }, - "vendors_not_parsed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors in this answer whose remediation EchelonGraph does not parse." - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "parsed_vendors", - "vendors_not_parsed", - "vendor_advisory_limit", - "item_text_cap", - "items_per_advisory_cap" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "installed_asked": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "ecosystem": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "ecosystem", + "package", + "version" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version this call sent (in request headers), as given; null when none." + }, + "item_text_cap": { + "type": [ + "number", + "null" + ] + }, + "items_per_advisory_cap": { + "type": [ + "number", + "null" + ] + }, + "parsed_vendors": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors whose remediation EchelonGraph parses." + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API could not read (its failed_sections); null when the answer does not say." + }, + "sections_relayed": { + "items": { + "type": "string" + }, + "type": "array" + }, + "vendor_advisory_limit": { + "type": [ + "number", + "null" + ] + }, + "vendors_not_parsed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors in this answer whose remediation EchelonGraph does not parse." + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "parsed_vendors", + "vendors_not_parsed", + "vendor_advisory_limit", + "item_text_cap", + "items_per_advisory_cap", + "installed_asked" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cisa": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "due_date": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "required_action": { + "description": "CISA's requiredAction, verbatim. CISA's required_action is directed at US federal civilian agencies (under BOD 26-04, which replaced BOD 22-01 on 10 June 2026) and is not EchelonGraph's advice.", + "type": [ + "string", + "null" + ] + }, + "short_description": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "coverage": {}, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "failed_sections": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fix_references": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "source": { + "type": [ + "string", + "null" + ] + }, + "tags": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read." + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "fixed_in": { + "description": "With an installed version: the first version above it that no affected range on record holds, always above it, as the advisory states it: the fixed bound of the range holding it, moved past any overlapping range that still holds that bound (fixed_in_detail then names it). null when no range on record holds it, no fix is on record past the ranges holding it, or the version was not assessed, with fixed_in_reason saying which. Absent when no installed version was asked.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the range holding the installed version: the overlapping ranges of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "installed": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "description": "The ecosystem asked for, in its canonical OSV spelling.", + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The affected range holding the version (fixed is exclusive, last_affected inclusive); absent when none holds it." + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "verdict": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "affected", + "not_affected", + "undetermined", + "not_assessed" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "affected (a range on record holds the version), not_affected (no range on record holds it), undetermined (a range could not be decided at it) or not_assessed (the record names no such package for this CVE, or the lookup did not run)." + }, + "version": { + "type": [ + "string", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version asked for, as the API read it from the request headers, and its verdict against this CVE; absent when none was asked." + }, + "not_assessed_reason": { + "type": [ + "string", + "null" + ] + }, + "patches": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "state": { + "description": "assessed, or not_assessed for a CVE record rejected by its numbering authority.", + "type": [ + "string", + "null" + ] + }, + "vendor_remediations": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "items": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "fixed_build": { + "description": "MSRC's FixedBuild; null elsewhere.", + "type": [ + "string", + "null" + ] + }, + "kind": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "The vendor's own category: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other." + }, + "product_count": { + "type": [ + "number", + "null" + ] + }, + "product_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendor's own product identifiers the item applies to, the first 16." + }, + "source_category": { + "description": "The vendor's own name for the category (CSAF vendor_fix, MSRC Vendor Fix, Palo Alto work_around).", + "type": [ + "string", + "null" + ] + }, + "source_subcategory": { + "description": "MSRC's SubType, e.g. Security Update; null elsewhere.", + "type": [ + "string", + "null" + ] + }, + "text": { + "description": "The vendor's text, verbatim but for HTML markup removed, cut at coverage.item_text_cap characters (text_truncated).", + "type": [ + "string", + "null" + ] + }, + "text_chars": { + "description": "The length of the vendor's text in characters.", + "type": [ + "number", + "null" + ] + }, + "text_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "items_total": { + "type": [ + "number", + "null" + ] + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (parsed, and the advisory lists no remediation for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory); withdrawn (the vendor rescinded it)." + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "installed_asked": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "ecosystem": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "ecosystem", + "package", + "version" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The installed version this call sent (in request headers), as given; null when none." + }, + "item_text_cap": { + "type": [ + "number", + "null" + ] + }, + "items_per_advisory_cap": { + "type": [ + "number", + "null" + ] + }, + "parsed_vendors": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors whose remediation EchelonGraph parses." + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API could not read (its failed_sections); null when the answer does not say." + }, + "sections_relayed": { + "items": { + "type": "string" + }, + "type": "array" + }, + "vendor_advisory_limit": { + "type": [ + "number", + "null" + ] + }, + "vendors_not_parsed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors in this answer whose remediation EchelonGraph does not parse." + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "parsed_vendors", + "vendors_not_parsed", + "vendor_advisory_limit", + "item_text_cap", + "items_per_advisory_cap", + "installed_asked" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_summary3 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "poller": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cves_ingested": { - "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", - "type": [ - "number", - "null" - ] - }, - "cves_skipped": { - "description": "CVE records this instance's NVD poller skipped since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "http_retries": { - "description": "HTTP retries this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "interval": { - "description": "How often this instance's NVD poller polls.", - "type": [ - "string", - "null" - ] - }, - "last_poll_at": { - "description": "When this instance's NVD poller last polled: never the feed's freshness.", - "type": [ - "string", - "null" - ] - }, - "last_poll_dur_ms": { - "description": "How long that poll took, in milliseconds.", - "type": [ - "number", - "null" - ] - }, - "poll_count": { - "description": "Polls this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "poll_errors": { - "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." - }, - "summary": { - "additionalProperties": {}, - "description": "summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label (v3.x, else v4.0; before NVD's record arrives, or where it gives none, a pre-NVD label from the CVE.org record or a GitHub advisory can stand in): provenance, never EchelonGraph's severity band. summary.nvd_none counts the active CVEs with no Critical, High, Medium or Low label there, CVEs NVD never labelled under CVSS v3 among them, and many of those carry an NVD CVSS v2 score instead: it is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. Whenever summary.nvd_none is above zero the note says what it counts, with its count.", - "properties": { - "critical": { - "type": [ - "number", - "null" - ] - }, - "high": { - "type": [ - "number", - "null" - ] - }, - "last_updated": { - "type": [ - "string", - "null" - ] - }, - "low": { - "type": [ - "number", - "null" - ] - }, - "medium": { - "type": [ - "number", - "null" - ] - }, - "none": { - "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", - "type": [ - "number", - "null" - ] - }, - "nvd_critical": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_high": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_low": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_medium": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_none": { - "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", - "type": [ - "number", - "null" - ] - }, - "rejected": { - "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "unscored": { - "description": "The same count as none, under its own name.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "poller": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cves_ingested": { + "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", + "type": [ + "number", + "null" + ] + }, + "cves_skipped": { + "description": "CVE records this instance's NVD poller skipped since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "http_retries": { + "description": "HTTP retries this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "interval": { + "description": "How often this instance's NVD poller polls.", + "type": [ + "string", + "null" + ] + }, + "last_poll_at": { + "description": "When this instance's NVD poller last polled: never the feed's freshness.", + "type": [ + "string", + "null" + ] + }, + "last_poll_dur_ms": { + "description": "How long that poll took, in milliseconds.", + "type": [ + "number", + "null" + ] + }, + "poll_count": { + "description": "Polls this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "poll_errors": { + "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." + }, + "summary": { + "additionalProperties": {}, + "description": "summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label (v3.x, else v4.0; before NVD's record arrives, or where it gives none, a pre-NVD label from the CVE.org record or a GitHub advisory can stand in): provenance, never EchelonGraph's severity band. summary.nvd_none counts the active CVEs with no Critical, High, Medium or Low label there, CVEs NVD never labelled under CVSS v3 among them, and many of those carry an NVD CVSS v2 score instead: it is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. Whenever summary.nvd_none is above zero the note says what it counts, with its count.", + "properties": { + "critical": { + "type": [ + "number", + "null" + ] + }, + "high": { + "type": [ + "number", + "null" + ] + }, + "last_updated": { + "type": [ + "string", + "null" + ] + }, + "low": { + "type": [ + "number", + "null" + ] + }, + "medium": { + "type": [ + "number", + "null" + ] + }, + "none": { + "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", + "type": [ + "number", + "null" + ] + }, + "nvd_critical": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_high": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_low": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_medium": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_none": { + "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", + "type": [ + "number", + "null" + ] + }, + "rejected": { + "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "unscored": { + "description": "The same count as none, under its own name.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
epss_history2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day the record holds; null when none are listed." - }, - "days_missing": { - "description": "Score dates from first_day to last_day the record does not hold.", - "items": { - "type": "string" - }, - "type": "array" - }, - "days_partial": { - "description": "Score dates held for some CVEs only.", - "items": { - "type": "string" - }, - "type": "array" - }, - "first_day": { - "description": "The earliest FIRST score date the run log lists; null when it lists none.", - "type": [ - "string", - "null" - ] - }, - "last_day": { - "type": [ - "string", - "null" - ] - }, - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "How many of them fall where changes are missing; null when the API did not say." - }, - "points_truncated": { - "type": "boolean" - }, - "series_complete": { - "description": "True only when the API says nothing in the record predates complete_since.", - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "complete_since", - "series_complete", - "points", - "points_before_complete_since", - "points_truncated", - "first_day", - "last_day", - "days_held", - "days_partial", - "days_missing" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when the record holds every change a refresh applied. Between series_starts_at and complete_since changes are missing, so a missing point there does not mean unchanged. Absent from an API older than #2867." - }, - "coverage": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From here on every change a refresh applied is a point; before it changes are missing." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day that a refresh applied completely." - }, - "days_missing": { - "anyOf": [ - { - "items": { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day that no refresh applied." - }, - "days_partial": { - "anyOf": [ - { - "items": { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Score dates whose refreshes all failed part-way: some CVEs hold that day, some do not." - }, - "first_day": { - "anyOf": [ - { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The earliest score date in the run log." - }, - "last_day": { - "anyOf": [ - { - "description": "A FIRST score date, YYYY-MM-DD.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The latest score date in the run log." - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "This CVE's points in the part of the record that misses changes." - }, - "recorded_from": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "series_starts_at: when recording began." - }, - "refresh_runs_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "run_log_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The first logged refresh: score dates before it are not listed, held or missing." - }, - "runs_undated": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ] - }, - "series_complete": { - "description": "True only when nothing in the record predates complete_since.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "Which part of the record is complete and which FIRST score dates it holds." - }, - "current": { - "additionalProperties": {}, - "properties": { - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The record's EPSS probability now; null when it holds none.", - "type": [ - "number", - "null" - ] - }, - "epss_updated_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." - } - }, - "type": "object" - }, - "cve_id": { - "type": "string" - }, - "history_rows": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Raw history rows read, before repeated records of one change were collapsed." - }, - "latest_point_matches_current": { - "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", - "type": [ - "boolean", - "null" - ] - }, - "points": { - "description": "Recorded changes, oldest first. Never a daily series.", - "items": { - "additionalProperties": {}, - "properties": { - "at": { - "description": "When EchelonGraph recorded this change.", - "type": "string" - }, - "epss_percentile": { - "description": "Its percentile (0 to 1), null where the record held none.", - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The EPSS probability (0 to 1) from that change on.", - "type": "number" - }, - "score_date": { - "description": "FIRST's score date (YYYY-MM-DD) of the logged refresh that wrote this point; null where no logged refresh covers it.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "at", - "epss_score" - ], - "type": "object" - }, - "type": "array" - }, - "points_truncated": { - "description": "True when only the newest rows were read, so the earliest points are missing.", - "type": [ - "boolean", - "null" - ] - }, - "series_kind": { - "description": "Always change_only: one point per recorded change, none for a day without one.", - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." - } - }, - "required": [ - "cve_id", - "series_kind", - "series_starts_at", - "current", - "points" - ], - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "complete_since": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." - }, - "days_held": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Score dates from first_day to last_day the record holds; null when none are listed." - }, - "days_missing": { - "description": "Score dates from first_day to last_day the record does not hold.", - "items": { - "type": "string" - }, - "type": "array" - }, - "days_partial": { - "description": "Score dates held for some CVEs only.", - "items": { - "type": "string" - }, - "type": "array" - }, - "first_day": { - "description": "The earliest FIRST score date the run log lists; null when it lists none.", - "type": [ - "string", - "null" - ] - }, - "last_day": { - "type": [ - "string", - "null" - ] - }, - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_before_complete_since": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "How many of them fall where changes are missing; null when the API did not say." - }, - "points_truncated": { - "type": "boolean" - }, - "series_complete": { - "description": "True only when the API says nothing in the record predates complete_since.", - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "complete_since", - "series_complete", - "points", - "points_before_complete_since", - "points_truncated", - "first_day", - "last_day", - "days_held", - "days_partial", - "days_missing" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when the record holds every change a refresh applied. Between series_starts_at and complete_since changes are missing, so a missing point there does not mean unchanged. Absent from an API older than #2867." + }, + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From here on every change a refresh applied is a point; before it changes are missing." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that a refresh applied completely." + }, + "days_missing": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that no refresh applied." + }, + "days_partial": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates whose refreshes all failed part-way: some CVEs hold that day, some do not." + }, + "first_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest score date in the run log." + }, + "last_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The latest score date in the run log." + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "This CVE's points in the part of the record that misses changes." + }, + "recorded_from": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "series_starts_at: when recording began." + }, + "refresh_runs_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "run_log_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The first logged refresh: score dates before it are not listed, held or missing." + }, + "runs_undated": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "series_complete": { + "description": "True only when nothing in the record predates complete_since.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Which part of the record is complete and which FIRST score dates it holds." + }, + "current": { + "additionalProperties": {}, + "properties": { + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The record's EPSS probability now; null when it holds none.", + "type": [ + "number", + "null" + ] + }, + "epss_updated_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." + } + }, + "type": "object" + }, + "cve_id": { + "type": "string" + }, + "history_rows": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Raw history rows read, before repeated records of one change were collapsed." + }, + "latest_point_matches_current": { + "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", + "type": [ + "boolean", + "null" + ] + }, + "points": { + "description": "Recorded changes, oldest first. Never a daily series.", + "items": { + "additionalProperties": {}, + "properties": { + "at": { + "description": "When EchelonGraph recorded this change.", + "type": "string" + }, + "epss_percentile": { + "description": "Its percentile (0 to 1), null where the record held none.", + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The EPSS probability (0 to 1) from that change on.", + "type": "number" + }, + "score_date": { + "description": "FIRST's score date (YYYY-MM-DD) of the logged refresh that wrote this point; null where no logged refresh covers it.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "at", + "epss_score" + ], + "type": "object" + }, + "type": "array" + }, + "points_truncated": { + "description": "True when only the newest rows were read, so the earliest points are missing.", + "type": [ + "boolean", + "null" + ] + }, + "series_kind": { + "description": "Always change_only: one point per recorded change, none for a day without one.", + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." + } + }, + "required": [ + "cve_id", + "series_kind", + "series_starts_at", + "current", + "points" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
exposure_radar3 fields changed- added
Input schema / $schemaAdded value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "description": "A field this version cannot label is left out of data and named in the note. Each of the kev_exposure, exposed_databases and leaked_credentials radars also carries generated_at, when the API computed its totals, and, when the API can tell, last_run_at. kev_exposure.last_run_at, exposed_databases.last_run_at and leaked_credentials.last_run_at are timestamps, not counts: each is when that radar last completed a check, a cycle whose reads succeeded, among them a Shodan search (for exposed_databases, or its LeakIX fallback) that answered at least one query, or for leaked_credentials a read of the public GitHub event stream. A cycle that read nothing does not move it, and it is not the time of every record a radar's numbers count, which cover everything still on record, not only what the last check found. A radar whose answer carries no last_run_at has none in the result, and the note says nothing about it. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "exposed_databases": { - "additionalProperties": false, - "description": "exposed_databases: exposed_databases.distinct_hosts counts distinct ip:port services the check confirmed answering without authentication, and exposed_databases.engines the distinct engine types among them; exposed_databases.top_engines and exposed_databases.top_countries rank up to 15 engines and 10 countries by those services. exposed_databases.pii_likely and exposed_databases.pci_likely count services whose schema names (never record values) pass a high-confidence, precision-first gate for personal or payment-card data, so a service outside them is not shown to hold no such data. exposed_databases.window.from and exposed_databases.window.to are timestamps, not counts: when EchelonGraph's check last confirmed the oldest and the newest of the services counted, a span of checks made at different times; with a counted service that has no such time on record there is no window.", - "properties": { - "distinct_hosts": { - "type": "number" - }, - "engines": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "pci_likely": { - "type": "number" - }, - "pii_likely": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_engines": { - "items": { - "additionalProperties": false, - "properties": { - "engine": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "engine", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "description": "kev_exposure: kev_exposure.distinct_hosts counts distinct ip:port services, not machines (a machine answering on two ports counts twice), with at least one CISA-KEV-listed CVE on record, and kev_exposure.ransomware_hosts those with a ransomware-linked one; kev_exposure.kev_cves_exposed and kev_exposure.ransomware_cves count distinct CVEs with at least one such service; kev_exposure.correlations counts service×CVE pairs, not services, so a service with three KEV CVEs counts three times. kev_exposure.top_products, kev_exposure.top_countries and kev_exposure.top_cves rank up to 12 products, 10 countries and 12 CVEs by those services; kev_exposure.top_cves[].cvss_v3_score and kev_exposure.top_cves[].epss_score are the highest CVSS v3 base score and EPSS probability recorded on that CVE's observations. kev_exposure.trend counts service×CVE pairs still on record by the week in which each was first recorded, over 12 weeks, so earlier weeks read low. kev_exposure.newest_kev lists the 15 CVEs that EchelonGraph's CVE records most recently mark as CISA-KEV-listed, each with an exposure_state: exposed, where kev_exposure.newest_kev[].exposed_hosts counts distinct ip:port services on record with it; or not_assessed, where the API's answer holds no measurement for that CVE (its 0 is not one) and no count is relayed, and this answer does not say whether the radar tracks that CVE: tracking is answered per CVE. kev_exposure.newest_kev[].cvss_v3_score and kev_exposure.newest_kev[].epss_score are the CVE record's CVSS v3 base score and EPSS probability. kev_exposure.window.from and kev_exposure.window.to are timestamps, not counts: when Shodan collected the banners of the oldest and the newest of the service×CVE pairs counted, a span of observations made at different times; with a counted pair that has no such time on record there is no window. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "correlations": { - "type": "number" - }, - "distinct_hosts": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "kev_cves_exposed": { - "type": "number" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "newest_kev": { - "items": { - "additionalProperties": false, - "properties": { - "added_date": { - "type": "string" - }, - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "exposed_hosts": { - "type": "number" - }, - "exposure_state": { - "enum": [ - "exposed", - "measured_zero", - "not_assessed" - ], - "type": "string" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - }, - "vuln_name": { - "type": "string" - } - }, - "required": [ - "cve_id", - "exposure_state" - ], - "type": "object" - }, - "type": "array" - }, - "ransomware_cves": { - "type": "number" - }, - "ransomware_hosts": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_cves": { - "items": { - "additionalProperties": false, - "properties": { - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "hosts": { - "type": "number" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - } - }, - "required": [ - "cve_id", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "hosts": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "trend": { - "items": { - "additionalProperties": false, - "properties": { - "new_exposures": { - "type": "number" - }, - "week": { - "type": "string" - } - }, - "required": [ - "week", - "new_exposures" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "description": "leaked_credentials: leaked_credentials.total counts (repository, secret) pairs, not distinct secrets, so one secret in three repositories counts three times; leaked_credentials.distinct_secrets counts each secret once and leaked_credentials.distinct_repos counts repositories; leaked_credentials.top_providers and leaked_credentials.top_types rank up to 15 providers and secret types by those pairs. None is validated: each is a credential-shaped string that passed EchelonGraph's filters, at most structurally checked and never tested against its provider. leaked_credentials.window.from and leaked_credentials.window.to are timestamps, not counts: when EchelonGraph's detector last found the oldest and the newest of the pairs counted.", - "properties": { - "distinct_repos": { - "type": "number" - }, - "distinct_secrets": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_providers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "provider": { - "type": "string" - } - }, - "required": [ - "provider", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_types": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "secret_type": { - "type": "string" - } - }, - "required": [ - "secret_type", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "description": "mcp_servers: counts and timestamps only, no hostname. mcp_servers.total counts hostnames the AI-exposure radar has checked for an MCP server, each once by its latest verdict on record, and not every one is an MCP server; EchelonGraph's own control servers are left out, and mcp_servers.own_controls_excluded counts them; hostnames whose owner opted out of scanning are not checked again while the opt-out stands, so their last verdict is left out too, and mcp_servers.withheld_opted_out counts them. mcp_servers.total is mcp_servers.protected plus mcp_servers.pending_readjudication plus mcp_servers.not_assessed. mcp_servers.protected counts hostnames whose /mcp endpoint asked for credentials and whose OAuth protected-resource metadata validated under RFC 9728; mcp_servers.prm_via divides them by where that document was found: mcp_servers.prm_via.header, mcp_servers.prm_via.wellknown_path and mcp_servers.prm_via.wellknown_root. mcp_servers.pending_readjudication counts verdicts of a rule since replaced, not yet re-checked. mcp_servers.not_assessed counts the rest, whose protection the radar could not assess (not assessed does not mean unprotected), and mcp_servers.not_assessed_by_reason puts each in one bucket. mcp_servers.not_assessed_by_reason.identified_no_challenge holds servers that identified themselves as MCP servers and did not ask for credentials at the handshake. That is normal in MCP: authorization is optional in the spec, and a server can enforce it at tools/call instead, which EchelonGraph never sends, so this bucket is not a finding of exposure. mcp_servers.not_assessed_by_reason.resource_mismatch, mcp_servers.not_assessed_by_reason.cross_origin_pointer, mcp_servers.not_assessed_by_reason.bare_challenge_no_prm, mcp_servers.not_assessed_by_reason.pointer_unreachable, mcp_servers.not_assessed_by_reason.pointer_invalid, mcp_servers.not_assessed_by_reason.no_authorization_servers, mcp_servers.not_assessed_by_reason.wellknown_unreachable and mcp_servers.not_assessed_by_reason.metadata_invalid hold endpoints that asked for credentials but whose RFC 9728 metadata did not validate, by why, so none of them is shown to lack protection; mcp_servers.not_assessed_by_reason.challenge_unadjudicated holds endpoints that asked for credentials before that check existed, not yet re-checked. mcp_servers.not_assessed_by_reason.no_http_answer holds hostnames that gave no HTTP answer, and mcp_servers.not_assessed_by_reason.not_identified_as_mcp hostnames whose HTTP answer identified no MCP server. mcp_servers.era divides every counted hostname by protocol era: mcp_servers.era.legacy; mcp_servers.era.dual, a lower bound; mcp_servers.era.modern, not proven modern-only; mcp_servers.era.unknown; and mcp_servers.era.not_measured, recorded before the era probe and not re-checked since. mcp_servers.transport divides them by transport: mcp_servers.transport.streamable_http, mcp_servers.transport.legacy_sse, mcp_servers.transport.unknown and mcp_servers.transport.not_measured. mcp_servers.window.from and mcp_servers.window.to are when the oldest and the newest of the verdicts counted were last checked. mcp_servers.last_run_at is a timestamp, not a count: when the AI-exposure radar, which checks other AI services too, last completed a check; mcp_servers.enabled is whether one completed within 45 minutes of the answer, and mcp_servers.counted_at is when the API read the counts. A partition whose buckets do not add up to the count it divides is left out and named; an answer that does not say it is the MCP-server counts, or whose mcp_servers.total, mcp_servers.protected, mcp_servers.pending_readjudication and mcp_servers.not_assessed are missing or contradict each other, is a failure.", - "properties": { - "counted_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "era": { - "additionalProperties": false, - "properties": { - "dual": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "legacy": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "modern": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "legacy", - "dual", - "modern", - "unknown", - "not_measured" - ], - "type": "object" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "not_assessed": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_assessed_by_reason": { - "additionalProperties": false, - "properties": { - "bare_challenge_no_prm": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "challenge_unadjudicated": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "cross_origin_pointer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "identified_no_challenge": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "metadata_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_authorization_servers": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_http_answer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_identified_as_mcp": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "resource_mismatch": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "identified_no_challenge", - "resource_mismatch", - "cross_origin_pointer", - "bare_challenge_no_prm", - "pointer_unreachable", - "pointer_invalid", - "no_authorization_servers", - "wellknown_unreachable", - "metadata_invalid", - "challenge_unadjudicated", - "no_http_answer", - "not_identified_as_mcp" - ], - "type": "object" - }, - "own_controls_excluded": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pending_readjudication": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "prm_via": { - "additionalProperties": false, - "properties": { - "header": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_path": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_root": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "header", - "wellknown_path", - "wellknown_root" - ], - "type": "object" - }, - "protected": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "transport": { - "additionalProperties": false, - "properties": { - "legacy_sse": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "streamable_http": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "streamable_http", - "legacy_sse", - "unknown", - "not_measured" - ], - "type": "object" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "withheld_opted_out": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "protected", - "pending_readjudication", - "not_assessed" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "description": "shadow_ai: the result is regrouped by what each number counts. shadow_ai.confirmed_exposed counts services EchelonGraph's probes found answering without an authentication gate (liveness active, or rechecking during a re-check): confirmed_exposed.total is the sum of confirmed_exposed.by_category, and confirmed_exposed.last_24h counts those first recorded in the last 24 h. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. confirmed_exposed.window.from and confirmed_exposed.window.to are timestamps, not counts: when EchelonGraph's verifier ran the probe that last decided the oldest and the newest of those services, a span of probes made at different times. shadow_ai.observed counts every Certificate Transparency or Shodan observation on record, whatever its verification state: its numbers are observed, not exposed. They are observed.total; observed.by_category (the same observations by category); observed.last_24h (those first recorded in the last 24 h); observed.trend_30d (observations per UTC day over the last 30 days); and observed.top_products, observed.top_countries and observed.top_issuers (up to ten products, countries and issuers ranked by observations, where an issuer is the certificate's CA for a Certificate Transparency observation and the hosting operator Shodan reports for a Shodan one). shadow_ai.authentication counts observations by probe outcome: authentication.observed where a probe observed an authentication gate (a 401/403, a login page or an auth marker), and authentication.not_determined where the service answered but no probe could tell. Neither authentication count is part of confirmed_exposed, and observed.total minus confirmed_exposed.total is not a count of secured services. The shadow-AI poller block carries only running and last_run_at: last_run_at is when the radar's leader last completed a Certificate Transparency (crt.sh) cycle, and its running is true only when that was within 30 minutes of the answer. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", - "properties": { - "authentication": { - "additionalProperties": false, - "properties": { - "not_determined": { - "type": "number" - }, - "observed": { - "type": "number" - } - }, - "type": "object" - }, - "confirmed_exposed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "observed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "last_observation": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "country": { - "type": "string" - } - }, - "required": [ - "country", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_issuers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "issuer": { - "type": "string" - } - }, - "required": [ - "issuer", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "trend_30d": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "date": { - "type": "string" - } - }, - "required": [ - "date", - "count" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "poller": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "running": { - "type": "boolean" - } - }, - "required": [ - "running", - "last_run_at" - ], - "type": "object" - } - }, - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at", - "enabled" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - }, - "running": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "last_run_at", - "running" - ], - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "radars": { - "description": "Each radar that could not be read, and why.", - "items": { - "additionalProperties": false, - "properties": { - "kind": { - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "unexpected_shape" - ], - "type": "string" - }, - "message": { - "type": "string" - }, - "path": { - "type": "string" - }, - "radar": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "radar", - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "type": "array" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "description": "A field this version cannot label is left out of data and named in the note. Each of the kev_exposure, exposed_databases and leaked_credentials radars also carries generated_at, when the API computed its totals, and, when the API can tell, last_run_at. kev_exposure.last_run_at, exposed_databases.last_run_at and leaked_credentials.last_run_at are timestamps, not counts: each is when that radar last completed a check, a cycle whose reads succeeded, among them a Shodan search (for exposed_databases, or its LeakIX fallback) that answered at least one query, or for leaked_credentials a read of the public GitHub event stream. A cycle that read nothing does not move it, and it is not the time of every record a radar's numbers count, which cover everything still on record, not only what the last check found. A radar whose answer carries no last_run_at has none in the result, and the note says nothing about it. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "exposed_databases": { + "additionalProperties": false, + "description": "exposed_databases: exposed_databases.distinct_hosts counts distinct ip:port services the check confirmed answering without authentication, and exposed_databases.engines the distinct engine types among them; exposed_databases.top_engines and exposed_databases.top_countries rank up to 15 engines and 10 countries by those services. exposed_databases.pii_likely and exposed_databases.pci_likely count services whose schema names (never record values) pass a high-confidence, precision-first gate for personal or payment-card data, so a service outside them is not shown to hold no such data. exposed_databases.window.from and exposed_databases.window.to are timestamps, not counts: when EchelonGraph's check last confirmed the oldest and the newest of the services counted, a span of checks made at different times; with a counted service that has no such time on record there is no window.", + "properties": { + "distinct_hosts": { + "type": "number" + }, + "engines": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "pci_likely": { + "type": "number" + }, + "pii_likely": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_engines": { + "items": { + "additionalProperties": false, + "properties": { + "engine": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "engine", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "description": "kev_exposure: kev_exposure.distinct_hosts counts distinct ip:port services, not machines (a machine answering on two ports counts twice), with at least one CISA-KEV-listed CVE on record, and kev_exposure.ransomware_hosts those with a ransomware-linked one; kev_exposure.kev_cves_exposed and kev_exposure.ransomware_cves count distinct CVEs with at least one such service; kev_exposure.correlations counts service×CVE pairs, not services, so a service with three KEV CVEs counts three times. kev_exposure.top_products, kev_exposure.top_countries and kev_exposure.top_cves rank up to 12 products, 10 countries and 12 CVEs by those services; kev_exposure.top_cves[].cvss_v3_score and kev_exposure.top_cves[].epss_score are the highest CVSS v3 base score and EPSS probability recorded on that CVE's observations. kev_exposure.trend counts service×CVE pairs still on record by the week in which each was first recorded, over 12 weeks, so earlier weeks read low. kev_exposure.newest_kev lists the 15 CVEs that EchelonGraph's CVE records most recently mark as CISA-KEV-listed, each with an exposure_state: exposed, where kev_exposure.newest_kev[].exposed_hosts counts distinct ip:port services on record with it; or not_assessed, where the API's answer holds no measurement for that CVE (its 0 is not one) and no count is relayed, and this answer does not say whether the radar tracks that CVE: tracking is answered per CVE. kev_exposure.newest_kev[].cvss_v3_score and kev_exposure.newest_kev[].epss_score are the CVE record's CVSS v3 base score and EPSS probability. kev_exposure.window.from and kev_exposure.window.to are timestamps, not counts: when Shodan collected the banners of the oldest and the newest of the service×CVE pairs counted, a span of observations made at different times; with a counted pair that has no such time on record there is no window. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "correlations": { + "type": "number" + }, + "distinct_hosts": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "kev_cves_exposed": { + "type": "number" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "newest_kev": { + "items": { + "additionalProperties": false, + "properties": { + "added_date": { + "type": "string" + }, + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "exposed_hosts": { + "type": "number" + }, + "exposure_state": { + "enum": [ + "exposed", + "measured_zero", + "not_assessed" + ], + "type": "string" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "vuln_name": { + "type": "string" + } + }, + "required": [ + "cve_id", + "exposure_state" + ], + "type": "object" + }, + "type": "array" + }, + "ransomware_cves": { + "type": "number" + }, + "ransomware_hosts": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_cves": { + "items": { + "additionalProperties": false, + "properties": { + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "hosts": { + "type": "number" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + }, + "required": [ + "cve_id", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "hosts": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "trend": { + "items": { + "additionalProperties": false, + "properties": { + "new_exposures": { + "type": "number" + }, + "week": { + "type": "string" + } + }, + "required": [ + "week", + "new_exposures" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "description": "leaked_credentials: leaked_credentials.total counts (repository, secret) pairs, not distinct secrets, so one secret in three repositories counts three times; leaked_credentials.distinct_secrets counts each secret once and leaked_credentials.distinct_repos counts repositories; leaked_credentials.top_providers and leaked_credentials.top_types rank up to 15 providers and secret types by those pairs. None is validated: each is a credential-shaped string that passed EchelonGraph's filters, at most structurally checked and never tested against its provider. leaked_credentials.window.from and leaked_credentials.window.to are timestamps, not counts: when EchelonGraph's detector last found the oldest and the newest of the pairs counted.", + "properties": { + "distinct_repos": { + "type": "number" + }, + "distinct_secrets": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_providers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "provider": { + "type": "string" + } + }, + "required": [ + "provider", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_types": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "secret_type": { + "type": "string" + } + }, + "required": [ + "secret_type", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "description": "mcp_servers: counts and timestamps only, no hostname. mcp_servers.total counts hostnames the AI-exposure radar has checked for an MCP server, each once by its latest verdict on record, and not every one is an MCP server; EchelonGraph's own control servers are left out, and mcp_servers.own_controls_excluded counts them; hostnames whose owner opted out of scanning are not checked again while the opt-out stands, so their last verdict is left out too, and mcp_servers.withheld_opted_out counts them. mcp_servers.total is mcp_servers.protected plus mcp_servers.pending_readjudication plus mcp_servers.not_assessed. mcp_servers.protected counts hostnames whose /mcp endpoint asked for credentials and whose OAuth protected-resource metadata validated under RFC 9728; mcp_servers.prm_via divides them by where that document was found: mcp_servers.prm_via.header, mcp_servers.prm_via.wellknown_path and mcp_servers.prm_via.wellknown_root. mcp_servers.pending_readjudication counts verdicts of a rule since replaced, not yet re-checked. mcp_servers.not_assessed counts the rest, whose protection the radar could not assess (not assessed does not mean unprotected), and mcp_servers.not_assessed_by_reason puts each in one bucket. mcp_servers.not_assessed_by_reason.identified_no_challenge holds servers that identified themselves as MCP servers and did not ask for credentials at the handshake. That is normal in MCP: authorization is optional in the spec, and a server can enforce it at tools/call instead, which EchelonGraph never sends, so this bucket is not a finding of exposure. mcp_servers.not_assessed_by_reason.resource_mismatch, mcp_servers.not_assessed_by_reason.cross_origin_pointer, mcp_servers.not_assessed_by_reason.bare_challenge_no_prm, mcp_servers.not_assessed_by_reason.pointer_unreachable, mcp_servers.not_assessed_by_reason.pointer_invalid, mcp_servers.not_assessed_by_reason.no_authorization_servers, mcp_servers.not_assessed_by_reason.wellknown_unreachable and mcp_servers.not_assessed_by_reason.metadata_invalid hold endpoints that asked for credentials but whose RFC 9728 metadata did not validate, by why, so none of them is shown to lack protection; mcp_servers.not_assessed_by_reason.challenge_unadjudicated holds endpoints that asked for credentials before that check existed, not yet re-checked. mcp_servers.not_assessed_by_reason.no_http_answer holds hostnames that gave no HTTP answer, and mcp_servers.not_assessed_by_reason.not_identified_as_mcp hostnames whose HTTP answer identified no MCP server. mcp_servers.era divides every counted hostname by protocol era: mcp_servers.era.legacy; mcp_servers.era.dual, a lower bound; mcp_servers.era.modern, not proven modern-only; mcp_servers.era.unknown; and mcp_servers.era.not_measured, recorded before the era probe and not re-checked since. mcp_servers.transport divides them by transport: mcp_servers.transport.streamable_http, mcp_servers.transport.legacy_sse, mcp_servers.transport.unknown and mcp_servers.transport.not_measured. mcp_servers.window.from and mcp_servers.window.to are when the oldest and the newest of the verdicts counted were last checked. mcp_servers.last_run_at is a timestamp, not a count: when the AI-exposure radar, which checks other AI services too, last completed a check; mcp_servers.enabled is whether one completed within 45 minutes of the answer, and mcp_servers.counted_at is when the API read the counts. A partition whose buckets do not add up to the count it divides is left out and named; an answer that does not say it is the MCP-server counts, or whose mcp_servers.total, mcp_servers.protected, mcp_servers.pending_readjudication and mcp_servers.not_assessed are missing or contradict each other, is a failure.", + "properties": { + "counted_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "era": { + "additionalProperties": false, + "properties": { + "dual": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "legacy": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "modern": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "legacy", + "dual", + "modern", + "unknown", + "not_measured" + ], + "type": "object" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "not_assessed": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_assessed_by_reason": { + "additionalProperties": false, + "properties": { + "bare_challenge_no_prm": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "challenge_unadjudicated": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "cross_origin_pointer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "identified_no_challenge": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "metadata_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_authorization_servers": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_http_answer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_identified_as_mcp": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "resource_mismatch": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "identified_no_challenge", + "resource_mismatch", + "cross_origin_pointer", + "bare_challenge_no_prm", + "pointer_unreachable", + "pointer_invalid", + "no_authorization_servers", + "wellknown_unreachable", + "metadata_invalid", + "challenge_unadjudicated", + "no_http_answer", + "not_identified_as_mcp" + ], + "type": "object" + }, + "own_controls_excluded": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pending_readjudication": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "prm_via": { + "additionalProperties": false, + "properties": { + "header": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_path": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_root": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "header", + "wellknown_path", + "wellknown_root" + ], + "type": "object" + }, + "protected": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "transport": { + "additionalProperties": false, + "properties": { + "legacy_sse": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "streamable_http": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "streamable_http", + "legacy_sse", + "unknown", + "not_measured" + ], + "type": "object" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "withheld_opted_out": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "protected", + "pending_readjudication", + "not_assessed" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "description": "shadow_ai: the result is regrouped by what each number counts. shadow_ai.confirmed_exposed counts services EchelonGraph's probes found answering without an authentication gate (liveness active, or rechecking during a re-check): confirmed_exposed.total is the sum of confirmed_exposed.by_category, and confirmed_exposed.last_24h counts those first recorded in the last 24 h. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. confirmed_exposed.window.from and confirmed_exposed.window.to are timestamps, not counts: when EchelonGraph's verifier ran the probe that last decided the oldest and the newest of those services, a span of probes made at different times. shadow_ai.observed counts every Certificate Transparency or Shodan observation on record, whatever its verification state: its numbers are observed, not exposed. They are observed.total; observed.by_category (the same observations by category); observed.last_24h (those first recorded in the last 24 h); observed.trend_30d (observations per UTC day over the last 30 days); and observed.top_products, observed.top_countries and observed.top_issuers (up to ten products, countries and issuers ranked by observations, where an issuer is the certificate's CA for a Certificate Transparency observation and the hosting operator Shodan reports for a Shodan one). shadow_ai.authentication counts observations by probe outcome: authentication.observed where a probe observed an authentication gate (a 401/403, a login page or an auth marker), and authentication.not_determined where the service answered but no probe could tell. Neither authentication count is part of confirmed_exposed, and observed.total minus confirmed_exposed.total is not a count of secured services. The shadow-AI poller block carries only running and last_run_at: last_run_at is when the radar's leader last completed a Certificate Transparency (crt.sh) cycle, and its running is true only when that was within 30 minutes of the answer. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "authentication": { + "additionalProperties": false, + "properties": { + "not_determined": { + "type": "number" + }, + "observed": { + "type": "number" + } + }, + "type": "object" + }, + "confirmed_exposed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "observed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "last_observation": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "country": { + "type": "string" + } + }, + "required": [ + "country", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_issuers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "issuer": { + "type": "string" + } + }, + "required": [ + "issuer", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "trend_30d": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "date": { + "type": "string" + } + }, + "required": [ + "date", + "count" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "poller": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "running": { + "type": "boolean" + } + }, + "required": [ + "running", + "last_run_at" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "exposed_databases": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + }, + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at", + "enabled" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "running": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "last_run_at", + "running" + ], + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "radars": { + "description": "Each radar that could not be read, and why.", + "items": { + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "unexpected_shape" + ], + "type": "string" + }, + "message": { + "type": "string" + }, + "path": { + "type": "string" + }, + "radar": { + "type": "string" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "radar", + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_cve2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_required_action": { - "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 22-01, by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "kev_short_description": { - "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "release_reference", - "nvd_patch_reference", - "cna_patch_reference" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), nvd_patch_reference (an NVD reference tagged Patch) and cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": {}, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", - "type": [ - "string", - "null" - ] - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "cna": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "name": { + "type": [ + "string", + "null" + ] + }, + "short_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." + }, + "cna_solution": { + "description": "The sentence of the CVE record's solutions, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "date_public": { + "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "date_public_source": { + "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "echelongraph_ssvc_decision": { + "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "vendor_advisory_fix", + "nvd_patch_reference", + "cna_patch_reference", + "cna_solution", + "description_fix" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions, written by its CNA, that names a fixed version; relayed as cna_solution) and description_fix (a sentence of the CVE description that names a fixed version). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_factors": { + "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_cwe2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max_page": { - "type": [ - "number", - "null" - ] - }, - "page": { - "description": "The page served.", - "type": [ - "number", - "null" - ] - }, - "page_requested": { - "description": "The page asked for.", - "type": "number" - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "page", - "page_requested", - "page_size", - "max_page" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "catalog_version": { - "description": "The version of the MITRE CWE catalog name and description come from.", - "type": [ - "string", - "null" - ] - }, - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v2_severity": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: a score only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE; false: NOT YET SCORED, not scored 0.", - "type": [ - "boolean", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "max_page": { - "description": "The last page the API serves; a later page is answered as this one.", - "type": [ - "number", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "order": { - "description": "How cves is sorted, as the API states it; absent from an API older than the field, which sorted by CVE id.", - "type": [ - "string", - "null" - ] - }, - "page": { - "type": [ - "number", - "null" - ] - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "The active CVEs classified under the CWE, rejected and reserved records left out.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "max_page": { - "type": [ - "number", - "null" - ] - }, - "page": { - "description": "The page served.", - "type": [ - "number", - "null" - ] - }, - "page_requested": { - "description": "The page asked for.", - "type": "number" - }, - "page_size": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "page", - "page_requested", - "page_size", - "max_page" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max_page": { + "type": [ + "number", + "null" + ] + }, + "page": { + "description": "The page served.", + "type": [ + "number", + "null" + ] + }, + "page_requested": { + "description": "The page asked for.", + "type": "number" + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "total", + "returned", + "page", + "page_requested", + "page_size", + "max_page" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "catalog_version": { + "description": "The version of the MITRE CWE catalog name and description come from.", + "type": [ + "string", + "null" + ] + }, + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v2_severity": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: a score only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE; false: NOT YET SCORED, not scored 0.", + "type": [ + "boolean", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "max_page": { + "description": "The last page the API serves; a later page is answered as this one.", + "type": [ + "number", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "order": { + "description": "How cves is sorted, as the API states it; absent from an API older than the field, which sorted by CVE id.", + "type": [ + "string", + "null" + ] + }, + "page": { + "type": [ + "number", + "null" + ] + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "The active CVEs classified under the CWE, rejected and reserved records left out.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "max_page": { + "type": [ + "number", + "null" + ] + }, + "page": { + "description": "The page served.", + "type": [ + "number", + "null" + ] + }, + "page_requested": { + "description": "The page asked for.", + "type": "number" + }, + "page_size": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "total", + "returned", + "page", + "page_requested", + "page_size", + "max_page" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_vendor_advisory2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "known_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "references": {}, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation": { - "description": "The vendor's remediation as one text (the legacy field), beside remediations.", - "type": [ - "string", - "null" - ] - }, - "remediation_items_not_stored": { - "description": "Items past the 64 stored per advisory.", - "type": [ - "number", - "null" - ] - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "remediations": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVEs the item covers; [] for the whole advisory." - }, - "fixed_build": { - "type": [ - "string", - "null" - ] - }, - "kind": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ] - }, - "product_count": { - "type": [ - "number", - "null" - ] - }, - "product_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "source_category": { - "description": "The vendor's own name for the category.", - "type": [ - "string", - "null" - ] - }, - "source_subcategory": { - "type": [ - "string", - "null" - ] - }, - "text": { - "description": "The vendor's text, verbatim but for HTML markup removed, untested by EchelonGraph; at most 2,000 characters (text_truncated, text_chars).", - "type": [ - "string", - "null" - ] - }, - "text_chars": { - "type": [ - "number", - "null" - ] - }, - "text_truncated": { - "type": [ - "boolean", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each remediation the vendor lists, with its kind, the vendor's own category." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_modified_at": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - }, - "withdrawn_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn_reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "known_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "references": {}, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation": { + "description": "The vendor's remediation as one text (the legacy field), beside remediations.", + "type": [ + "string", + "null" + ] + }, + "remediation_items_not_stored": { + "description": "Items past the 64 stored per advisory.", + "type": [ + "number", + "null" + ] + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "remediations": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVEs the item covers; [] for the whole advisory." + }, + "fixed_build": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "product_count": { + "type": [ + "number", + "null" + ] + }, + "product_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "source_category": { + "description": "The vendor's own name for the category.", + "type": [ + "string", + "null" + ] + }, + "source_subcategory": { + "type": [ + "string", + "null" + ] + }, + "text": { + "description": "The vendor's text, verbatim but for HTML markup removed, untested by EchelonGraph; at most 2,000 characters (text_truncated, text_chars).", + "type": [ + "string", + "null" + ] + }, + "text_chars": { + "type": [ + "number", + "null" + ] + }, + "text_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each remediation the vendor lists, with its kind, the vendor's own category." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_modified_at": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
kev_recent2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "catalog": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "catalog_count": { - "type": [ - "number", - "null" - ] - }, - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "feed_url": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "filters": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": {}, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev": { - "description": "Newest kev_added_date first; rows within one date are ordered by cve_id.", - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "eg_kev_tier": { - "type": [ - "number", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "type": [ - "string", - "null" - ] - }, - "kev_product": { - "type": [ - "string", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_vendor": { - "type": [ - "string", - "null" - ] - }, - "kev_vuln_name": { - "type": [ - "string", - "null" - ] - }, - "our_first_seen_kev": { - "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "kev_listed_total": { - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - }, - "notes": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "order": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "last_successful_fetch_at", - "catalog_version", - "date_released" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog": { + "const": "CISA KEV catalog", + "type": "string" + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "catalog": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "catalog_count": { + "type": [ + "number", + "null" + ] + }, + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "feed_url": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "filters": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev": { + "description": "Newest kev_added_date first; rows within one date are ordered by cve_id.", + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "eg_kev_tier": { + "type": [ + "number", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "type": [ + "string", + "null" + ] + }, + "kev_product": { + "type": [ + "string", + "null" + ] + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_vendor": { + "type": [ + "string", + "null" + ] + }, + "kev_vuln_name": { + "type": [ + "string", + "null" + ] + }, + "our_first_seen_kev": { + "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "kev_listed_total": { + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "next_cursor": { + "type": [ + "string", + "null" + ] + }, + "notes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "order": { + "type": [ + "string", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "last_successful_fetch_at", + "catalog_version", + "date_released" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog": { + "const": "CISA KEV catalog", + "type": "string" + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
scan_manifest2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls read more than once (the same package and version in two places) and sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "entries_pinned": { - "description": "Entries pinned to one version across the files, duplicates included.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files": { - "description": "Files passed.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_not_read": { - "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_read": { - "description": "Of those, the ones read.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_checked": { - "description": "Entries not sent (data.not_checked): not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_checked_by_reason": { - "additionalProperties": false, - "description": "not_checked, counted by reason.", - "properties": { - "local_path": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "unsupported_line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "vcs_source": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unpinned": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unresolved": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "object" - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "files", - "files_read", - "files_not_read", - "entries_pinned", - "duplicates_removed", - "not_checked", - "not_checked_by_reason", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "manifest": { - "additionalProperties": false, - "description": "Each file passed, in order, and how it was read. Filenames and contents are not sent to the API.", - "properties": { - "files": { - "items": { - "additionalProperties": false, - "properties": { - "ecosystem": { - "description": "The OSV ecosystem of the purls read from it.", - "type": [ - "string", - "null" - ] - }, - "filename": { - "type": "string" - }, - "format": { - "anyOf": [ - { - "enum": [ - "requirements.txt", - "go.mod", - "package-lock.json", - "Cargo.lock", - "Gemfile.lock", - "composer.lock", - "poetry.lock", - "gradle.lockfile" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The format the file was read as: set by format, or read from the filename; null when it was not read." - }, - "not_checked": { - "description": "Entries not sent, listed in data.not_checked: not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "notes": { - "description": "How this file was read where that limits what its verdicts cover (a go.mod below go 1.17).", - "items": { - "type": "string" - }, - "type": "array" - }, - "purls": { - "description": "Entries pinned to one version, read as purls (duplicates included).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "read": { - "description": "false: the file was refused or could not be read, and nothing in it is checked (not clean).", - "type": "boolean" - }, - "refused": { - "description": "Why the file was not read, and the file to pass instead where there is one; null when it was read.", - "type": [ - "string", - "null" - ] - }, - "replaced": { - "description": "go.mod replace directives applied: the module required, and the module and version checked instead.", - "items": { - "additionalProperties": false, - "properties": { - "from": { - "type": "string" - }, - "to": { - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "type": "array" - }, - "skipped": { - "description": "Entries that are not dependencies (a package-lock's root entry, the project itself).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "filename", - "format", - "ecosystem", - "read", - "refused", - "purls", - "not_checked", - "skipped", - "notes", - "replaced" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "files" - ], - "type": "object" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_checked": { - "description": "Each entry not sent to the API, with its file, line and reason: not checked, and not clean.", - "items": { - "additionalProperties": false, - "properties": { - "detail": { - "type": "string" - }, - "file": { - "type": "string" - }, - "line": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "1-based line; null in a JSON lockfile, whose entries spec names by key." - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "description": "version_unpinned: a range or wildcard, not one version; version_unresolved: no single registry version (none given, a branch, or an excluded go.mod version); local_path: a directory, file or workspace member; vcs_source: a VCS checkout; unsupported_line: a line or entry this tool does not read (another file named by -r or -c, a direct URL, another registry).", - "enum": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "string" - }, - "spec": { - "description": "What the file says for the entry: its line, or its lockfile key and version (at most 200 characters).", - "type": "string" - } - }, - "required": [ - "file", - "name", - "spec", - "reason", - "line", - "detail" - ], - "type": "object" - }, - "type": "array" - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matched_package": { - "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", - "type": [ - "string", - "null" - ] - }, - "matched_version_from": { - "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", - "type": [ - "string", - "null" - ] - }, - "matched_via": { - "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", - "type": [ - "number", - "null" - ] - }, - "fixed_in": { - "description": "The fixed bound of the advisory interval that holds this component's version, always above it. null when that interval records no fix (it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", - "type": [ - "string", - "null" - ] - }, - "fixed_in_reason": { - "description": "Why fixed_in is null; absent when fixed_in is a version.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "fixed": { - "type": [ - "string", - "null" - ] - }, - "introduced": { - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." - }, - "kev_listed": { - "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", - "type": [ - "boolean", - "null" - ] - }, - "match_reason": { - "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names the fixed version B, \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "purl_name": { - "description": "Upstream rows: the purl's own (binary) package name, not looked up.", - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "required": [ - "manifest", - "not_checked" - ], - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls read more than once (the same package and version in two places) and sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "entries_pinned": { - "description": "Entries pinned to one version across the files, duplicates included.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files": { - "description": "Files passed.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_not_read": { - "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "files_read": { - "description": "Of those, the ones read.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_checked": { - "description": "Entries not sent (data.not_checked): not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_checked_by_reason": { - "additionalProperties": false, - "description": "not_checked, counted by reason.", - "properties": { - "local_path": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "unsupported_line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "vcs_source": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unpinned": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "version_unresolved": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "version_unpinned", - "version_unresolved", - "local_path", - "vcs_source", - "unsupported_line" - ], - "type": "object" - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "files", - "files_read", - "files_not_read", - "entries_pinned", - "duplicates_removed", - "not_checked", - "not_checked_by_reason", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls read more than once (the same package and version in two places) and sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entries_pinned": { + "description": "Entries pinned to one version across the files, duplicates included.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files": { + "description": "Files passed.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_not_read": { + "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_read": { + "description": "Of those, the ones read.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_checked": { + "description": "Entries not sent (data.not_checked): not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_checked_by_reason": { + "additionalProperties": false, + "description": "not_checked, counted by reason.", + "properties": { + "local_path": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "unsupported_line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "vcs_source": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unpinned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unresolved": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "object" + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "files", + "files_read", + "files_not_read", + "entries_pinned", + "duplicates_removed", + "not_checked", + "not_checked_by_reason", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "manifest": { + "additionalProperties": false, + "description": "Each file passed, in order, and how it was read. Filenames and contents are not sent to the API.", + "properties": { + "files": { + "items": { + "additionalProperties": false, + "properties": { + "ecosystem": { + "description": "The OSV ecosystem of the purls read from it.", + "type": [ + "string", + "null" + ] + }, + "filename": { + "type": "string" + }, + "format": { + "anyOf": [ + { + "enum": [ + "requirements.txt", + "go.mod", + "package-lock.json", + "Cargo.lock", + "Gemfile.lock", + "composer.lock", + "poetry.lock", + "gradle.lockfile" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The format the file was read as: set by format, or read from the filename; null when it was not read." + }, + "not_checked": { + "description": "Entries not sent, listed in data.not_checked: not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "notes": { + "description": "How this file was read where that limits what its verdicts cover (a go.mod below go 1.17).", + "items": { + "type": "string" + }, + "type": "array" + }, + "purls": { + "description": "Entries pinned to one version, read as purls (duplicates included).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "read": { + "description": "false: the file was refused or could not be read, and nothing in it is checked (not clean).", + "type": "boolean" + }, + "refused": { + "description": "Why the file was not read, and the file to pass instead where there is one; null when it was read.", + "type": [ + "string", + "null" + ] + }, + "replaced": { + "description": "go.mod replace directives applied: the module required, and the module and version checked instead.", + "items": { + "additionalProperties": false, + "properties": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "type": "array" + }, + "skipped": { + "description": "Entries that are not dependencies (a package-lock's root entry, the project itself).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "filename", + "format", + "ecosystem", + "read", + "refused", + "purls", + "not_checked", + "skipped", + "notes", + "replaced" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "files" + ], + "type": "object" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_checked": { + "description": "Each entry not sent to the API, with its file, line and reason: not checked, and not clean.", + "items": { + "additionalProperties": false, + "properties": { + "detail": { + "type": "string" + }, + "file": { + "type": "string" + }, + "line": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "1-based line; null in a JSON lockfile, whose entries spec names by key." + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "description": "version_unpinned: a range or wildcard, not one version; version_unresolved: no single registry version (none given, a branch, or an excluded go.mod version); local_path: a directory, file or workspace member; vcs_source: a VCS checkout; unsupported_line: a line or entry this tool does not read (another file named by -r or -c, a direct URL, another registry).", + "enum": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "string" + }, + "spec": { + "description": "What the file says for the entry: its line, or its lockfile key and version (at most 200 characters).", + "type": "string" + } + }, + "required": [ + "file", + "name", + "spec", + "reason", + "line", + "detail" + ], + "type": "object" + }, + "type": "array" + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matched_package": { + "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", + "type": [ + "string", + "null" + ] + }, + "matched_version_from": { + "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", + "type": [ + "string", + "null" + ] + }, + "matched_via": { + "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "The lowest version above this component's that no affected interval of the CVE's record for the package holds, always above it: the fixed bound of the interval that holds the component's version, moved past any overlapping interval that still holds that bound (fixed_in_detail then names it). null when no such version is on record (an interval on the way records no fix: it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_detail": { + "description": "Set when fixed_in is not the fixed bound of the interval that holds the component's version: the overlapping intervals of the same record it moved past, which still hold that bound.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", + "type": [ + "boolean", + "null" + ] + }, + "match_reason": { + "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names that interval's fixed bound B (another interval of the advisory can still hold B; fixed_in is the version past them all), \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "purl_name": { + "description": "Upstream rows: the purl's own (binary) package name, not looked up.", + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "required": [ + "manifest", + "not_checked" + ], + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls read more than once (the same package and version in two places) and sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "entries_pinned": { + "description": "Entries pinned to one version across the files, duplicates included.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files": { + "description": "Files passed.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_not_read": { + "description": "The ones refused or unreadable: nothing in them is checked, and none is clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "files_read": { + "description": "Of those, the ones read.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_checked": { + "description": "Entries not sent (data.not_checked): not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_checked_by_reason": { + "additionalProperties": false, + "description": "not_checked, counted by reason.", + "properties": { + "local_path": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "unsupported_line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "vcs_source": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unpinned": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "version_unresolved": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "version_unpinned", + "version_unresolved", + "local_path", + "vcs_source", + "unsupported_line" + ], + "type": "object" + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "files", + "files_read", + "files_not_read", + "entries_pinned", + "duplicates_removed", + "not_checked", + "not_checked_by_reason", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_cves2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "The rows in this page.", - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_notes_urls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_required_action": { - "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 22-01, by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "kev_short_description": { - "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", - "type": [ - "string", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "release_reference", - "nvd_patch_reference", - "cna_patch_reference" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), nvd_patch_reference (an NVD reference tagged Patch) and cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": {}, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", - "type": [ - "string", - "null" - ] - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "description": "true: a search phrase was relaxed to all of its words.", - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "description": "false: the matches were not counted, so total is not a count.", - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "description": "true: there are at least total matches.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "The rows in this page.", - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cna": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "name": { + "type": [ + "string", + "null" + ] + }, + "short_name": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The CNA that wrote the CVE record: short_name as the record gives it, and name, the CVE Program's name for that CNA (the short name where its list does not hold it). Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field." + }, + "cna_solution": { + "description": "The sentence of the CVE record's solutions, written by its CNA, that names a released fix, verbatim: what makes cna_solution patch evidence. It is the CNA's text, not EchelonGraph's advice. Absent where the record's solutions name no fixed version, as well as where the field itself is: Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "date_public": { + "description": "When the vulnerability was made public, as the CVE record's CNA states it (the record's datePublic: \"if known, the date/time the vulnerability was disclosed publicly\"). It is the CNA's date, not the record's own publication date, which is published. Absent where EchelonGraph has not read the CVE record's CNA container yet, where the record has none, for a REJECTED CVE, and from an API older than the field.", + "type": [ + "string", + "null" + ] + }, + "date_public_source": { + "description": "Whose date date_public is: cna, the CVE record's CNA. Absent whenever date_public is.", + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "echelongraph_ssvc_decision": { + "description": "The SSVC decision (Act, Attend, Track* or Track) EchelonGraph computes with CISA's decision table at medium mission impact. CISA publishes the table and, for some CVEs, its inputs, not a decision for a CVE. score_factors.ssvc gives the decision at low, medium and high mission impact, with each input and its source.", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 26-04 (which replaced BOD 22-01 on 10 June 2026), by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "vendor_advisory_fix", + "nvd_patch_reference", + "cna_patch_reference", + "cna_solution", + "description_fix" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), vendor_advisory_fix (a vendor advisory that lists a fix for the CVE under the vendor's own structured category: Red Hat's CSAF vendor_fix, Microsoft's Vendor Fix), nvd_patch_reference (an NVD reference tagged Patch), cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record), cna_solution (a sentence of the CVE record's solutions, written by its CNA, that names a fixed version; relayed as cna_solution) and description_fix (a sentence of the CVE description that names a fixed version). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fix_status": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "basis": { + "type": [ + "string", + "null" + ] + }, + "described_by": { + "type": [ + "string", + "null" + ] + }, + "listed_in_patch_table": { + "type": [ + "boolean", + "null" + ] + }, + "solution_by": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cna": { + "type": [ + "string", + "null" + ] + }, + "statement": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "available", + "fix_referenced", + "fix_merged", + "none_confirmed", + "unknown" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "stated_in_record": { + "type": [ + "boolean", + "null" + ] + }, + "unread_inputs": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The API's fix-status rule for the CVE, the one CVE Pulse pages show: state is available (a fix is on record), fix_referenced (a reference tagged Patch, often a source commit, and no release confirmed), fix_merged (an upstream fix merged, not yet in a tagged release), none_confirmed (no fix evidence on record, which is not a finding that no fix exists) or unknown (an input could not be read). basis is the step of the rule that decided it; described_by is the CVE description's sentence naming the fix, solution_by the CVE record's solution sentence naming it (statement) and the CNA that wrote it (cna), stated_in_record that patch_evidence counts a fix the CVE record states with no sentence to quote, listed_in_patch_table that a fixed version or patch row is on record; unread_inputs names any input the API could not read." + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: fix_status first (the API's fix-status rule: state, basis, described_by, solution_by, stated_in_record, listed_in_patch_table and unread_inputs), vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation by NVD, or patch or mitigation by the CNA), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_factors": { + "description": "EchelonGraph's evidence for its score. ssvc: the SSVC decision at every mission impact level, each input with its source. bod_26_04 (scorer v3.4 and later): CISA BOD 26-04's remediation timeline, if_publicly_exposed and if_not_publicly_exposed, each a list of CERT/CC's keys (3DF, 3D, 14D, 60D, FSU) named in timelines, with kev, automatable and technical_impact, each with its source; source cisa_bod_26_04_default is CISA's own default for a CVE not in KEV that nobody has assessed." + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "description": "true: a search phrase was relaxed to all of its words.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "description": "false: the matches were not counted, so total is not a count.", + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "description": "true: there are at least total matches.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_vendor_advisories2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "description": "Whether a free-text search filtered this answer.", - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, vendor_advisory_id, affected_products and cve_ids (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word): it must equal, ignoring case, a whole word (a run of letters and digits) of one of those, so xz finds xz-utils but not xzibit, and a 1- or 2-character query with any other character, such as c#, matches nothing.", - "type": [ - "string", - "null" - ] - }, - "total": { - "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000; paging past it still works. Without a query, total is the exact count and total_capped is false.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "description": "Whether a free-text search filtered this answer.", + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, vendor_advisory_id, affected_products and cve_ids (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word): it must equal, ignoring case, a whole word (a run of letters and digits) of one of those, so xz finds xz-utils but not xzibit, and a 1- or 2-character query with any other character, such as c#, matches nothing.", + "type": [ + "string", + "null" + ] + }, + "total": { + "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000; paging past it still works. Without a query, total is the exact count and total_capped is false.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
vendor_advisories_for_cve2 fields changed- added
Input schema / properties / fullAdded value: +{ + "description": "true: data in the structured result is the answer whole, however long. Without it, a structured result past 30,000 characters of JSON has its data cut (DATA CUT): in an order the note states, the entries of its longest lists keep only some of their fields, and then the lists only some of their entries; data_truncated is true, and truncated gives each list cut with its total, the number returned and whether its entries are thinned. Whole data is for a program; a client that sizes structured results, as Claude Code does against MAX_MCP_OUTPUT_TOKENS, can refuse an answer past its cap.", + "type": "boolean" +} - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "rejected_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." - }, - "remediation_kinds": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_fix", - "workaround", - "mitigation", - "no_fix_planned", - "none_available", - "other" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." - }, - "remediation_state": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "parsed", - "none_in_source", - "not_parsed", - "withdrawn" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cve_rejected": { - "description": "true: the CVE record of cve_id was rejected (withdrawn) by its numbering authority, so these advisories name a rejected record, not an active vulnerability; null when that could not be checked.", - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cve_rejected": { + "description": "true: the CVE record of cve_id was rejected (withdrawn) by its numbering authority, so these advisories name a rejected record, not an active vulnerability; null when that could not be checked.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "data_truncated": { + "description": "false: data is the answer whole. true: the structured result would pass 30,000 characters of JSON with data whole, so data is cut (DATA CUT): the entries of some of its lists keep only some of their fields, or the lists only some of their entries, truncated gives each, and no string is shortened. The same call with full: true returns data whole.", + "type": "boolean" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + }, + "truncated": { + "additionalProperties": { + "additionalProperties": false, + "properties": { + "returned": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "thinned": { + "const": true, + "type": "boolean" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "returned" + ], + "type": "object" + }, + "description": "Present when data_truncated is true: each list of data that was cut, by its path in data (a dot between the names of an object and a list inside it), with total, its entries in the answer, returned, the entries data holds, and thinned, true when each of them keeps only some of its fields.", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data_truncated", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
1 tool update
- Changed
cve_intel1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "affected_packages": { - "items": { - "additionalProperties": {}, - "properties": { - "dependents_count": { - "type": [ - "number", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_branches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - }, - "fixed": { - "description": "The range's fix: the first version past it. null where no fix is on record.", - "type": [ - "string", - "null" - ] - }, - "introduced": { - "description": "The range's lower bound, inclusive; \"0\" is the first version.", - "type": [ - "string", - "null" - ] - }, - "last_affected": { - "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", - "type": [ - "string", - "null" - ] - }, - "source": { - "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; that range's fixed is the fix for it, and a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." - }, - "fixed_version": { - "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "version_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cve_id": { - "type": "string" - }, - "cwes": { - "items": { - "additionalProperties": {}, - "properties": { - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits": { - "items": { - "additionalProperties": {}, - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "first_seen_at": { - "type": [ - "string", - "null" - ] - }, - "kind": { - "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", - "type": [ - "string", - "null" - ] - }, - "source_name": { - "type": [ - "string", - "null" - ] - }, - "source_url": { - "type": [ - "string", - "null" - ] - }, - "verified_status": { - "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits_by_kind": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_by_status": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_capped": { - "description": "true: exploits lists fewer references than exploits_total.", - "type": "boolean" - }, - "exploits_total": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Every exploit reference on record for the CVE, not only those listed in exploits." - }, - "fixed_versions": { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_version": { - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "vulnerable_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline": { - "items": { - "additionalProperties": {}, - "properties": { - "enriched_at": { - "type": [ - "string", - "null" - ] - }, - "enrichment_kind": { - "type": [ - "string", - "null" - ] - }, - "fields_changed": {}, - "score_delta": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline_count_30d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_count_7d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_total": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "cve_id" - ], - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "properties": { + "affected_packages": { + "items": { + "additionalProperties": {}, + "properties": { + "dependents_count": { + "type": [ + "number", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + }, + "fixed": { + "description": "The range's fix: the first version past it. null where no fix is on record.", + "type": [ + "string", + "null" + ] + }, + "introduced": { + "description": "The range's lower bound, inclusive; \"0\" is the first version.", + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; that range's fixed is the fix for it, and a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "version_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cve_id": { + "type": "string" + }, + "cwes": { + "items": { + "additionalProperties": {}, + "properties": { + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits": { + "items": { + "additionalProperties": {}, + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "eg_first_seen_at": { + "description": "When EchelonGraph first recorded the reference, as a UTC timestamp: a date of EchelonGraph's, not the source's.", + "type": "string" + }, + "first_seen_at": { + "description": "Deprecated: the same value as source_published_at, null when that is.", + "type": [ + "string", + "null" + ] + }, + "kind": { + "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", + "type": [ + "string", + "null" + ] + }, + "source_name": { + "type": [ + "string", + "null" + ] + }, + "source_published_at": { + "description": "The source's own date for the reference (Exploit-DB's date_published, a GitHub proof-of-concept repository's created_at, or the first commit of a nuclei template or Metasploit module where EchelonGraph derived it from the source's git history); null where the source gives none, and EchelonGraph supplies no stand-in date.", + "type": [ + "string", + "null" + ] + }, + "source_url": { + "type": [ + "string", + "null" + ] + }, + "verified_status": { + "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits_by_kind": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_by_status": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_capped": { + "description": "true: exploits lists fewer references than exploits_total.", + "type": "boolean" + }, + "exploits_total": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Every exploit reference on record for the CVE, not only those listed in exploits." + }, + "fixed_versions": { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_version": { + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "vulnerable_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline": { + "items": { + "additionalProperties": {}, + "properties": { + "enriched_at": { + "type": [ + "string", + "null" + ] + }, + "enrichment_kind": { + "type": [ + "string", + "null" + ] + }, + "fields_changed": {}, + "score_delta": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline_count_30d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_count_7d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "cve_id" + ], + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
14 tool updates
- Changed
check_affected1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", - "type": [ - "boolean", - "null" - ] - }, - "candidate_count": { - "type": [ - "number", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "ecosystem_recognised": { - "type": [ - "boolean", - "null" - ] - }, - "excluded": {}, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_vendor": { - "description": "The vendor NVD's CPE asserts for this match.", - "type": [ - "string", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "effective_score": { - "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", - "type": [ - "number", - "null" - ] - }, - "effective_severity": { - "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "EPSS exploitation probability, 0 to 1.", - "type": [ - "number", - "null" - ] - }, - "kev_listed": { - "description": "Listed in CISA-KEV: known to be exploited.", - "type": [ - "boolean", - "null" - ] - }, - "match_confidence": { - "type": [ - "number", - "null" - ] - }, - "match_method": { - "type": [ - "string", - "null" - ] - }, - "match_reason": { - "type": [ - "string", - "null" - ] - }, - "matched_criteria": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "description": "CISA-KEV records known use in ransomware campaigns.", - "type": [ - "boolean", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", - "type": [ - "boolean", - "null" - ] - }, - "score_unassessed_reason": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", - "type": [ - "string", - "null" - ] - }, - "vendor_severity": { - "type": [ - "string", - "null" - ] - }, - "vendor_unknown": { - "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", - "type": [ - "boolean", - "null" - ] - }, - "version_evidence": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - }, - "product_named_count": { - "type": [ - "number", - "null" - ] - }, - "undecidable_excluded_count": { - "type": [ - "number", - "null" - ] - }, - "undecided_candidate_count": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "detail": { - "type": [ - "string", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_count": { - "type": [ - "number", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", + "type": [ + "boolean", + "null" + ] + }, + "candidate_count": { + "type": [ + "number", + "null" + ] + }, + "candidates_capped": { + "description": "true: not every candidate CVE was loaded.", + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "description": "true: the match list stopped at its cap.", + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "degraded": { + "description": "true: the lookup ran out of time.", + "type": [ + "boolean", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "excluded": {}, + "excluded_count": { + "description": "CPE candidates suppressed by the vendor or platform gate.", + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "description": "Which lookup path answered.", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cpe_vendor": { + "description": "The vendor NVD's CPE asserts for this match.", + "type": [ + "string", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "effective_score": { + "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", + "type": [ + "number", + "null" + ] + }, + "effective_severity": { + "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "EPSS exploitation probability, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "Registry match: the fixed bound of the advisory interval that holds this version, always above it. null when that interval records no fix (it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which. Absent on a CPE match.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Registry match: the advisory interval that holds this version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Listed in CISA-KEV: known to be exploited.", + "type": [ + "boolean", + "null" + ] + }, + "match_confidence": { + "type": [ + "number", + "null" + ] + }, + "match_method": { + "type": [ + "string", + "null" + ] + }, + "match_reason": { + "type": [ + "string", + "null" + ] + }, + "matched_criteria": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "description": "CISA-KEV records known use in ransomware campaigns.", + "type": [ + "boolean", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", + "type": [ + "boolean", + "null" + ] + }, + "score_unassessed_reason": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", + "type": [ + "string", + "null" + ] + }, + "vendor_severity": { + "type": [ + "string", + "null" + ] + }, + "vendor_unknown": { + "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", + "type": [ + "boolean", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "description": "Advisories decided as not affecting this version.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + }, + "product_named_count": { + "type": [ + "number", + "null" + ] + }, + "undecidable_excluded_count": { + "type": [ + "number", + "null" + ] + }, + "undecided_candidate_count": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "detail": { + "type": [ + "string", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_count": { + "type": [ + "number", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
check_sbom1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matched_package": { + "description": "The package name the advisories were looked up by (#2836): the purl's own name, or, for a deb or apk purl with an upstream qualifier, the source package it names, which is how Debian and Alpine file advisories.", + "type": [ + "string", + "null" + ] + }, + "matched_version_from": { + "description": "Upstream rows: upstream when the qualifier named a version (upstream=name@version) and it was used, purl when the purl's own version was.", + "type": [ + "string", + "null" + ] + }, + "matched_via": { + "description": "Which name matched_package is: purl_name (the purl's name), upstream (the purl's upstream qualifier) or coordinates (the component's package).", + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "The CVE's EPSS score (FIRST), as EchelonGraph's record holds it; null when it has none.", + "type": [ + "number", + "null" + ] + }, + "fixed_in": { + "description": "The fixed bound of the advisory interval that holds this component's version, always above it. null when that interval records no fix (it ends at last_affected, or has no end) or no interval holds the version, with fixed_in_reason saying which.", + "type": [ + "string", + "null" + ] + }, + "fixed_in_reason": { + "description": "Why fixed_in is null; absent when fixed_in is a version.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "fixed": { + "type": [ + "string", + "null" + ] + }, + "introduced": { + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The advisory interval that holds this component's version (fixed is exclusive, last_affected inclusive); absent when no interval holds it." + }, + "kev_listed": { + "description": "Whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, as EchelonGraph's record holds it.", + "type": [ + "boolean", + "null" + ] + }, + "match_reason": { + "description": "Why the advisory applies, with the advisory interval the version falls inside: \"[A, B)\" names the fixed version B, \"[A, B]\" the last affected version B. On an upstream row it ends by naming the source package and the purl name.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "purl_name": { + "description": "Upstream rows: the purl's own (binary) package name, not looked up.", + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
cve_exposure1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "countries": { - "type": [ - "number", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "exposed_hosts": { - "type": [ - "number", - "null" - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev_catalog_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_seen_in_observations": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "type": [ - "string", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "top_countries": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "country": { - "type": [ - "string", - "null" - ] - }, - "hosts": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "top_products": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "hosts": { - "type": [ - "number", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "tracked": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "exposure_state": { - "anyOf": [ - { - "enum": [ - "exposed", - "measured_zero", - "not_assessed", - "tracking_unknown" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "exposure_state", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "in_scope": { - "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "in_scope" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "countries": { + "type": [ + "number", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "exposed_hosts": { + "type": [ + "number", + "null" + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev_catalog_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_seen_in_observations": { + "type": [ + "boolean", + "null" + ] + }, + "last_seen": { + "description": "When EchelonGraph last wrote or refreshed a service's row, not when the service was observed and not when its vulnerable version was last confirmed: it is set to the time of the write when a search matches the banner, and again when a re-check finds the port still listed by Shodan InternetDB, without re-reading the banner, so a patched service can stay counted while its port stays open. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "type": [ + "string", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "top_countries": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "country": { + "type": [ + "string", + "null" + ] + }, + "hosts": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "top_products": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "hosts": { + "type": [ + "number", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "tracked": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "exposure_state": { + "anyOf": [ + { + "enum": [ + "exposed", + "measured_zero", + "not_assessed", + "tracking_unknown" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "What the answer's count is, as the note's (exposure_state: …) tag says; not state, which says whether the answer is a dated measurement. exposed: data.exposed_hosts counts the services the radar holds on record for the CVE, above 0. measured_zero: the API marks the CVE as tracked with 0 services, a zero in the radar's sample. not_assessed: the CVE is outside the radar's tracked set, so its count, if any, is not a current measurement. tracking_unknown: the API does not say whether the radar tracks the CVE, so its 0 is not evidence either way. null: the answer carries no count." + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "exposure_state", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "in_scope": { + "description": "The API's tracked verdict: whether the CVE is in the radar's tracked set; null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "in_scope" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Added
cve_remediation - Changed
cve_summary1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "poller": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cves_ingested": { - "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", - "type": [ - "number", - "null" - ] - }, - "cves_skipped": { - "description": "CVE records this instance's NVD poller skipped since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "http_retries": { - "description": "HTTP retries this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "interval": { - "description": "How often this instance's NVD poller polls.", - "type": [ - "string", - "null" - ] - }, - "last_poll_at": { - "description": "When this instance's NVD poller last polled: never the feed's freshness.", - "type": [ - "string", - "null" - ] - }, - "last_poll_dur_ms": { - "description": "How long that poll took, in milliseconds.", - "type": [ - "number", - "null" - ] - }, - "poll_count": { - "description": "Polls this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "poll_errors": { - "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." - }, - "summary": { - "additionalProperties": {}, - "properties": { - "critical": { - "type": [ - "number", - "null" - ] - }, - "high": { - "type": [ - "number", - "null" - ] - }, - "last_updated": { - "type": [ - "string", - "null" - ] - }, - "low": { - "type": [ - "number", - "null" - ] - }, - "medium": { - "type": [ - "number", - "null" - ] - }, - "none": { - "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", - "type": [ - "number", - "null" - ] - }, - "nvd_critical": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_high": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_low": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_medium": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_none": { - "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", - "type": [ - "number", - "null" - ] - }, - "rejected": { - "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "unscored": { - "description": "The same count as none, under its own name.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "poller": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cves_ingested": { + "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", + "type": [ + "number", + "null" + ] + }, + "cves_skipped": { + "description": "CVE records this instance's NVD poller skipped since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "http_retries": { + "description": "HTTP retries this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "interval": { + "description": "How often this instance's NVD poller polls.", + "type": [ + "string", + "null" + ] + }, + "last_poll_at": { + "description": "When this instance's NVD poller last polled: never the feed's freshness.", + "type": [ + "string", + "null" + ] + }, + "last_poll_dur_ms": { + "description": "How long that poll took, in milliseconds.", + "type": [ + "number", + "null" + ] + }, + "poll_count": { + "description": "Polls this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "poll_errors": { + "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." + }, + "summary": { + "additionalProperties": {}, + "description": "summary.nvd_critical, summary.nvd_high, summary.nvd_medium, summary.nvd_low and summary.nvd_none count the same active CVEs as summary.total by NVD's CVSS severity label (v3.x, else v4.0; before NVD's record arrives, or where it gives none, a pre-NVD label from the CVE.org record or a GitHub advisory can stand in): provenance, never EchelonGraph's severity band. summary.nvd_none counts the active CVEs with no Critical, High, Medium or Low label there, CVEs NVD never labelled under CVSS v3 among them, and many of those carry an NVD CVSS v2 score instead: it is neither a count of CVEs rated None nor the count of CVEs with no severity, which is summary.none. Whenever summary.nvd_none is above zero the note says what it counts, with its count.", + "properties": { + "critical": { + "type": [ + "number", + "null" + ] + }, + "high": { + "type": [ + "number", + "null" + ] + }, + "last_updated": { + "type": [ + "string", + "null" + ] + }, + "low": { + "type": [ + "number", + "null" + ] + }, + "medium": { + "type": [ + "number", + "null" + ] + }, + "none": { + "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", + "type": [ + "number", + "null" + ] + }, + "nvd_critical": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_high": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_low": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_medium": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_none": { + "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", + "type": [ + "number", + "null" + ] + }, + "rejected": { + "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "unscored": { + "description": "The same count as none, under its own name.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
epss_history1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_truncated": { - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "points", - "points_truncated" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "current": { - "additionalProperties": {}, - "properties": { - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The record's EPSS probability now; null when it holds none.", - "type": [ - "number", - "null" - ] - }, - "epss_updated_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." - } - }, - "type": "object" - }, - "cve_id": { - "type": "string" - }, - "history_rows": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Raw history rows read, before repeated records of one change were collapsed." - }, - "latest_point_matches_current": { - "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", - "type": [ - "boolean", - "null" - ] - }, - "points": { - "description": "Recorded changes, oldest first. Never a daily series.", - "items": { - "additionalProperties": {}, - "properties": { - "at": { - "description": "When EchelonGraph recorded this change.", - "type": "string" - }, - "epss_percentile": { - "description": "Its percentile (0 to 1), null where the record held none.", - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "description": "The EPSS probability (0 to 1) from that change on.", - "type": "number" - } - }, - "required": [ - "at", - "epss_score" - ], - "type": "object" - }, - "type": "array" - }, - "points_truncated": { - "description": "True when only the newest rows were read, so the earliest points are missing.", - "type": [ - "boolean", - "null" - ] - }, - "series_kind": { - "description": "Always change_only: one point per recorded change, none for a day without one.", - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." - } - }, - "required": [ - "cve_id", - "series_kind", - "series_starts_at", - "current", - "points" - ], - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "points": { - "description": "How many points the series holds.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "points_truncated": { - "type": "boolean" - }, - "series_kind": { - "enum": [ - "change_only" - ], - "type": "string" - }, - "series_starts_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "series_kind", - "series_starts_at", - "points", - "points_truncated" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when the record holds every change a refresh applied. Between series_starts_at and complete_since changes are missing, so a missing point there does not mean unchanged. Absent from an API older than #2867." + }, + "coverage": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From here on every change a refresh applied is a point; before it changes are missing." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that a refresh applied completely." + }, + "days_missing": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day that no refresh applied." + }, + "days_partial": { + "anyOf": [ + { + "items": { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Score dates whose refreshes all failed part-way: some CVEs hold that day, some do not." + }, + "first_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest score date in the run log." + }, + "last_day": { + "anyOf": [ + { + "description": "A FIRST score date, YYYY-MM-DD.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The latest score date in the run log." + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "This CVE's points in the part of the record that misses changes." + }, + "recorded_from": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "series_starts_at: when recording began." + }, + "refresh_runs_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "run_log_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The first logged refresh: score dates before it are not listed, held or missing." + }, + "runs_undated": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "series_complete": { + "description": "True only when nothing in the record predates complete_since.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Which part of the record is complete and which FIRST score dates it holds." + }, + "current": { + "additionalProperties": {}, + "properties": { + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The record's EPSS probability now; null when it holds none.", + "type": [ + "number", + "null" + ] + }, + "epss_updated_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When EchelonGraph last wrote a changed EPSS value for this CVE." + } + }, + "type": "object" + }, + "cve_id": { + "type": "string" + }, + "history_rows": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Raw history rows read, before repeated records of one change were collapsed." + }, + "latest_point_matches_current": { + "description": "Whether the newest point equals current; false means a change is missing from the series; null when there is no point or no current value.", + "type": [ + "boolean", + "null" + ] + }, + "points": { + "description": "Recorded changes, oldest first. Never a daily series.", + "items": { + "additionalProperties": {}, + "properties": { + "at": { + "description": "When EchelonGraph recorded this change.", + "type": "string" + }, + "epss_percentile": { + "description": "Its percentile (0 to 1), null where the record held none.", + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "description": "The EPSS probability (0 to 1) from that change on.", + "type": "number" + }, + "score_date": { + "description": "FIRST's score date (YYYY-MM-DD) of the logged refresh that wrote this point; null where no logged refresh covers it.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "at", + "epss_score" + ], + "type": "object" + }, + "type": "array" + }, + "points_truncated": { + "description": "True when only the newest rows were read, so the earliest points are missing.", + "type": [ + "boolean", + "null" + ] + }, + "series_kind": { + "description": "Always change_only: one point per recorded change, none for a day without one.", + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The earliest EPSS change EchelonGraph recorded for any CVE: when recording began. Null when nothing has been recorded." + } + }, + "required": [ + "cve_id", + "series_kind", + "series_starts_at", + "current", + "points" + ], + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "complete_since": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "From when every change is a point; null when the API did not say, and then no part of the series is known complete." + }, + "days_held": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Score dates from first_day to last_day the record holds; null when none are listed." + }, + "days_missing": { + "description": "Score dates from first_day to last_day the record does not hold.", + "items": { + "type": "string" + }, + "type": "array" + }, + "days_partial": { + "description": "Score dates held for some CVEs only.", + "items": { + "type": "string" + }, + "type": "array" + }, + "first_day": { + "description": "The earliest FIRST score date the run log lists; null when it lists none.", + "type": [ + "string", + "null" + ] + }, + "last_day": { + "type": [ + "string", + "null" + ] + }, + "points": { + "description": "How many points the series holds.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "points_before_complete_since": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "How many of them fall where changes are missing; null when the API did not say." + }, + "points_truncated": { + "type": "boolean" + }, + "series_complete": { + "description": "True only when the API says nothing in the record predates complete_since.", + "type": "boolean" + }, + "series_kind": { + "enum": [ + "change_only" + ], + "type": "string" + }, + "series_starts_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "series_kind", + "series_starts_at", + "complete_since", + "series_complete", + "points", + "points_before_complete_since", + "points_truncated", + "first_day", + "last_day", + "days_held", + "days_partial", + "days_missing" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
exposure_radar1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "distinct_hosts": { - "type": "number" - }, - "engines": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "pci_likely": { - "type": "number" - }, - "pii_likely": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_engines": { - "items": { - "additionalProperties": false, - "properties": { - "engine": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "engine", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "correlations": { - "type": "number" - }, - "distinct_hosts": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "kev_cves_exposed": { - "type": "number" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "newest_kev": { - "items": { - "additionalProperties": false, - "properties": { - "added_date": { - "type": "string" - }, - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "exposed_hosts": { - "type": "number" - }, - "exposure_state": { - "enum": [ - "exposed", - "measured_zero", - "not_assessed" - ], - "type": "string" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - }, - "vuln_name": { - "type": "string" - } - }, - "required": [ - "cve_id", - "exposure_state" - ], - "type": "object" - }, - "type": "array" - }, - "ransomware_cves": { - "type": "number" - }, - "ransomware_hosts": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_cves": { - "items": { - "additionalProperties": false, - "properties": { - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "hosts": { - "type": "number" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - } - }, - "required": [ - "cve_id", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "hosts": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "trend": { - "items": { - "additionalProperties": false, - "properties": { - "new_exposures": { - "type": "number" - }, - "week": { - "type": "string" - } - }, - "required": [ - "week", - "new_exposures" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "distinct_repos": { - "type": "number" - }, - "distinct_secrets": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_providers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "provider": { - "type": "string" - } - }, - "required": [ - "provider", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_types": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "secret_type": { - "type": "string" - } - }, - "required": [ - "secret_type", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "counted_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "era": { - "additionalProperties": false, - "properties": { - "dual": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "legacy": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "modern": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "legacy", - "dual", - "modern", - "unknown", - "not_measured" - ], - "type": "object" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "not_assessed": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_assessed_by_reason": { - "additionalProperties": false, - "properties": { - "bare_challenge_no_prm": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "challenge_unadjudicated": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "cross_origin_pointer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "identified_no_challenge": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "metadata_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_authorization_servers": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_http_answer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_identified_as_mcp": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "resource_mismatch": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "identified_no_challenge", - "resource_mismatch", - "cross_origin_pointer", - "bare_challenge_no_prm", - "pointer_unreachable", - "pointer_invalid", - "no_authorization_servers", - "wellknown_unreachable", - "metadata_invalid", - "challenge_unadjudicated", - "no_http_answer", - "not_identified_as_mcp" - ], - "type": "object" - }, - "own_controls_excluded": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pending_readjudication": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "prm_via": { - "additionalProperties": false, - "properties": { - "header": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_path": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_root": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "header", - "wellknown_path", - "wellknown_root" - ], - "type": "object" - }, - "protected": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "transport": { - "additionalProperties": false, - "properties": { - "legacy_sse": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "streamable_http": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "streamable_http", - "legacy_sse", - "unknown", - "not_measured" - ], - "type": "object" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "withheld_opted_out": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "total", - "protected", - "pending_readjudication", - "not_assessed" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "authentication": { - "additionalProperties": false, - "properties": { - "not_determined": { - "type": "number" - }, - "observed": { - "type": "number" - } - }, - "type": "object" - }, - "confirmed_exposed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "observed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "last_observation": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "country": { - "type": "string" - } - }, - "required": [ - "country", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_issuers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "issuer": { - "type": "string" - } - }, - "required": [ - "issuer", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "trend_30d": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "date": { - "type": "string" - } - }, - "required": [ - "date", - "count" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "poller": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "running": { - "type": "boolean" - } - }, - "required": [ - "running", - "last_run_at" - ], - "type": "object" - } - }, - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at", - "enabled" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - }, - "running": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "last_run_at", - "running" - ], - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "radars": { - "description": "Each radar that could not be read, and why.", - "items": { - "additionalProperties": false, - "properties": { - "kind": { - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "unexpected_shape" - ], - "type": "string" - }, - "message": { - "type": "string" - }, - "path": { - "type": "string" - }, - "radar": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "radar", - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "type": "array" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "description": "A field this version cannot label is left out of data and named in the note. Each of the kev_exposure, exposed_databases and leaked_credentials radars also carries generated_at, when the API computed its totals, and, when the API can tell, last_run_at. kev_exposure.last_run_at, exposed_databases.last_run_at and leaked_credentials.last_run_at are timestamps, not counts: each is when that radar last completed a check, a cycle whose reads succeeded, among them a Shodan search (for exposed_databases, or its LeakIX fallback) that answered at least one query, or for leaked_credentials a read of the public GitHub event stream. A cycle that read nothing does not move it, and it is not the time of every record a radar's numbers count, which cover everything still on record, not only what the last check found. A radar whose answer carries no last_run_at has none in the result, and the note says nothing about it. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "exposed_databases": { + "additionalProperties": false, + "description": "exposed_databases: exposed_databases.distinct_hosts counts distinct ip:port services the check confirmed answering without authentication, and exposed_databases.engines the distinct engine types among them; exposed_databases.top_engines and exposed_databases.top_countries rank up to 15 engines and 10 countries by those services. exposed_databases.pii_likely and exposed_databases.pci_likely count services whose schema names (never record values) pass a high-confidence, precision-first gate for personal or payment-card data, so a service outside them is not shown to hold no such data. exposed_databases.window.from and exposed_databases.window.to are timestamps, not counts: when EchelonGraph's check last confirmed the oldest and the newest of the services counted, a span of checks made at different times; with a counted service that has no such time on record there is no window.", + "properties": { + "distinct_hosts": { + "type": "number" + }, + "engines": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "pci_likely": { + "type": "number" + }, + "pii_likely": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_engines": { + "items": { + "additionalProperties": false, + "properties": { + "engine": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "engine", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "description": "kev_exposure: kev_exposure.distinct_hosts counts distinct ip:port services, not machines (a machine answering on two ports counts twice), with at least one CISA-KEV-listed CVE on record, and kev_exposure.ransomware_hosts those with a ransomware-linked one; kev_exposure.kev_cves_exposed and kev_exposure.ransomware_cves count distinct CVEs with at least one such service; kev_exposure.correlations counts service×CVE pairs, not services, so a service with three KEV CVEs counts three times. kev_exposure.top_products, kev_exposure.top_countries and kev_exposure.top_cves rank up to 12 products, 10 countries and 12 CVEs by those services; kev_exposure.top_cves[].cvss_v3_score and kev_exposure.top_cves[].epss_score are the highest CVSS v3 base score and EPSS probability recorded on that CVE's observations. kev_exposure.trend counts service×CVE pairs still on record by the week in which each was first recorded, over 12 weeks, so earlier weeks read low. kev_exposure.newest_kev lists the 15 CVEs that EchelonGraph's CVE records most recently mark as CISA-KEV-listed, each with an exposure_state: exposed, where kev_exposure.newest_kev[].exposed_hosts counts distinct ip:port services on record with it; or not_assessed, where the API's answer holds no measurement for that CVE (its 0 is not one) and no count is relayed, and this answer does not say whether the radar tracks that CVE: tracking is answered per CVE. kev_exposure.newest_kev[].cvss_v3_score and kev_exposure.newest_kev[].epss_score are the CVE record's CVSS v3 base score and EPSS probability. kev_exposure.window.from and kev_exposure.window.to are timestamps, not counts: when Shodan collected the banners of the oldest and the newest of the service×CVE pairs counted, a span of observations made at different times; with a counted pair that has no such time on record there is no window. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "correlations": { + "type": "number" + }, + "distinct_hosts": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "kev_cves_exposed": { + "type": "number" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "newest_kev": { + "items": { + "additionalProperties": false, + "properties": { + "added_date": { + "type": "string" + }, + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "exposed_hosts": { + "type": "number" + }, + "exposure_state": { + "enum": [ + "exposed", + "measured_zero", + "not_assessed" + ], + "type": "string" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "vuln_name": { + "type": "string" + } + }, + "required": [ + "cve_id", + "exposure_state" + ], + "type": "object" + }, + "type": "array" + }, + "ransomware_cves": { + "type": "number" + }, + "ransomware_hosts": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_cves": { + "items": { + "additionalProperties": false, + "properties": { + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "hosts": { + "type": "number" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + }, + "required": [ + "cve_id", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "hosts": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "trend": { + "items": { + "additionalProperties": false, + "properties": { + "new_exposures": { + "type": "number" + }, + "week": { + "type": "string" + } + }, + "required": [ + "week", + "new_exposures" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "description": "leaked_credentials: leaked_credentials.total counts (repository, secret) pairs, not distinct secrets, so one secret in three repositories counts three times; leaked_credentials.distinct_secrets counts each secret once and leaked_credentials.distinct_repos counts repositories; leaked_credentials.top_providers and leaked_credentials.top_types rank up to 15 providers and secret types by those pairs. None is validated: each is a credential-shaped string that passed EchelonGraph's filters, at most structurally checked and never tested against its provider. leaked_credentials.window.from and leaked_credentials.window.to are timestamps, not counts: when EchelonGraph's detector last found the oldest and the newest of the pairs counted.", + "properties": { + "distinct_repos": { + "type": "number" + }, + "distinct_secrets": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_providers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "provider": { + "type": "string" + } + }, + "required": [ + "provider", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_types": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "secret_type": { + "type": "string" + } + }, + "required": [ + "secret_type", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "description": "mcp_servers: counts and timestamps only, no hostname. mcp_servers.total counts hostnames the AI-exposure radar has checked for an MCP server, each once by its latest verdict on record, and not every one is an MCP server; EchelonGraph's own control servers are left out, and mcp_servers.own_controls_excluded counts them; hostnames whose owner opted out of scanning are not checked again while the opt-out stands, so their last verdict is left out too, and mcp_servers.withheld_opted_out counts them. mcp_servers.total is mcp_servers.protected plus mcp_servers.pending_readjudication plus mcp_servers.not_assessed. mcp_servers.protected counts hostnames whose /mcp endpoint asked for credentials and whose OAuth protected-resource metadata validated under RFC 9728; mcp_servers.prm_via divides them by where that document was found: mcp_servers.prm_via.header, mcp_servers.prm_via.wellknown_path and mcp_servers.prm_via.wellknown_root. mcp_servers.pending_readjudication counts verdicts of a rule since replaced, not yet re-checked. mcp_servers.not_assessed counts the rest, whose protection the radar could not assess (not assessed does not mean unprotected), and mcp_servers.not_assessed_by_reason puts each in one bucket. mcp_servers.not_assessed_by_reason.identified_no_challenge holds servers that identified themselves as MCP servers and did not ask for credentials at the handshake. That is normal in MCP: authorization is optional in the spec, and a server can enforce it at tools/call instead, which EchelonGraph never sends, so this bucket is not a finding of exposure. mcp_servers.not_assessed_by_reason.resource_mismatch, mcp_servers.not_assessed_by_reason.cross_origin_pointer, mcp_servers.not_assessed_by_reason.bare_challenge_no_prm, mcp_servers.not_assessed_by_reason.pointer_unreachable, mcp_servers.not_assessed_by_reason.pointer_invalid, mcp_servers.not_assessed_by_reason.no_authorization_servers, mcp_servers.not_assessed_by_reason.wellknown_unreachable and mcp_servers.not_assessed_by_reason.metadata_invalid hold endpoints that asked for credentials but whose RFC 9728 metadata did not validate, by why, so none of them is shown to lack protection; mcp_servers.not_assessed_by_reason.challenge_unadjudicated holds endpoints that asked for credentials before that check existed, not yet re-checked. mcp_servers.not_assessed_by_reason.no_http_answer holds hostnames that gave no HTTP answer, and mcp_servers.not_assessed_by_reason.not_identified_as_mcp hostnames whose HTTP answer identified no MCP server. mcp_servers.era divides every counted hostname by protocol era: mcp_servers.era.legacy; mcp_servers.era.dual, a lower bound; mcp_servers.era.modern, not proven modern-only; mcp_servers.era.unknown; and mcp_servers.era.not_measured, recorded before the era probe and not re-checked since. mcp_servers.transport divides them by transport: mcp_servers.transport.streamable_http, mcp_servers.transport.legacy_sse, mcp_servers.transport.unknown and mcp_servers.transport.not_measured. mcp_servers.window.from and mcp_servers.window.to are when the oldest and the newest of the verdicts counted were last checked. mcp_servers.last_run_at is a timestamp, not a count: when the AI-exposure radar, which checks other AI services too, last completed a check; mcp_servers.enabled is whether one completed within 45 minutes of the answer, and mcp_servers.counted_at is when the API read the counts. A partition whose buckets do not add up to the count it divides is left out and named; an answer that does not say it is the MCP-server counts, or whose mcp_servers.total, mcp_servers.protected, mcp_servers.pending_readjudication and mcp_servers.not_assessed are missing or contradict each other, is a failure.", + "properties": { + "counted_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "era": { + "additionalProperties": false, + "properties": { + "dual": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "legacy": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "modern": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "legacy", + "dual", + "modern", + "unknown", + "not_measured" + ], + "type": "object" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "not_assessed": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_assessed_by_reason": { + "additionalProperties": false, + "properties": { + "bare_challenge_no_prm": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "challenge_unadjudicated": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "cross_origin_pointer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "identified_no_challenge": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "metadata_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_authorization_servers": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_http_answer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_identified_as_mcp": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "resource_mismatch": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "identified_no_challenge", + "resource_mismatch", + "cross_origin_pointer", + "bare_challenge_no_prm", + "pointer_unreachable", + "pointer_invalid", + "no_authorization_servers", + "wellknown_unreachable", + "metadata_invalid", + "challenge_unadjudicated", + "no_http_answer", + "not_identified_as_mcp" + ], + "type": "object" + }, + "own_controls_excluded": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pending_readjudication": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "prm_via": { + "additionalProperties": false, + "properties": { + "header": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_path": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_root": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "header", + "wellknown_path", + "wellknown_root" + ], + "type": "object" + }, + "protected": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "transport": { + "additionalProperties": false, + "properties": { + "legacy_sse": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "streamable_http": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "streamable_http", + "legacy_sse", + "unknown", + "not_measured" + ], + "type": "object" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "withheld_opted_out": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "protected", + "pending_readjudication", + "not_assessed" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "description": "shadow_ai: the result is regrouped by what each number counts. shadow_ai.confirmed_exposed counts services EchelonGraph's probes found answering without an authentication gate (liveness active, or rechecking during a re-check): confirmed_exposed.total is the sum of confirmed_exposed.by_category, and confirmed_exposed.last_24h counts those first recorded in the last 24 h. Of the shadow_ai numbers, only confirmed_exposed counts exposed services. confirmed_exposed.window.from and confirmed_exposed.window.to are timestamps, not counts: when EchelonGraph's verifier ran the probe that last decided the oldest and the newest of those services, a span of probes made at different times. shadow_ai.observed counts every Certificate Transparency or Shodan observation on record, whatever its verification state: its numbers are observed, not exposed. They are observed.total; observed.by_category (the same observations by category); observed.last_24h (those first recorded in the last 24 h); observed.trend_30d (observations per UTC day over the last 30 days); and observed.top_products, observed.top_countries and observed.top_issuers (up to ten products, countries and issuers ranked by observations, where an issuer is the certificate's CA for a Certificate Transparency observation and the hosting operator Shodan reports for a Shodan one). shadow_ai.authentication counts observations by probe outcome: authentication.observed where a probe observed an authentication gate (a 401/403, a login page or an auth marker), and authentication.not_determined where the service answered but no probe could tell. Neither authentication count is part of confirmed_exposed, and observed.total minus confirmed_exposed.total is not a count of secured services. The shadow-AI poller block carries only running and last_run_at: last_run_at is when the radar's leader last completed a Certificate Transparency (crt.sh) cycle, and its running is true only when that was within 30 minutes of the answer. Shodan data is owned by Shodan, which holds its copyright (© Shodan).", + "properties": { + "authentication": { + "additionalProperties": false, + "properties": { + "not_determined": { + "type": "number" + }, + "observed": { + "type": "number" + } + }, + "type": "object" + }, + "confirmed_exposed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "observed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "last_observation": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "country": { + "type": "string" + } + }, + "required": [ + "country", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_issuers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "issuer": { + "type": "string" + } + }, + "required": [ + "issuer", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "trend_30d": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "date": { + "type": "string" + } + }, + "required": [ + "date", + "count" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "poller": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "running": { + "type": "boolean" + } + }, + "required": [ + "running", + "last_run_at" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "exposed_databases": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + }, + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at", + "enabled" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "running": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "last_run_at", + "running" + ], + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "radars": { + "description": "Each radar that could not be read, and why.", + "items": { + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "unexpected_shape" + ], + "type": "string" + }, + "message": { + "type": "string" + }, + "path": { + "type": "string" + }, + "radar": { + "type": "string" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "radar", + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "nvd_patch_reference" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range) and nvd_patch_reference (an NVD reference tagged Patch). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "type": [ - "string", - "null" - ] - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 22-01, by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "nvd_patch_reference", + "cna_patch_reference" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), nvd_patch_reference (an NVD reference tagged Patch) and cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_vendor_advisory1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "known_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_modified_at": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - }, - "withdrawn_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn_reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "known_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "references": {}, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation": { + "description": "The vendor's remediation as one text (the legacy field), beside remediations.", + "type": [ + "string", + "null" + ] + }, + "remediation_items_not_stored": { + "description": "Items past the 64 stored per advisory.", + "type": [ + "number", + "null" + ] + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "remediations": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVEs the item covers; [] for the whole advisory." + }, + "fixed_build": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "product_count": { + "type": [ + "number", + "null" + ] + }, + "product_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "source_category": { + "description": "The vendor's own name for the category.", + "type": [ + "string", + "null" + ] + }, + "source_subcategory": { + "type": [ + "string", + "null" + ] + }, + "text": { + "description": "The vendor's text, verbatim but for HTML markup removed, untested by EchelonGraph; at most 2,000 characters (text_truncated, text_chars).", + "type": [ + "string", + "null" + ] + }, + "text_chars": { + "type": [ + "number", + "null" + ] + }, + "text_truncated": { + "type": [ + "boolean", + "null" + ] + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each remediation the vendor lists, with its kind, the vendor's own category." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_modified_at": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
kev_recent3 fields changed- changed
Input schema / properties / since / descriptionPrevious value: -"earliest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it)"New value: +"earliest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it, with the time and offset dropped; anything else is refused)" - changed
Input schema / properties / until / descriptionPrevious value: -"latest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it)"New value: +"latest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it, with the time and offset dropped; anything else is refused)" - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "catalog": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "catalog_count": { - "type": [ - "number", - "null" - ] - }, - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "feed_url": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "filters": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": {}, - "type": "object" - }, - { - "type": "null" - } - ] - }, - "generated_at": { - "type": [ - "string", - "null" - ] - }, - "kev": { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "eg_kev_tier": { - "type": [ - "number", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_due_date": { - "type": [ - "string", - "null" - ] - }, - "kev_product": { - "type": [ - "string", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "kev_vendor": { - "type": [ - "string", - "null" - ] - }, - "kev_vuln_name": { - "type": [ - "string", - "null" - ] - }, - "our_first_seen_kev": { - "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "kev_listed_total": { - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - }, - "notes": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "order": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog_version": { - "type": [ - "string", - "null" - ] - }, - "date_released": { - "type": [ - "string", - "null" - ] - }, - "last_successful_fetch_at": { - "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "last_successful_fetch_at", - "catalog_version", - "date_released" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "catalog": { - "const": "CISA KEV catalog", - "type": "string" - }, - "catalog_count": { - "description": "CISA's own count, in the catalog last fetched.", - "type": [ - "number", - "null" - ] - }, - "has_more": { - "description": "Whether next_cursor names a further page.", - "type": [ - "boolean", - "null" - ] - }, - "kev_listed_total": { - "description": "Every CVE EchelonGraph holds as KEV-listed.", - "type": [ - "number", - "null" - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "description": "Rows in this page.", - "type": [ - "number", - "null" - ] - }, - "total": { - "description": "CVEs matching the filters.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "catalog", - "total", - "returned", - "kev_listed_total", - "catalog_count", - "limit", - "has_more" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog": { + "const": "CISA KEV catalog", + "type": "string" + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "catalog": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "catalog_count": { + "type": [ + "number", + "null" + ] + }, + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "feed_url": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "filters": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "generated_at": { + "type": [ + "string", + "null" + ] + }, + "kev": { + "description": "Newest kev_added_date first; rows within one date are ordered by cve_id.", + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "eg_kev_tier": { + "type": [ + "number", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "type": [ + "string", + "null" + ] + }, + "kev_product": { + "type": [ + "string", + "null" + ] + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_vendor": { + "type": [ + "string", + "null" + ] + }, + "kev_vuln_name": { + "type": [ + "string", + "null" + ] + }, + "our_first_seen_kev": { + "description": "When EchelonGraph's poller first recorded the CVE entering the catalog; null where no such record exists.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "kev_listed_total": { + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "next_cursor": { + "type": [ + "string", + "null" + ] + }, + "notes": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "order": { + "type": [ + "string", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog_version": { + "type": [ + "string", + "null" + ] + }, + "date_released": { + "type": [ + "string", + "null" + ] + }, + "last_successful_fetch_at": { + "description": "When CISA last answered our poll of its feed: a 200 we applied, or a 304 Not Modified.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "last_successful_fetch_at", + "catalog_version", + "date_released" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "catalog": { + "const": "CISA KEV catalog", + "type": "string" + }, + "catalog_count": { + "description": "CISA's own count, in the catalog last fetched.", + "type": [ + "number", + "null" + ] + }, + "has_more": { + "description": "Whether next_cursor names a further page.", + "type": [ + "boolean", + "null" + ] + }, + "kev_listed_total": { + "description": "Every CVE EchelonGraph holds as KEV-listed.", + "type": [ + "number", + "null" + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "Rows in this page.", + "type": [ + "number", + "null" + ] + }, + "total": { + "description": "CVEs matching the filters.", + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "catalog", + "total", + "returned", + "kev_listed_total", + "catalog_count", + "limit", + "has_more" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Added
scan_manifest - Changed
search_cves1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "patch_available": { - "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false.", - "type": [ - "boolean", - "null" - ] - }, - "patch_evidence": { - "anyOf": [ - { - "items": { - "anyOf": [ - { - "enum": [ - "vendor_patch", - "fixed_version", - "nvd_patch_reference" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range) and nvd_patch_reference (an NVD reference tagged Patch). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "type": [ - "string", - "null" - ] - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_due_date": { + "description": "CISA's dueDate: when US federal civilian agencies must have applied kev_required_action. Absent where the CVE is not CISA-KEV-listed.", + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_notes_urls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The https links in CISA's notes for the CVE, in CISA's order, de-duplicated, at most 10: the references CISA's catalog entry gives, such as the vendor's advisory or instructions and NVD's page. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none)." + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "kev_required_action": { + "description": "CISA's requiredAction for the CVE, verbatim from its Known Exploited Vulnerabilities catalog: the action CISA requires of US federal civilian agencies under Binding Operational Directive 22-01, by kev_due_date. It is CISA's text, not EchelonGraph's advice. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "kev_short_description": { + "description": "CISA's shortDescription of the vulnerability, verbatim from its Known Exploited Vulnerabilities catalog. Absent where the CVE is not CISA-KEV-listed, where CISA's entry has none, or where EchelonGraph has not stored it yet (an API older than the field serves none).", + "type": [ + "string", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false. An answer with no patch_evidence (an API older than that field) does not name the evidence, and a false there is not a finding that no fix exists either.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "release_reference", + "nvd_patch_reference", + "cna_patch_reference" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range), release_reference (a reference that EchelonGraph confirmed through the GitHub API is a published release containing the fix, or a pull request or commit that a published release contains), nvd_patch_reference (an NVD reference tagged Patch) and cna_patch_reference (a reference the CVE's CNA tagged patch in its CVE record). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": {}, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "A capped summary (at most 1,500 characters of JSON) of how the CVE is fixed, as its sources state it: vendor_remediation_kinds (per kind, the vendor advisories listing one for this CVE, by the vendor's own category), vendor_advisories, vendors_not_parsed, kev_required_action (CISA's, verbatim), fixed_branches_count, fixed_versions (per package, fixed versions on record), fix_references (URLs tagged Patch or Mitigation), failed_sections, truncated, and see, the name of the tool that returns the whole, with each text. A kind missing from vendor_remediation_kinds is not a finding that no such remediation exists. Absent for a REJECTED CVE and from an API older than the field." + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "description": "How confident EchelonGraph is in its score: NONE when score_assessed is false.", + "type": [ + "string", + "null" + ] + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "description": "true: a search phrase was relaxed to all of its words.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "description": "false: the matches were not counted, so total is not a count.", + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "description": "true: there are at least total matches.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "description": "The rows in this page.", + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_vendor_advisories1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "description": "Whether a free-text search filtered this answer.", - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query.", - "type": [ - "string", - "null" - ] - }, - "total": { - "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "description": "Whether a free-text search filtered this answer.", + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query. A query of 3 or more characters is matched case-insensitively as a substring of each advisory's title, description, vendor name, vendor_advisory_id, affected_products and cve_ids (search_match substring). A query of 1 or 2 characters matches whole words only (search_match word): it must equal, ignoring case, a whole word (a run of letters and digits) of one of those, so xz finds xz-utils but not xzibit, and a 1- or 2-character query with any other character, such as c#, matches nothing.", + "type": [ + "string", + "null" + ] + }, + "total": { + "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count. A search counts at most 1,000 matches: past that, total is 1000 and total_capped is true, which means 1,000 or more (the note writes 1,000+), never exactly 1,000; paging past it still works. Without a query, total is the exact count and total_capped is false.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds, only that vendor's when vendor is given; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
vendor_advisories_for_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "rejected_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs this advisory names whose CVE record was rejected (withdrawn) by its numbering authority: each is a rejected record, not an active vulnerability, whatever the advisory's text says. The vendor's withdrawn is separate and unchanged by it. [] when none is; null when that could not be checked." + }, + "remediation_kinds": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_fix", + "workaround", + "mitigation", + "no_fix_planned", + "none_available", + "other" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The kinds of remediation the advisory lists (for the CVE asked about, on a by-cve row), each the vendor's own category, never read from the text: vendor_fix, workaround, mitigation, no_fix_planned, none_available or other. [] with remediation_state not_parsed is not a finding that it lists none." + }, + "remediation_state": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "parsed", + "none_in_source", + "not_parsed", + "withdrawn" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "parsed; none_in_source (EchelonGraph read the vendor's remediation, and it lists none for this CVE, which is not a finding that no fix exists); not_parsed (EchelonGraph does not read this vendor's remediation, or has not yet read this advisory: not a finding of none); withdrawn (the vendor rescinded the advisory)." + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cve_rejected": { + "description": "true: the CVE record of cve_id was rejected (withdrawn) by its numbering authority, so these advisories name a rejected record, not an active vulnerability; null when that could not be checked.", + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "description": "A vendor's window in what EchelonGraph holds: vendor, advisories (how many EchelonGraph holds from that vendor), earliest_vendor_published_at and latest_vendor_published_at (the earliest and latest vendor_published_at among them, null when none is held), held_since (the start of the window EchelonGraph has read that vendor's advisories from, before which an advisory may not be held; null when none is held or the API does not say; for a vendor with no history read it is when its feed was first read from, and can be years after earliest_vendor_published_at, since an older advisory is held when the vendor revised it later, not the ones published beside it) and history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried).", + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
2 tool updates
- Changed
get_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "type": [ - "string", - "null" - ] - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "nvd_patch_reference" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range) and nvd_patch_reference (an NVD reference tagged Patch). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "type": [ + "string", + "null" + ] + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_cves1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "cves": { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_configurations": { - "anyOf": [ - { - "items": {}, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." - }, - "cpe_match": { - "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_severity": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_risk": { - "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", - "type": [ - "string", - "null" - ] - }, - "epss_percentile": { - "type": [ - "number", - "null" - ] - }, - "epss_score": { - "type": [ - "number", - "null" - ] - }, - "ghsa_id": { - "type": [ - "string", - "null" - ] - }, - "kev_added_date": { - "type": [ - "string", - "null" - ] - }, - "kev_listed": { - "type": [ - "boolean", - "null" - ] - }, - "kev_ransomware": { - "type": [ - "boolean", - "null" - ] - }, - "modified": { - "type": [ - "string", - "null" - ] - }, - "published": { - "type": [ - "string", - "null" - ] - }, - "references": {}, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", - "type": [ - "boolean", - "null" - ] - }, - "score_confidence": { - "type": [ - "string", - "null" - ] - }, - "score_unassessed_reason": { - "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_relaxed": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "total_counted": { - "type": [ - "boolean", - "null" - ] - }, - "total_is_lower_bound": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "total", - "total_counted", - "total_is_lower_bound", - "search_relaxed", - "returned", - "limit", - "offset" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "cves": { + "items": { + "additionalProperties": {}, + "properties": { + "cpe_configurations": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "NVD's configurations array as NVD sent it: each configuration and node with its operator (AND, OR) and negate, and each cpeMatch with criteria, vulnerable, versionStartIncluding, versionStartExcluding, versionEndIncluding, versionEndExcluding and matchCriteriaId. A cpeMatch with vulnerable false inside an AND configuration is the platform the vulnerable product runs on, not an affected product. Absent: EchelonGraph holds no stored NVD configuration for the CVE, which is not a finding that no product is affected." + }, + "cpe_match": { + "description": "The record's CPE match criteria as one flat list, every configuration's cpeMatch entries together: the AND/OR operator and negate of each configuration and node, versionStartExcluding and matchCriteriaId are not in it, so a CPE that is only a platform a product runs on reads as one more entry." + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_severity": { + "type": [ + "string", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_risk": { + "description": "EchelonGraph's 0-100 risk priority, fused from the score, exploitation and automatability: a rating only when score_assessed is true. With score_assessed false it is a placeholder.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score for the CVE: a score only when score_assessed is true. With score_assessed false it is a placeholder, not a rating.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "description": "The severity band of echelongraph_score: a rating only when score_assessed is true. With score_assessed false it is a placeholder (NONE).", + "type": [ + "string", + "null" + ] + }, + "epss_percentile": { + "type": [ + "number", + "null" + ] + }, + "epss_score": { + "type": [ + "number", + "null" + ] + }, + "ghsa_id": { + "type": [ + "string", + "null" + ] + }, + "kev_added_date": { + "type": [ + "string", + "null" + ] + }, + "kev_listed": { + "type": [ + "boolean", + "null" + ] + }, + "kev_ransomware": { + "type": [ + "boolean", + "null" + ] + }, + "modified": { + "type": [ + "string", + "null" + ] + }, + "patch_available": { + "description": "true: EchelonGraph holds evidence of a fix for the CVE, its sources named in patch_evidence. false: no fix evidence is on record, which is not a finding that no fix exists. Once true it is never set back to false.", + "type": [ + "boolean", + "null" + ] + }, + "patch_evidence": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "enum": [ + "vendor_patch", + "fixed_version", + "nvd_patch_reference" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sources of the fix evidence EchelonGraph holds for the CVE, strongest first: vendor_patch (a vendor patch on record, from Ubuntu or Red Hat), fixed_version (a fixed version recorded for an affected package, or the fixed bound of an affected version range) and nvd_patch_reference (an NVD reference tagged Patch). Empty where none was found when EchelonGraph last computed it. Absent (an API older than the field): the answer does not name the evidence." + }, + "published": { + "type": [ + "string", + "null" + ] + }, + "references": {}, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. true: echelongraph_score, echelongraph_severity and echelongraph_risk are its score. false: the CVE is NOT YET SCORED, not scored 0, and any of those three it carries is a placeholder, not a rating; the API may leave them out. Absent (an API older than the field): the answer does not say whether the CVE was scored.", + "type": [ + "boolean", + "null" + ] + }, + "score_confidence": { + "type": [ + "string", + "null" + ] + }, + "score_unassessed_reason": { + "description": "Why score_assessed is false: no_signal, no source has yet published severity data EchelonGraph can score; or rejected, the record was withdrawn by its numbering authority and is never scored. Absent when the CVE is scored.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_relaxed": { + "type": [ + "boolean", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "total_counted": { + "type": [ + "boolean", + "null" + ] + }, + "total_is_lower_bound": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "total", + "total_counted", + "total_is_lower_bound", + "search_relaxed", + "returned", + "limit", + "offset" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
4 tool updates
- Changed
check_affected1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Read first. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", - "type": [ - "boolean", - "null" - ] - }, - "candidate_count": { - "type": [ - "number", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "ecosystem_recognised": { - "type": [ - "boolean", - "null" - ] - }, - "excluded": {}, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cpe_vendor": { - "description": "The vendor NVD's CPE asserts for this match.", - "type": [ - "string", - "null" - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "cvss_v2_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "cvss_v4_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "echelongraph_score": { - "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", - "type": [ - "number", - "null" - ] - }, - "echelongraph_severity": { - "type": [ - "string", - "null" - ] - }, - "effective_score": { - "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", - "type": [ - "number", - "null" - ] - }, - "effective_severity": { - "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", - "type": [ - "string", - "null" - ] - }, - "epss_score": { - "description": "EPSS exploitation probability, 0 to 1.", - "type": [ - "number", - "null" - ] - }, - "kev_listed": { - "description": "Listed in CISA-KEV: known to be exploited.", - "type": [ - "boolean", - "null" - ] - }, - "match_confidence": { - "type": [ - "number", - "null" - ] - }, - "match_method": { - "type": [ - "string", - "null" - ] - }, - "match_reason": { - "type": [ - "string", - "null" - ] - }, - "matched_criteria": { - "type": [ - "string", - "null" - ] - }, - "ransomware": { - "description": "CISA-KEV records known use in ransomware campaigns.", - "type": [ - "boolean", - "null" - ] - }, - "score_assessed": { - "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", - "type": [ - "boolean", - "null" - ] - }, - "score_unassessed_reason": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", - "type": [ - "string", - "null" - ] - }, - "vendor_severity": { - "type": [ - "string", - "null" - ] - }, - "vendor_unknown": { - "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", - "type": [ - "boolean", - "null" - ] - }, - "version_evidence": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "product": { - "type": [ - "string", - "null" - ] - }, - "product_named_count": { - "type": [ - "number", - "null" - ] - }, - "undecidable_excluded_count": { - "type": [ - "number", - "null" - ] - }, - "undecided_candidate_count": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "detail": { - "type": [ - "string", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_count": { - "type": [ - "number", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "assessed": { - "description": "The answer's assessed, first: null when the answer does not say.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "degraded": { - "type": [ - "boolean", - "null" - ] - }, - "excluded_count": { - "type": [ - "number", - "null" - ] - }, - "lookup": { - "description": "Which lookup path this call asked for.", - "enum": [ - "cpe", - "registry" - ], - "type": "string" - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "product_not_in_cpe_corpus", - "package_not_cpe_nameable", - "candidate_load_pending", - "candidate_window_truncated", - "package_not_in_advisory_corpus", - "no_decidable_advisory", - "advisory_lookup_failed" - ], - "type": "string" - }, - { - "type": "string" - } - ], - "description": "Why assessed is false; empty or absent when it is true." - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "assessed", - "not_assessed_reason", - "lookup", - "match_layer", - "count", - "capped", - "candidates_capped", - "excluded_count", - "undetermined_count", - "not_affected_count", - "degraded" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "count depends on it. true: the lookup evaluated this component. false: it did not, and count 0 says nothing about whether this version is affected.", + "type": [ + "boolean", + "null" + ] + }, + "candidate_count": { + "type": [ + "number", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "ecosystem_recognised": { + "type": [ + "boolean", + "null" + ] + }, + "excluded": {}, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cpe_vendor": { + "description": "The vendor NVD's CPE asserts for this match.", + "type": [ + "string", + "null" + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "cvss_v2_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "cvss_v4_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "echelongraph_score": { + "description": "EchelonGraph's 0-10 score: present only when score_assessed is true.", + "type": [ + "number", + "null" + ] + }, + "echelongraph_severity": { + "type": [ + "string", + "null" + ] + }, + "effective_score": { + "description": "The best real score held for the CVE (EchelonGraph's, else CVSS), the number the matches are ranked by.", + "type": [ + "number", + "null" + ] + }, + "effective_severity": { + "description": "The band of effective_score; absent or empty when the CVE has no band at all (unrated, not harmless).", + "type": [ + "string", + "null" + ] + }, + "epss_score": { + "description": "EPSS exploitation probability, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "kev_listed": { + "description": "Listed in CISA-KEV: known to be exploited.", + "type": [ + "boolean", + "null" + ] + }, + "match_confidence": { + "type": [ + "number", + "null" + ] + }, + "match_method": { + "type": [ + "string", + "null" + ] + }, + "match_reason": { + "type": [ + "string", + "null" + ] + }, + "matched_criteria": { + "type": [ + "string", + "null" + ] + }, + "ransomware": { + "description": "CISA-KEV records known use in ransomware campaigns.", + "type": [ + "boolean", + "null" + ] + }, + "score_assessed": { + "description": "Whether EchelonGraph has scored the CVE. false: NOT YET SCORED, and echelongraph_score is withheld.", + "type": [ + "boolean", + "null" + ] + }, + "score_unassessed_reason": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "description": "NVD's own CVSS v3 band, as provenance: it can be NONE for a CVE NVD rated only under CVSS v2. Rank and display on effective_severity.", + "type": [ + "string", + "null" + ] + }, + "vendor_severity": { + "type": [ + "string", + "null" + ] + }, + "vendor_unknown": { + "description": "true: the vendor was not verified, so the match is real but its attribution to your vendor is not.", + "type": [ + "boolean", + "null" + ] + }, + "version_evidence": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "product": { + "type": [ + "string", + "null" + ] + }, + "product_named_count": { + "type": [ + "number", + "null" + ] + }, + "undecidable_excluded_count": { + "type": [ + "number", + "null" + ] + }, + "undecided_candidate_count": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "detail": { + "type": [ + "string", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_count": { + "type": [ + "number", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "assessed": { + "description": "The answer's assessed, first: null when the answer does not say.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "degraded": { + "type": [ + "boolean", + "null" + ] + }, + "excluded_count": { + "type": [ + "number", + "null" + ] + }, + "lookup": { + "description": "Which lookup path this call asked for.", + "enum": [ + "cpe", + "registry" + ], + "type": "string" + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "product_not_in_cpe_corpus", + "package_not_cpe_nameable", + "candidate_load_pending", + "candidate_window_truncated", + "package_not_in_advisory_corpus", + "no_decidable_advisory", + "advisory_lookup_failed" + ], + "type": "string" + }, + { + "type": "string" + } + ], + "description": "Why assessed is false; empty or absent when it is true." + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + } + }, + "required": [ + "assessed", + "not_assessed_reason", + "lookup", + "match_layer", + "count", + "capped", + "candidates_capped", + "excluded_count", + "undetermined_count", + "not_affected_count", + "degraded" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_vendor_advisory1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "known_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_modified_at": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - }, - "withdrawn_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn_reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "known_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_modified_at": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_vendor_advisories1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "description": "Whether a free-text search filtered this answer.", - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query.", - "type": [ - "string", - "null" - ] - }, - "total": { - "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "description": "Whether a free-text search filtered this answer.", + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query.", + "type": [ + "string", + "null" + ] + }, + "total": { + "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
vendor_advisories_for_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", - "type": [ - "string", - "null" - ] - }, - "held_since": { - "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "held_since", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory, so it is a withdrawn advisory, not a current one.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
5 tool updates
- Changed
cve_intel1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "affected_packages": { - "items": { - "additionalProperties": {}, - "properties": { - "dependents_count": { - "type": [ - "number", - "null" - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_version": { - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "version_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "cve_id": { - "type": "string" - }, - "cwes": { - "items": { - "additionalProperties": {}, - "properties": { - "cwe_id": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits": { - "items": { - "additionalProperties": {}, - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "first_seen_at": { - "type": [ - "string", - "null" - ] - }, - "kind": { - "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", - "type": [ - "string", - "null" - ] - }, - "source_name": { - "type": [ - "string", - "null" - ] - }, - "source_url": { - "type": [ - "string", - "null" - ] - }, - "verified_status": { - "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "exploits_by_kind": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_by_status": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "exploits_capped": { - "description": "true: exploits lists fewer references than exploits_total.", - "type": "boolean" - }, - "exploits_total": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Every exploit reference on record for the CVE, not only those listed in exploits." - }, - "fixed_versions": { - "items": { - "additionalProperties": {}, - "properties": { - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "fixed_version": { - "type": [ - "string", - "null" - ] - }, - "package_name": { - "type": [ - "string", - "null" - ] - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "vulnerable_range": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline": { - "items": { - "additionalProperties": {}, - "properties": { - "enriched_at": { - "type": [ - "string", - "null" - ] - }, - "enrichment_kind": { - "type": [ - "string", - "null" - ] - }, - "fields_changed": {}, - "score_delta": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "timeline_count_30d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_count_7d": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "timeline_total": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "cve_id" - ], - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "affected_packages": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "exploits": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "fixed_versions": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Rows the API returned; null when the section was not read." - } - }, - "required": [ - "returned", - "api_row_limit" - ], - "type": "object" - }, - "sections_failed": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." - }, - "sections_left_out": { - "description": "The sections of the answer this tool does not relay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "sections_relayed": { - "description": "The sections of the answer relayed in data.", - "items": { - "type": "string" - }, - "type": "array" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "api_row_limit": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "relayed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The newest rows relayed in data.timeline." - }, - "returned": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "returned", - "relayed", - "api_row_limit" - ], - "type": "object" - } - }, - "required": [ - "sections_relayed", - "sections_failed", - "sections_left_out", - "exploits", - "affected_packages", - "fixed_versions", - "timeline" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "properties": { + "affected_packages": { + "items": { + "additionalProperties": {}, + "properties": { + "dependents_count": { + "type": [ + "number", + "null" + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_branches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "description": "The OSV record that published the range (GHSA-…, PYSEC-…, CVE-…); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + }, + "fixed": { + "description": "The range's fix: the first version past it. null where no fix is on record.", + "type": [ + "string", + "null" + ] + }, + "introduced": { + "description": "The range's lower bound, inclusive; \"0\" is the first version.", + "type": [ + "string", + "null" + ] + }, + "last_affected": { + "description": "The range's last affected version, inclusive, where no fix is on record; never a fix.", + "type": [ + "string", + "null" + ] + }, + "source": { + "description": "The loader's label for that record (osv_bulk, osv); null on a row loaded before it was stored.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "fixed_branches lists each affected range of the package on record: introduced, and fixed (the range's fix) or last_affected (its last affected version, where no fix is on record), each null when absent, with advisory_id (the OSV record that published the range) and source (the loader's label for that record), both null on a row loaded before they were stored. Ranges with an advisory_id are in the order their record lists them (records in id order); ranges without one are oldest first. To pick the range for an installed version, compare in the ecosystem's version order (release numbers part by part, as numbers: 2.4 is below 2.13.0): the version is in a range when it is at or above introduced (\"0\" is the first version) and below fixed, or at or below last_affected; that range's fixed is the fix for it, and a version in no range is outside every range on record. fixed_branches is null where the package's ranges were never loaded, and [] where no version range is on record (the advisory gives none, only commit ranges, or more than are stored), which is not a finding that no fix exists: fixed_version can still name one. fixed_version is one range's fix, kept for compatibility (one per package: the range the loader kept, the advisory's last as a rule), not the fix for every affected range: for CVE-2021-44228, its advisory gives log4j-core three ranges, and fixed_version 2.12.2 is the fix for the one from 2.4, while the range holding 2.14.1 (from 2.13.0) is fixed in 2.15.0." + }, + "fixed_version": { + "description": "One range's fix, kept for compatibility; not the fix for every affected range: read fixed_branches.", + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "version_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "cve_id": { + "type": "string" + }, + "cwes": { + "items": { + "additionalProperties": {}, + "properties": { + "cwe_id": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits": { + "items": { + "additionalProperties": {}, + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "first_seen_at": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "description": "metasploit, exploit_db, nuclei_template, github_poc or vendor_poc.", + "type": [ + "string", + "null" + ] + }, + "source_name": { + "type": [ + "string", + "null" + ] + }, + "source_url": { + "type": [ + "string", + "null" + ] + }, + "verified_status": { + "description": "verified_status is the label stored with each reference: verified for a Metasploit module, for an Exploit-DB entry Exploit-DB marks verified, and for curated seed rows marked so; reported for a public artefact nothing has confirmed works (nuclei templates, GitHub proofs of concept, unverified Exploit-DB entries); unconfirmed where a curated row says so. It is a label from the source, not a guarantee that the exploit works against a given system.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "exploits_by_kind": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_by_status": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "exploits_capped": { + "description": "true: exploits lists fewer references than exploits_total.", + "type": "boolean" + }, + "exploits_total": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Every exploit reference on record for the CVE, not only those listed in exploits." + }, + "fixed_versions": { + "items": { + "additionalProperties": {}, + "properties": { + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "fixed_version": { + "type": [ + "string", + "null" + ] + }, + "package_name": { + "type": [ + "string", + "null" + ] + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "vulnerable_range": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline": { + "items": { + "additionalProperties": {}, + "properties": { + "enriched_at": { + "type": [ + "string", + "null" + ] + }, + "enrichment_kind": { + "type": [ + "string", + "null" + ] + }, + "fields_changed": {}, + "score_delta": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "timeline_count_30d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_count_7d": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "timeline_total": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "cve_id" + ], + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "affected_packages": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "exploits": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "fixed_versions": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "description": "The most rows the API returns for this list per CVE: a list this long may be cut.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Rows the API returned; null when the section was not read." + } + }, + "required": [ + "returned", + "api_row_limit" + ], + "type": "object" + }, + "sections_failed": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The sections the API says it could not read (its failed_sections), left out of data; null when the answer does not say (an API older than failed_sections), so an empty list may be an unread section." + }, + "sections_left_out": { + "description": "The sections of the answer this tool does not relay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sections_relayed": { + "description": "The sections of the answer relayed in data.", + "items": { + "type": "string" + }, + "type": "array" + }, + "timeline": { + "additionalProperties": false, + "properties": { + "api_row_limit": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "relayed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The newest rows relayed in data.timeline." + }, + "returned": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "returned", + "relayed", + "api_row_limit" + ], + "type": "object" + } + }, + "required": [ + "sections_relayed", + "sections_failed", + "sections_left_out", + "exploits", + "affected_packages", + "fixed_versions", + "timeline" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
exposure_radar1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "distinct_hosts": { - "type": "number" - }, - "engines": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "pci_likely": { - "type": "number" - }, - "pii_likely": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_engines": { - "items": { - "additionalProperties": false, - "properties": { - "engine": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "engine", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "correlations": { - "type": "number" - }, - "distinct_hosts": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "kev_cves_exposed": { - "type": "number" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "newest_kev": { - "items": { - "additionalProperties": false, - "properties": { - "added_date": { - "type": "string" - }, - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "exposed_hosts": { - "type": "number" - }, - "exposure_state": { - "enum": [ - "exposed", - "measured_zero", - "not_assessed" - ], - "type": "string" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - }, - "vuln_name": { - "type": "string" - } - }, - "required": [ - "cve_id", - "exposure_state" - ], - "type": "object" - }, - "type": "array" - }, - "ransomware_cves": { - "type": "number" - }, - "ransomware_hosts": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_cves": { - "items": { - "additionalProperties": false, - "properties": { - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "hosts": { - "type": "number" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - } - }, - "required": [ - "cve_id", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "hosts": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "trend": { - "items": { - "additionalProperties": false, - "properties": { - "new_exposures": { - "type": "number" - }, - "week": { - "type": "string" - } - }, - "required": [ - "week", - "new_exposures" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "distinct_repos": { - "type": "number" - }, - "distinct_secrets": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_providers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "provider": { - "type": "string" - } - }, - "required": [ - "provider", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_types": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "secret_type": { - "type": "string" - } - }, - "required": [ - "secret_type", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "counted_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "era": { - "additionalProperties": false, - "properties": { - "dual": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "legacy": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "modern": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "legacy", - "dual", - "modern", - "unknown", - "not_measured" - ], - "type": "object" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "not_assessed": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_assessed_by_reason": { - "additionalProperties": false, - "properties": { - "bare_challenge_no_prm": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "challenge_unadjudicated": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "cross_origin_pointer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "identified_no_challenge": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "metadata_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_authorization_servers": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_http_answer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_identified_as_mcp": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "resource_mismatch": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "identified_no_challenge", - "resource_mismatch", - "cross_origin_pointer", - "bare_challenge_no_prm", - "pointer_unreachable", - "pointer_invalid", - "no_authorization_servers", - "wellknown_unreachable", - "metadata_invalid", - "challenge_unadjudicated", - "no_http_answer", - "not_identified_as_mcp" - ], - "type": "object" - }, - "own_controls_excluded": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pending_readjudication": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "prm_via": { - "additionalProperties": false, - "properties": { - "header": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_path": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_root": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "header", - "wellknown_path", - "wellknown_root" - ], - "type": "object" - }, - "protected": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "transport": { - "additionalProperties": false, - "properties": { - "legacy_sse": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "streamable_http": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "streamable_http", - "legacy_sse", - "unknown", - "not_measured" - ], - "type": "object" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "required": [ - "total", - "protected", - "pending_readjudication", - "not_assessed" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "authentication": { - "additionalProperties": false, - "properties": { - "not_determined": { - "type": "number" - }, - "observed": { - "type": "number" - } - }, - "type": "object" - }, - "confirmed_exposed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "total": { - "type": "number" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "type": "object" - }, - "observed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "last_observation": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "country": { - "type": "string" - } - }, - "required": [ - "country", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_issuers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "issuer": { - "type": "string" - } - }, - "required": [ - "issuer", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "trend_30d": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "date": { - "type": "string" - } - }, - "required": [ - "date", - "count" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "poller": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "running": { - "type": "boolean" - } - }, - "required": [ - "running", - "last_run_at" - ], - "type": "object" - } - }, - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at", - "enabled" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - }, - "running": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "last_run_at", - "running" - ], - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "radars": { - "description": "Each radar that could not be read, and why.", - "items": { - "additionalProperties": false, - "properties": { - "kind": { - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "unexpected_shape" - ], - "type": "string" - }, - "message": { - "type": "string" - }, - "path": { - "type": "string" - }, - "radar": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "radar", - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "type": "array" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "properties": { + "exposed_databases": { + "additionalProperties": false, + "properties": { + "distinct_hosts": { + "type": "number" + }, + "engines": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "pci_likely": { + "type": "number" + }, + "pii_likely": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_engines": { + "items": { + "additionalProperties": false, + "properties": { + "engine": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "engine", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "properties": { + "correlations": { + "type": "number" + }, + "distinct_hosts": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "kev_cves_exposed": { + "type": "number" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "newest_kev": { + "items": { + "additionalProperties": false, + "properties": { + "added_date": { + "type": "string" + }, + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "exposed_hosts": { + "type": "number" + }, + "exposure_state": { + "enum": [ + "exposed", + "measured_zero", + "not_assessed" + ], + "type": "string" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "vuln_name": { + "type": "string" + } + }, + "required": [ + "cve_id", + "exposure_state" + ], + "type": "object" + }, + "type": "array" + }, + "ransomware_cves": { + "type": "number" + }, + "ransomware_hosts": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_cves": { + "items": { + "additionalProperties": false, + "properties": { + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "hosts": { + "type": "number" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + }, + "required": [ + "cve_id", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "hosts": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "trend": { + "items": { + "additionalProperties": false, + "properties": { + "new_exposures": { + "type": "number" + }, + "week": { + "type": "string" + } + }, + "required": [ + "week", + "new_exposures" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "properties": { + "distinct_repos": { + "type": "number" + }, + "distinct_secrets": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_providers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "provider": { + "type": "string" + } + }, + "required": [ + "provider", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_types": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "secret_type": { + "type": "string" + } + }, + "required": [ + "secret_type", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "properties": { + "counted_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "era": { + "additionalProperties": false, + "properties": { + "dual": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "legacy": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "modern": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "legacy", + "dual", + "modern", + "unknown", + "not_measured" + ], + "type": "object" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "not_assessed": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_assessed_by_reason": { + "additionalProperties": false, + "properties": { + "bare_challenge_no_prm": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "challenge_unadjudicated": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "cross_origin_pointer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "identified_no_challenge": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "metadata_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_authorization_servers": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_http_answer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_identified_as_mcp": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "resource_mismatch": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "identified_no_challenge", + "resource_mismatch", + "cross_origin_pointer", + "bare_challenge_no_prm", + "pointer_unreachable", + "pointer_invalid", + "no_authorization_servers", + "wellknown_unreachable", + "metadata_invalid", + "challenge_unadjudicated", + "no_http_answer", + "not_identified_as_mcp" + ], + "type": "object" + }, + "own_controls_excluded": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pending_readjudication": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "prm_via": { + "additionalProperties": false, + "properties": { + "header": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_path": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_root": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "header", + "wellknown_path", + "wellknown_root" + ], + "type": "object" + }, + "protected": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "transport": { + "additionalProperties": false, + "properties": { + "legacy_sse": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "streamable_http": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "streamable_http", + "legacy_sse", + "unknown", + "not_measured" + ], + "type": "object" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "withheld_opted_out": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "total", + "protected", + "pending_readjudication", + "not_assessed" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "properties": { + "authentication": { + "additionalProperties": false, + "properties": { + "not_determined": { + "type": "number" + }, + "observed": { + "type": "number" + } + }, + "type": "object" + }, + "confirmed_exposed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "observed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "last_observation": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "country": { + "type": "string" + } + }, + "required": [ + "country", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_issuers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "issuer": { + "type": "string" + } + }, + "required": [ + "issuer", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "trend_30d": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "date": { + "type": "string" + } + }, + "required": [ + "date", + "count" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "poller": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "running": { + "type": "boolean" + } + }, + "required": [ + "running", + "last_run_at" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "exposed_databases": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + }, + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at", + "enabled" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "running": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "last_run_at", + "running" + ], + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "radars": { + "description": "Each radar that could not be read, and why.", + "items": { + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "unexpected_shape" + ], + "type": "string" + }, + "message": { + "type": "string" + }, + "path": { + "type": "string" + }, + "radar": { + "type": "string" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "radar", + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_vendor_advisory1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "known_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_modified_at": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - }, - "withdrawn_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn_reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "vendor_window": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "history_backfill" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." - } - }, - "required": [ - "vendor_window" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "known_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_modified_at": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", + "type": [ + "boolean", + "null" + ] + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_vendor_advisories1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "description": "Whether a free-text search filtered this answer.", - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query.", - "type": [ - "string", - "null" - ] - }, - "total": { - "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "search_match": { - "anyOf": [ - { - "enum": [ - "word", - "substring" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." - }, - "total": { - "description": "The API's total; when total_capped is true, a lower bound, not the count.", - "type": [ - "number", - "null" - ] - }, - "total_capped": { - "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", - "type": [ - "boolean", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." - } - }, - "required": [ - "total", - "total_capped", - "returned", - "limit", - "offset", - "search_applied", - "search_match", - "vendor_windows" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "description": "Whether a free-text search filtered this answer.", + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query.", + "type": [ + "string", + "null" + ] + }, + "total": { + "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
vendor_advisories_for_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, the earliest held dated after 1 January of cve_year, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "cve_year": { - "description": "The year in the CVE ID.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - }, - "vendor_windows": { - "anyOf": [ - { - "items": { - "additionalProperties": false, - "properties": { - "advisories": { - "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", - "type": [ - "number", - "null" - ] - }, - "earliest_vendor_published_at": { - "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", - "type": [ - "string", - "null" - ] - }, - "history_backfill": { - "anyOf": [ - { - "anyOf": [ - { - "enum": [ - "complete", - "in_progress", - "not_started", - "not_supported" - ], - "type": "string" - }, - { - "type": "string" - } - ] - }, - { - "type": "null" - } - ], - "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." - }, - "latest_vendor_published_at": { - "description": "The latest vendor_published_at among them; null when none is held.", - "type": [ - "string", - "null" - ] - }, - "vendor": { - "description": "The vendor slug.", - "type": "string" - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "vendor", - "vendor_display_name", - "advisories", - "earliest_vendor_published_at", - "latest_vendor_published_at", - "history_backfill" - ], - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." - }, - "vendors_not_fully_held": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, the earliest held dated after 1 January of cve_year, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." - } - }, - "required": [ - "returned", - "cap", - "at_cap", - "cve_year", - "vendor_windows", - "vendors_not_fully_held" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. Not where the window begins: see held_since.", + "type": [ + "string", + "null" + ] + }, + "held_since": { + "description": "The start of the window EchelonGraph has read this vendor's advisories from; null when none is held or the API does not say. An advisory this vendor published before it may not be held, even when earliest_vendor_published_at is older.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "held_since", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its held_since may not be held, even when its earliest_vendor_published_at is older, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, held_since after 1 January of cve_year or not known, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
2 tool updates
- Changed
check_sbom1 field changed- changed
Input schema / properties / sbom / descriptionPrevious value: -"a CycloneDX JSON or SPDX JSON document, as JSON text or as an object; its purls are read here and only they are sent"New value: +"a CycloneDX JSON or SPDX JSON document, as JSON text or as an object; its purls are read by this MCP server and only they are sent to the API; over the hosted endpoint (mcp.echelongraph.io) the document is the request body"
- Changed
cve_summary1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "poller": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "cves_ingested": { - "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", - "type": [ - "number", - "null" - ] - }, - "cves_skipped": { - "description": "CVE records this instance's NVD poller skipped since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "http_retries": { - "description": "HTTP retries this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "interval": { - "description": "How often this instance's NVD poller polls.", - "type": [ - "string", - "null" - ] - }, - "last_poll_at": { - "description": "When this instance's NVD poller last polled: never the feed's freshness.", - "type": [ - "string", - "null" - ] - }, - "last_poll_dur_ms": { - "description": "How long that poll took, in milliseconds.", - "type": [ - "number", - "null" - ] - }, - "poll_count": { - "description": "Polls this instance's NVD poller made since the instance last started.", - "type": [ - "number", - "null" - ] - }, - "poll_errors": { - "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so." - }, - "summary": { - "additionalProperties": {}, - "properties": { - "critical": { - "type": [ - "number", - "null" - ] - }, - "high": { - "type": [ - "number", - "null" - ] - }, - "last_updated": { - "type": [ - "string", - "null" - ] - }, - "low": { - "type": [ - "number", - "null" - ] - }, - "medium": { - "type": [ - "number", - "null" - ] - }, - "none": { - "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", - "type": [ - "number", - "null" - ] - }, - "nvd_critical": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_high": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_low": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_medium": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_none": { - "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", - "type": [ - "number", - "null" - ] - }, - "rejected": { - "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "unscored": { - "description": "The same count as none, under its own name.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "poller": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cves_ingested": { + "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", + "type": [ + "number", + "null" + ] + }, + "cves_skipped": { + "description": "CVE records this instance's NVD poller skipped since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "http_retries": { + "description": "HTTP retries this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "interval": { + "description": "How often this instance's NVD poller polls.", + "type": [ + "string", + "null" + ] + }, + "last_poll_at": { + "description": "When this instance's NVD poller last polled: never the feed's freshness.", + "type": [ + "string", + "null" + ] + }, + "last_poll_dur_ms": { + "description": "How long that poll took, in milliseconds.", + "type": [ + "number", + "null" + ] + }, + "poll_count": { + "description": "Polls this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "poll_errors": { + "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so. A poller field the answer sends in a JSON type other than the one described here is left out of data and named in the note, and a poller that is neither a JSON object nor null is left out whole: summary is relayed either way." + }, + "summary": { + "additionalProperties": {}, + "properties": { + "critical": { + "type": [ + "number", + "null" + ] + }, + "high": { + "type": [ + "number", + "null" + ] + }, + "last_updated": { + "type": [ + "string", + "null" + ] + }, + "low": { + "type": [ + "number", + "null" + ] + }, + "medium": { + "type": [ + "number", + "null" + ] + }, + "none": { + "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", + "type": [ + "number", + "null" + ] + }, + "nvd_critical": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_high": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_low": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_medium": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_none": { + "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", + "type": [ + "number", + "null" + ] + }, + "rejected": { + "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "unscored": { + "description": "The same count as none, under its own name.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
6 tool updates
- Changed
check_sbom1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "not_sent_purls": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "batch_size": { - "description": "The most purls one request carries (the API's cap per request).", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches": { - "description": "Requests the distinct purls make, at batch_size each.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "batches_sent": { - "description": "Of those, the ones the API answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "distinct_purls": { - "description": "Distinct purls to check: sent plus not_sent.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "not_sent": { - "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "not_sent_reason": { - "anyOf": [ - { - "enum": [ - "time_budget", - "rate_limited", - "request_failed" - ], - "type": "string" - }, - { - "type": "null" - } - ], - "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." - }, - "partial": { - "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", - "type": [ - "boolean", - "null" - ] - }, - "rate_limit_waits": { - "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "sent": { - "description": "Distinct purls sent and answered.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "waited_ms": { - "description": "Milliseconds spent in those waits.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "distinct_purls", - "batch_size", - "batches", - "batches_sent", - "sent", - "not_sent", - "not_sent_reason", - "rate_limit_waits", - "waited_ms", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, before a batch or while one was unanswered, which is then cut off; or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
exposure_radar1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "distinct_hosts": { - "type": "number" - }, - "engines": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "pci_likely": { - "type": "number" - }, - "pii_likely": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_engines": { - "items": { - "additionalProperties": false, - "properties": { - "engine": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "engine", - "hosts" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "correlations": { - "type": "number" - }, - "distinct_hosts": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "kev_cves_exposed": { - "type": "number" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "newest_kev": { - "items": { - "additionalProperties": false, - "properties": { - "added_date": { - "type": "string" - }, - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "exposed_hosts": { - "type": "number" - }, - "exposure_state": { - "enum": [ - "exposed", - "measured_zero", - "not_assessed" - ], - "type": "string" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - }, - "vuln_name": { - "type": "string" - } - }, - "required": [ - "cve_id", - "exposure_state" - ], - "type": "object" - }, - "type": "array" - }, - "ransomware_cves": { - "type": "number" - }, - "ransomware_hosts": { - "type": "number" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "country": { - "type": "string" - }, - "hosts": { - "type": "number" - } - }, - "required": [ - "country", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_cves": { - "items": { - "additionalProperties": false, - "properties": { - "cve_id": { - "type": "string" - }, - "cvss_v3_score": { - "type": "number" - }, - "epss_score": { - "type": "number" - }, - "hosts": { - "type": "number" - }, - "ransomware": { - "type": "boolean" - }, - "severity": { - "type": "string" - } - }, - "required": [ - "cve_id", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "hosts": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "hosts" - ], - "type": "object" - }, - "type": "array" - }, - "trend": { - "items": { - "additionalProperties": false, - "properties": { - "new_exposures": { - "type": "number" - }, - "week": { - "type": "string" - } - }, - "required": [ - "week", - "new_exposures" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "distinct_repos": { - "type": "number" - }, - "distinct_secrets": { - "type": "number" - }, - "generated_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_providers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "provider": { - "type": "string" - } - }, - "required": [ - "provider", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_types": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "secret_type": { - "type": "string" - } - }, - "required": [ - "secret_type", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - } - }, - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "counted_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "era": { - "additionalProperties": false, - "properties": { - "dual": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "legacy": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "modern": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "legacy", - "dual", - "modern", - "unknown", - "not_measured" - ], - "type": "object" - }, - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "not_assessed": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_assessed_by_reason": { - "additionalProperties": false, - "properties": { - "bare_challenge_no_prm": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "challenge_unadjudicated": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "cross_origin_pointer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "identified_no_challenge": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "metadata_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_authorization_servers": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "no_http_answer": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_identified_as_mcp": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_invalid": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pointer_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "resource_mismatch": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_unreachable": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "identified_no_challenge", - "resource_mismatch", - "cross_origin_pointer", - "bare_challenge_no_prm", - "pointer_unreachable", - "pointer_invalid", - "no_authorization_servers", - "wellknown_unreachable", - "metadata_invalid", - "challenge_unadjudicated", - "no_http_answer", - "not_identified_as_mcp" - ], - "type": "object" - }, - "own_controls_excluded": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "pending_readjudication": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "prm_via": { - "additionalProperties": false, - "properties": { - "header": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_path": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "wellknown_root": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "header", - "wellknown_path", - "wellknown_root" - ], - "type": "object" - }, - "protected": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "total": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "transport": { - "additionalProperties": false, - "properties": { - "legacy_sse": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "not_measured": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "streamable_http": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "unknown": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "streamable_http", - "legacy_sse", - "unknown", - "not_measured" - ], - "type": "object" - }, - "window": { - "additionalProperties": false, - "properties": { - "from": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "to": { - "description": "An RFC 3339 instant.", - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - } - }, - "required": [ - "total", - "protected", - "pending_readjudication", - "not_assessed" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "authentication": { - "additionalProperties": false, - "properties": { - "not_determined": { - "type": "number" - }, - "observed": { - "type": "number" - } - }, - "type": "object" - }, - "confirmed_exposed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "total": { - "type": "number" - } - }, - "type": "object" - }, - "observed": { - "additionalProperties": false, - "properties": { - "by_category": { - "additionalProperties": { - "type": "number" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "last_24h": { - "type": "number" - }, - "last_observation": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "top_countries": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "country": { - "type": "string" - } - }, - "required": [ - "country", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_issuers": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "issuer": { - "type": "string" - } - }, - "required": [ - "issuer", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "top_products": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "product": { - "type": "string" - } - }, - "required": [ - "product", - "count" - ], - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "number" - }, - "trend_30d": { - "items": { - "additionalProperties": false, - "properties": { - "count": { - "type": "number" - }, - "date": { - "type": "string" - } - }, - "required": [ - "date", - "count" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "poller": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "description": "An RFC 3339 instant.", - "type": "string" - }, - "running": { - "type": "boolean" - } - }, - "required": [ - "running", - "last_run_at" - ], - "type": "object" - } - }, - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - "freshness": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "exposed_databases": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "kev_exposure": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "leaked_credentials": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at" - ], - "type": "object" - }, - "mcp_servers": { - "additionalProperties": false, - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "last_run_at", - "enabled" - ], - "type": "object" - }, - "shadow_ai": { - "additionalProperties": false, - "properties": { - "last_run_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ] - }, - "running": { - "type": [ - "boolean", - "null" - ] - } - }, - "required": [ - "last_run_at", - "running" - ], - "type": "object" - } - }, - "required": [ - "kev_exposure", - "exposed_databases", - "leaked_credentials", - "shadow_ai", - "mcp_servers" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The producing radar's last completed check (last_run_at), where the API serves one." - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "answered": { - "description": "The radars that answered. On a failure their answers are withheld.", - "items": { - "type": "string" - }, - "type": "array" - }, - "failed": { - "description": "The radars that could not be read.", - "items": { - "type": "string" - }, - "type": "array" - }, - "radars": { - "description": "The radars this tool reads.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "radars", - "answered", - "failed" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "radars": { - "description": "Each radar that could not be read, and why.", - "items": { - "additionalProperties": false, - "properties": { - "kind": { - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "unexpected_shape" - ], - "type": "string" - }, - "message": { - "type": "string" - }, - "path": { - "type": "string" - }, - "radar": { - "type": "string" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "radar", - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "type": "array" - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": false, + "properties": { + "exposed_databases": { + "additionalProperties": false, + "properties": { + "distinct_hosts": { + "type": "number" + }, + "engines": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "pci_likely": { + "type": "number" + }, + "pii_likely": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_engines": { + "items": { + "additionalProperties": false, + "properties": { + "engine": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "engine", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "properties": { + "correlations": { + "type": "number" + }, + "distinct_hosts": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "kev_cves_exposed": { + "type": "number" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "newest_kev": { + "items": { + "additionalProperties": false, + "properties": { + "added_date": { + "type": "string" + }, + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "exposed_hosts": { + "type": "number" + }, + "exposure_state": { + "enum": [ + "exposed", + "measured_zero", + "not_assessed" + ], + "type": "string" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + }, + "vuln_name": { + "type": "string" + } + }, + "required": [ + "cve_id", + "exposure_state" + ], + "type": "object" + }, + "type": "array" + }, + "ransomware_cves": { + "type": "number" + }, + "ransomware_hosts": { + "type": "number" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "country": { + "type": "string" + }, + "hosts": { + "type": "number" + } + }, + "required": [ + "country", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_cves": { + "items": { + "additionalProperties": false, + "properties": { + "cve_id": { + "type": "string" + }, + "cvss_v3_score": { + "type": "number" + }, + "epss_score": { + "type": "number" + }, + "hosts": { + "type": "number" + }, + "ransomware": { + "type": "boolean" + }, + "severity": { + "type": "string" + } + }, + "required": [ + "cve_id", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "hosts": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "hosts" + ], + "type": "object" + }, + "type": "array" + }, + "trend": { + "items": { + "additionalProperties": false, + "properties": { + "new_exposures": { + "type": "number" + }, + "week": { + "type": "string" + } + }, + "required": [ + "week", + "new_exposures" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "properties": { + "distinct_repos": { + "type": "number" + }, + "distinct_secrets": { + "type": "number" + }, + "generated_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_providers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "provider": { + "type": "string" + } + }, + "required": [ + "provider", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_types": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "secret_type": { + "type": "string" + } + }, + "required": [ + "secret_type", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "properties": { + "counted_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "era": { + "additionalProperties": false, + "properties": { + "dual": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "legacy": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "modern": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "legacy", + "dual", + "modern", + "unknown", + "not_measured" + ], + "type": "object" + }, + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "not_assessed": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_assessed_by_reason": { + "additionalProperties": false, + "properties": { + "bare_challenge_no_prm": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "challenge_unadjudicated": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "cross_origin_pointer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "identified_no_challenge": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "metadata_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_authorization_servers": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "no_http_answer": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_identified_as_mcp": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_invalid": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pointer_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "resource_mismatch": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_unreachable": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "identified_no_challenge", + "resource_mismatch", + "cross_origin_pointer", + "bare_challenge_no_prm", + "pointer_unreachable", + "pointer_invalid", + "no_authorization_servers", + "wellknown_unreachable", + "metadata_invalid", + "challenge_unadjudicated", + "no_http_answer", + "not_identified_as_mcp" + ], + "type": "object" + }, + "own_controls_excluded": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "pending_readjudication": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "prm_via": { + "additionalProperties": false, + "properties": { + "header": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_path": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "wellknown_root": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "header", + "wellknown_path", + "wellknown_root" + ], + "type": "object" + }, + "protected": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "total": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "transport": { + "additionalProperties": false, + "properties": { + "legacy_sse": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "not_measured": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "streamable_http": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unknown": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "streamable_http", + "legacy_sse", + "unknown", + "not_measured" + ], + "type": "object" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "required": [ + "total", + "protected", + "pending_readjudication", + "not_assessed" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "properties": { + "authentication": { + "additionalProperties": false, + "properties": { + "not_determined": { + "type": "number" + }, + "observed": { + "type": "number" + } + }, + "type": "object" + }, + "confirmed_exposed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "total": { + "type": "number" + }, + "window": { + "additionalProperties": false, + "properties": { + "from": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "to": { + "description": "An RFC 3339 instant.", + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + } + }, + "type": "object" + }, + "observed": { + "additionalProperties": false, + "properties": { + "by_category": { + "additionalProperties": { + "type": "number" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "last_24h": { + "type": "number" + }, + "last_observation": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "top_countries": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "country": { + "type": "string" + } + }, + "required": [ + "country", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_issuers": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "issuer": { + "type": "string" + } + }, + "required": [ + "issuer", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "top_products": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "product": { + "type": "string" + } + }, + "required": [ + "product", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "number" + }, + "trend_30d": { + "items": { + "additionalProperties": false, + "properties": { + "count": { + "type": "number" + }, + "date": { + "type": "string" + } + }, + "required": [ + "date", + "count" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "poller": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "description": "An RFC 3339 instant.", + "type": "string" + }, + "running": { + "type": "boolean" + } + }, + "required": [ + "running", + "last_run_at" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + "freshness": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "exposed_databases": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "kev_exposure": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "leaked_credentials": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at" + ], + "type": "object" + }, + "mcp_servers": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + }, + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "last_run_at", + "enabled" + ], + "type": "object" + }, + "shadow_ai": { + "additionalProperties": false, + "properties": { + "last_run_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "running": { + "type": [ + "boolean", + "null" + ] + } + }, + "required": [ + "last_run_at", + "running" + ], + "type": "object" + } + }, + "required": [ + "kev_exposure", + "exposed_databases", + "leaked_credentials", + "shadow_ai", + "mcp_servers" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The producing radar's last completed check (last_run_at), where the API serves one." + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "answered": { + "description": "The radars that answered. On a failure their answers are withheld.", + "items": { + "type": "string" + }, + "type": "array" + }, + "failed": { + "description": "The radars that could not be read.", + "items": { + "type": "string" + }, + "type": "array" + }, + "radars": { + "description": "The radars this tool reads.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "radars", + "answered", + "failed" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "radars": { + "description": "Each radar that could not be read, and why.", + "items": { + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "unexpected_shape" + ], + "type": "string" + }, + "message": { + "type": "string" + }, + "path": { + "type": "string" + }, + "radar": { + "type": "string" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "radar", + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
get_vendor_advisory1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "known_cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "references": {}, - "remediation": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_modified_at": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - }, - "withdrawn_at": { - "type": [ - "string", - "null" - ] - }, - "withdrawn_reason": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "known_cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The CVE IDs of cve_ids that have a record in EchelonGraph's CVE feed." + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "references": {}, + "remediation": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_modified_at": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", + "type": [ + "boolean", + "null" + ] + }, + "withdrawn_at": { + "type": [ + "string", + "null" + ] + }, + "withdrawn_reason": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "vendor_window": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "history_backfill" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "This advisory's vendor's window in what EchelonGraph holds; null when the windows could not be read or carry none for this vendor." + } + }, + "required": [ + "vendor_window" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
search_cves1 field changed- added
Input schema / properties / offsetAdded value: +{ + "description": "rows to skip (default 0)", + "maximum": 10000, + "minimum": 0, + "type": "integer" +}
- Changed
search_vendor_advisories2 fields changed- changed
Input schema / properties / query / descriptionPrevious value: -"free text, at most 100 bytes: a product, an advisory ID, a CVE ID or a keyword, e.g. 'exchange server'"New value: +"free text, at most 100 bytes: a product, an advisory ID, a CVE ID or a keyword, e.g. 'exchange server'; 1 or 2 characters match whole words only" - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "limit", - "offset", - "search_applied" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "description": "Whether a free-text search filtered this answer.", - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "limit": { - "type": [ - "number", - "null" - ] - }, - "offset": { - "type": [ - "number", - "null" - ] - }, - "returned": { - "type": [ - "number", - "null" - ] - }, - "search_applied": { - "type": [ - "boolean", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "total", - "returned", - "limit", - "offset", - "search_applied" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "description": "Whether a free-text search filtered this answer.", + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "description": "How the query was matched: word (a query of 1 or 2 characters, whole words only) or substring; null without a query.", + "type": [ + "string", + "null" + ] + }, + "total": { + "description": "The matches; when total_capped is true, a lower bound: 1,000 or more.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: the search stopped counting at total, so total is a lower bound (1,000+), not the count.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "limit": { + "type": [ + "number", + "null" + ] + }, + "offset": { + "type": [ + "number", + "null" + ] + }, + "returned": { + "type": [ + "number", + "null" + ] + }, + "search_applied": { + "type": [ + "boolean", + "null" + ] + }, + "search_match": { + "anyOf": [ + { + "enum": [ + "word", + "substring" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "word: a query of 1 or 2 characters, matched as a whole word only; substring: a longer query; null without a query." + }, + "total": { + "description": "The API's total; when total_capped is true, a lower bound, not the count.", + "type": [ + "number", + "null" + ] + }, + "total_capped": { + "description": "true: total is the API's cap on a search's count, so 1,000 or more match.", + "type": [ + "boolean", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." + } + }, + "required": [ + "total", + "total_capped", + "returned", + "limit", + "offset", + "search_applied", + "search_match", + "vendor_windows" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
vendor_advisories_for_cve1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "returned", - "cap", - "at_cap" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "advisories": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "advisory_id": { - "type": [ - "string", - "null" - ] - }, - "affected_products": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cvss_v3_score": { - "type": [ - "number", - "null" - ] - }, - "our_first_seen_at": { - "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "summary": { - "type": [ - "string", - "null" - ] - }, - "title": { - "type": [ - "string", - "null" - ] - }, - "vendor": { - "type": [ - "string", - "null" - ] - }, - "vendor_advisory_id": { - "type": [ - "string", - "null" - ] - }, - "vendor_display_name": { - "type": [ - "string", - "null" - ] - }, - "vendor_published_at": { - "description": "The date the vendor gives for the advisory.", - "type": [ - "string", - "null" - ] - }, - "withdrawn": { - "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", - "type": [ - "boolean", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "cve_id": { - "type": [ - "string", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "at_cap": { - "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", - "type": [ - "boolean", - "null" - ] - }, - "cap": { - "description": "The most the API returns for one CVE, newest first.", - "type": "number" - }, - "returned": { - "description": "The advisories in this answer.", - "type": [ - "number", - "null" - ] - } - }, - "required": [ - "returned", - "cap", - "at_cap" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, the earliest held dated after 1 January of cve_year, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "advisories": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "advisory_id": { + "type": [ + "string", + "null" + ] + }, + "affected_products": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cvss_v3_score": { + "type": [ + "number", + "null" + ] + }, + "our_first_seen_at": { + "description": "When EchelonGraph first recorded the advisory; not the vendor's date.", + "type": [ + "string", + "null" + ] + }, + "severity": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "vendor": { + "type": [ + "string", + "null" + ] + }, + "vendor_advisory_id": { + "type": [ + "string", + "null" + ] + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + }, + "vendor_published_at": { + "description": "The date the vendor gives for the advisory.", + "type": [ + "string", + "null" + ] + }, + "withdrawn": { + "description": "true: the vendor withdrew (rescinded) this advisory; report it as withdrawn.", + "type": [ + "boolean", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "cve_id": { + "type": [ + "string", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "at_cap": { + "description": "true: the answer is full, so the vendor feeds may hold more advisories for this CVE than it lists.", + "type": [ + "boolean", + "null" + ] + }, + "cap": { + "description": "The most the API returns for one CVE, newest first.", + "type": "number" + }, + "cve_year": { + "description": "The year in the CVE ID.", + "type": "number" + }, + "returned": { + "description": "The advisories in this answer.", + "type": [ + "number", + "null" + ] + }, + "vendor_windows": { + "anyOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "advisories": { + "description": "How many advisories EchelonGraph holds from this vendor, withdrawn ones not counted.", + "type": [ + "number", + "null" + ] + }, + "earliest_vendor_published_at": { + "description": "The earliest vendor_published_at among them; null when none is held. An advisory this vendor published before it is not held.", + "type": [ + "string", + "null" + ] + }, + "history_backfill": { + "anyOf": [ + { + "anyOf": [ + { + "enum": [ + "complete", + "in_progress", + "not_started", + "not_supported" + ], + "type": "string" + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ], + "description": "history_backfill: complete (the vendor's published history has been read back as far as its source goes), in_progress or not_started (it is still being read, so the vendor's older advisories are not all held yet), or not_supported (EchelonGraph has no history read for that vendor, so what it holds is what the vendor's feed has carried)." + }, + "latest_vendor_published_at": { + "description": "The latest vendor_published_at among them; null when none is held.", + "type": [ + "string", + "null" + ] + }, + "vendor": { + "description": "The vendor slug.", + "type": "string" + }, + "vendor_display_name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "vendor", + "vendor_display_name", + "advisories", + "earliest_vendor_published_at", + "latest_vendor_published_at", + "history_backfill" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Each vendor's window in what EchelonGraph holds; null when the windows could not be read. An advisory a vendor published before its earliest_vendor_published_at is not held, so no advisory from a vendor is not a finding that it published none." + }, + "vendors_not_fully_held": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The vendors with no advisory in this answer that may have published one EchelonGraph does not hold: none held, the earliest held dated after 1 January of cve_year, or history_backfill in_progress or not_started. No advisory from them is not a finding that they published none. null when the windows could not be read." + } + }, + "required": [ + "returned", + "cap", + "at_cap", + "cve_year", + "vendor_windows", + "vendors_not_fully_held" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
2 tool updates
- Changed
cve_summary1 field changed- changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "description": "What the answer covers; null where the answer says nothing about it.", - "type": "null" - }, - "data": { - "additionalProperties": {}, - "properties": { - "summary": { - "additionalProperties": {}, - "properties": { - "critical": { - "type": [ - "number", - "null" - ] - }, - "high": { - "type": [ - "number", - "null" - ] - }, - "last_updated": { - "type": [ - "string", - "null" - ] - }, - "low": { - "type": [ - "number", - "null" - ] - }, - "medium": { - "type": [ - "number", - "null" - ] - }, - "none": { - "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", - "type": [ - "number", - "null" - ] - }, - "nvd_critical": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_high": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_low": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_medium": { - "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", - "type": [ - "number", - "null" - ] - }, - "nvd_none": { - "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", - "type": [ - "number", - "null" - ] - }, - "rejected": { - "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", - "type": [ - "number", - "null" - ] - }, - "total": { - "type": [ - "number", - "null" - ] - }, - "unscored": { - "description": "The same count as none, under its own name.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "type": "null" - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "description": "What the answer covers; null where the answer says nothing about it.", + "type": "null" + }, + "data": { + "additionalProperties": {}, + "properties": { + "poller": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "cves_ingested": { + "description": "CVE records this instance's NVD poller wrote since the instance last started: never the feed's size or intake.", + "type": [ + "number", + "null" + ] + }, + "cves_skipped": { + "description": "CVE records this instance's NVD poller skipped since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "http_retries": { + "description": "HTTP retries this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "interval": { + "description": "How often this instance's NVD poller polls.", + "type": [ + "string", + "null" + ] + }, + "last_poll_at": { + "description": "When this instance's NVD poller last polled: never the feed's freshness.", + "type": [ + "string", + "null" + ] + }, + "last_poll_dur_ms": { + "description": "How long that poll took, in milliseconds.", + "type": [ + "number", + "null" + ] + }, + "poll_count": { + "description": "Polls this instance's NVD poller made since the instance last started.", + "type": [ + "number", + "null" + ] + }, + "poll_errors": { + "description": "Polls of this instance's NVD poller that failed since the instance last started: never the feed's reliability.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "poller holds the in-memory counters of the NVD poller of the one API instance that answered (cves_ingested, cves_skipped, http_retries, poll_count, poll_errors, last_poll_at, last_poll_dur_ms, interval), counted since that instance last started and zeroed on every restart: they describe that instance, never the feed's size, intake, reliability or freshness. Whenever the answer carries poller the note says so." + }, + "summary": { + "additionalProperties": {}, + "properties": { + "critical": { + "type": [ + "number", + "null" + ] + }, + "high": { + "type": [ + "number", + "null" + ] + }, + "last_updated": { + "type": [ + "string", + "null" + ] + }, + "low": { + "type": [ + "number", + "null" + ] + }, + "medium": { + "type": [ + "number", + "null" + ] + }, + "none": { + "description": "The active CVEs with no severity band from any source: CVEs not yet scored, not a severity rating of None.", + "type": [ + "number", + "null" + ] + }, + "nvd_critical": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Critical: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_high": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is High: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_low": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Low: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_medium": { + "description": "Of the active CVEs total counts, those whose NVD CVSS severity label is Medium: NVD's label, as provenance, never EchelonGraph's severity band.", + "type": [ + "number", + "null" + ] + }, + "nvd_none": { + "description": "Of the active CVEs total counts, those with no Critical, High, Medium or Low NVD CVSS severity label, many of them with an NVD CVSS v2 score instead: neither a count of CVEs rated None nor the count of CVEs with no severity, which is none.", + "type": [ + "number", + "null" + ] + }, + "rejected": { + "description": "The CVE records rejected (withdrawn) by their numbering authority, which total and every other count here leave out: withdrawn records, never vulnerabilities.", + "type": [ + "number", + "null" + ] + }, + "total": { + "type": [ + "number", + "null" + ] + }, + "unscored": { + "description": "The same count as none, under its own name.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "type": "null" + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
kev_recent2 fields changed- changed
Input schema / properties / since / descriptionPrevious value: -"earliest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as its UTC date)"New value: +"earliest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it)" - changed
Input schema / properties / until / descriptionPrevious value: -"latest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as its UTC date)"New value: +"latest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as the date written in it)"
2 tool updates
- Changed
check_sbom2 fields changed- changed
Input schema / properties / purls / descriptionPrevious value: -"package URLs to check, e.g. pkg:npm/lodash@4.17.20 or pkg:deb/debian/openssl@3.0.11-1~deb12u1?distro=debian-12 (up to 200)"New value: +"package URLs to check, e.g. pkg:npm/lodash@4.17.20 or pkg:deb/debian/openssl@3.0.11-1~deb12u1?distro=debian-12 (up to 2,000 distinct, sent in batches of 200)" - changed
Output schema / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "partial": { - "description": "The answer's summary.partial: true when the time budget ran out first.", - "type": [ - "boolean", - "null" - ] - }, - "sent": { - "description": "Distinct purls sent and checked.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "sent", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "description": "What the answer covers; null where the answer says nothing about it." - }, - "data": { - "additionalProperties": {}, - "properties": { - "answered_at": { - "type": [ - "string", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "match_layer": { - "type": [ - "string", - "null" - ] - }, - "results": { - "items": { - "additionalProperties": {}, - "properties": { - "advisories_considered": { - "type": [ - "number", - "null" - ] - }, - "assessed": { - "description": "Whether the matcher produced a verdict for this component. false is never clean.", - "type": [ - "boolean", - "null" - ] - }, - "candidates_capped": { - "type": [ - "boolean", - "null" - ] - }, - "capped": { - "type": [ - "boolean", - "null" - ] - }, - "code": { - "type": [ - "string", - "null" - ] - }, - "count": { - "type": [ - "number", - "null" - ] - }, - "cve_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "ecosystem": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": [ - "number", - "null" - ] - }, - "input_kind": { - "type": [ - "string", - "null" - ] - }, - "matches": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "not_affected_count": { - "type": [ - "number", - "null" - ] - }, - "not_assessed_reason": { - "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", - "type": [ - "string", - "null" - ] - }, - "package": { - "type": [ - "string", - "null" - ] - }, - "purl": { - "type": [ - "string", - "null" - ] - }, - "undetermined": { - "anyOf": [ - { - "items": { - "additionalProperties": {}, - "properties": { - "cve_id": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "undetermined_count": { - "type": [ - "number", - "null" - ] - }, - "verdict": { - "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", - "type": [ - "string", - "null" - ] - }, - "version": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "summary": { - "additionalProperties": {}, - "properties": { - "affected": { - "type": [ - "number", - "null" - ] - }, - "components": { - "type": [ - "number", - "null" - ] - }, - "corpus_cache_max_age_ms": { - "type": [ - "number", - "null" - ] - }, - "elapsed_ms": { - "type": [ - "number", - "null" - ] - }, - "lookups": { - "type": [ - "number", - "null" - ] - }, - "not_affected": { - "description": "Components with a decided, clean verdict.", - "type": [ - "number", - "null" - ] - }, - "not_assessed": { - "description": "Components with no verdict: not clean.", - "type": [ - "number", - "null" - ] - }, - "not_assessed_by_reason": { - "anyOf": [ - { - "additionalProperties": {}, - "properties": { - "advisory_lookup_failed": { - "type": "number" - }, - "candidate_window_truncated": { - "type": "number" - }, - "distro_release_unknown": { - "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", - "type": "number" - }, - "invalid_component": { - "type": "number" - }, - "no_decidable_advisory": { - "type": "number" - }, - "package_not_in_advisory_corpus": { - "type": "number" - }, - "purl_type_unsupported": { - "type": "number" - }, - "time_budget": { - "description": "Components the batch's time budget ran out before: not clean; check them again.", - "type": "number" - }, - "version_missing": { - "type": "number" - } - }, - "type": "object" - }, - { - "type": "null" - } - ], - "description": "The not_assessed components, counted by not_assessed_reason." - }, - "partial": { - "description": "true when the time budget ran out before every component was looked up.", - "type": [ - "boolean", - "null" - ] - }, - "time_budget_ms": { - "type": [ - "number", - "null" - ] - }, - "undetermined": { - "description": "Components whose advisories could not all be decided and none matched: not clean.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "type": "object" - }, - "freshness": { - "description": "The producing radar's last completed check (last_run_at), where the API serves one.", - "type": "null" - }, - "measured_at": { - "anyOf": [ - { - "description": "An RFC 3339 instant.", - "type": "string" - }, - { - "type": "null" - } - ], - "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." - }, - "method": { - "description": "How the numbers were produced.", - "type": "string" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", - "enum": [ - "measured", - "not_assessed" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "data" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "coverage": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "components_in_document": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." - }, - "duplicates_removed": { - "description": "Purls that appeared more than once and were sent once.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "input": { - "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", - "enum": [ - "purls", - "cyclonedx", - "spdx" - ], - "type": "string" - }, - "not_assessed": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "Of those sent, the components with no verdict, as the answer counts them." - }, - "partial": { - "description": "The answer's summary.partial: true when the time budget ran out first.", - "type": [ - "boolean", - "null" - ] - }, - "sent": { - "description": "Distinct purls sent and checked.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "with_purl": { - "description": "Of those, the ones carrying a purl.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "without_purl": { - "description": "The ones without a purl: not checked, and not clean.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - } - }, - "required": [ - "input", - "components_in_document", - "with_purl", - "without_purl", - "duplicates_removed", - "sent", - "not_assessed", - "partial" - ], - "type": "object" - }, - { - "type": "null" - } - ] - }, - "error": { - "additionalProperties": false, - "properties": { - "kind": { - "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", - "enum": [ - "network", - "timeout", - "http", - "not_json", - "not_object", - "invalid_input", - "internal", - "unexpected_shape", - "radars" - ], - "type": "string" - }, - "message": { - "description": "The cause: the API's own message, or what went wrong.", - "type": "string" - }, - "path": { - "description": "The API path requested, when a request was made.", - "type": [ - "string", - "null" - ] - }, - "status": { - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The HTTP status, when the API answered one." - } - }, - "required": [ - "kind", - "path", - "status", - "message" - ], - "type": "object" - }, - "freshness": { - "type": "null" - }, - "measured_at": { - "type": "null" - }, - "method": { - "type": "null" - }, - "notes": { - "description": "Caveats, one sentence each.", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", - "enum": [ - "failed", - "invalid_input" - ], - "type": "string" - } - }, - "required": [ - "state", - "measured_at", - "method", - "coverage", - "freshness", - "notes", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "What the answer covers; null where the answer says nothing about it." + }, + "data": { + "additionalProperties": {}, + "properties": { + "answered_at": { + "type": [ + "string", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "match_layer": { + "type": [ + "string", + "null" + ] + }, + "not_sent_purls": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The distinct purls not sent (coverage.not_sent_reason says why): not checked, and not clean. Present only when some were not sent." + }, + "results": { + "items": { + "additionalProperties": {}, + "properties": { + "advisories_considered": { + "type": [ + "number", + "null" + ] + }, + "assessed": { + "description": "Whether the matcher produced a verdict for this component. false is never clean.", + "type": [ + "boolean", + "null" + ] + }, + "candidates_capped": { + "type": [ + "boolean", + "null" + ] + }, + "capped": { + "type": [ + "boolean", + "null" + ] + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "count": { + "type": [ + "number", + "null" + ] + }, + "cve_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ecosystem": { + "type": [ + "string", + "null" + ] + }, + "error": { + "type": [ + "string", + "null" + ] + }, + "index": { + "type": [ + "number", + "null" + ] + }, + "input_kind": { + "type": [ + "string", + "null" + ] + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "not_affected_count": { + "type": [ + "number", + "null" + ] + }, + "not_assessed_reason": { + "description": "Why assessed is false: package_not_in_advisory_corpus, no_decidable_advisory, advisory_lookup_failed, candidate_window_truncated, time_budget, distro_release_unknown, purl_type_unsupported, version_missing or invalid_component.", + "type": [ + "string", + "null" + ] + }, + "package": { + "type": [ + "string", + "null" + ] + }, + "purl": { + "type": [ + "string", + "null" + ] + }, + "undetermined": { + "anyOf": [ + { + "items": { + "additionalProperties": {}, + "properties": { + "cve_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "undetermined_count": { + "type": [ + "number", + "null" + ] + }, + "verdict": { + "description": "affected (count > 0); not_affected (assessed, no match, nothing undetermined: the only clean verdict); undetermined (advisories name the package, at least one could not be decided, none matched: not clean); not_assessed (no verdict: not clean).", + "type": [ + "string", + "null" + ] + }, + "version": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "summary": { + "additionalProperties": {}, + "properties": { + "affected": { + "type": [ + "number", + "null" + ] + }, + "components": { + "type": [ + "number", + "null" + ] + }, + "corpus_cache_max_age_ms": { + "type": [ + "number", + "null" + ] + }, + "elapsed_ms": { + "type": [ + "number", + "null" + ] + }, + "lookups": { + "type": [ + "number", + "null" + ] + }, + "not_affected": { + "description": "Components with a decided, clean verdict.", + "type": [ + "number", + "null" + ] + }, + "not_assessed": { + "description": "Components with no verdict: not clean.", + "type": [ + "number", + "null" + ] + }, + "not_assessed_by_reason": { + "anyOf": [ + { + "additionalProperties": {}, + "properties": { + "advisory_lookup_failed": { + "type": "number" + }, + "candidate_window_truncated": { + "type": "number" + }, + "distro_release_unknown": { + "description": "deb, apk or rpm purls without a distro qualifier naming the release, which EchelonGraph does not guess.", + "type": "number" + }, + "invalid_component": { + "type": "number" + }, + "no_decidable_advisory": { + "type": "number" + }, + "package_not_in_advisory_corpus": { + "type": "number" + }, + "purl_type_unsupported": { + "type": "number" + }, + "time_budget": { + "description": "Components the batch's time budget ran out before: not clean; check them again.", + "type": "number" + }, + "version_missing": { + "type": "number" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The not_assessed components, counted by not_assessed_reason." + }, + "partial": { + "description": "true when the time budget ran out before every component was looked up.", + "type": [ + "boolean", + "null" + ] + }, + "time_budget_ms": { + "type": [ + "number", + "null" + ] + }, + "undetermined": { + "description": "Components whose advisories could not all be decided and none matched: not clean.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "freshness": { + "description": "The producing radar's last completed check (last_run_at), where the API serves one.", + "type": "null" + }, + "measured_at": { + "anyOf": [ + { + "description": "An RFC 3339 instant.", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "When the underlying observation was made, as the API states it; null when the answer does not say or holds no observation." + }, + "method": { + "description": "How the numbers were produced.", + "type": "string" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "measured: a measurement of what was asked; an exposure count is measured only with measured_at and method. not_assessed: the answer holds no dated measurement of what was asked, so no count in it is presented as one; it can still relay a count, as what the source holds on record, undated, and its notes (and exposure_state, where the result carries it) say what each count is.", + "enum": [ + "measured", + "not_assessed" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "coverage": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "batch_size": { + "description": "The most purls one request carries (the API's cap per request).", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches": { + "description": "Requests the distinct purls make, at batch_size each.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "batches_sent": { + "description": "Of those, the ones the API answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "components_in_document": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Components (CycloneDX) or packages (SPDX) in the document; null for a purl list." + }, + "distinct_purls": { + "description": "Distinct purls to check: sent plus not_sent.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "duplicates_removed": { + "description": "Purls that appeared more than once and were sent once.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "input": { + "description": "What was passed: a purl list, a CycloneDX JSON document or an SPDX JSON document.", + "enum": [ + "purls", + "cyclonedx", + "spdx" + ], + "type": "string" + }, + "not_assessed": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "Of those sent, the components with no verdict, as the answer counts them." + }, + "not_sent": { + "description": "Distinct purls not sent, listed in data.not_sent_purls: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "not_sent_reason": { + "anyOf": [ + { + "enum": [ + "time_budget", + "rate_limited", + "request_failed" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Why not_sent is above 0: time_budget (the call's 50 s budget ran out, or waiting out the API's Retry-After would pass it), rate_limited (a 429 without Retry-After, or a 429 after 10 waits), request_failed (a batch after the first failed; the note quotes how). null when every purl was sent." + }, + "partial": { + "description": "true when not every purl was sent (not_sent above 0) or any batch's summary.partial was true (its time budget ran out first); otherwise the answer's summary.partial.", + "type": [ + "boolean", + "null" + ] + }, + "rate_limit_waits": { + "description": "How many times the API answered 429 and the tool waited its Retry-After before sending the batch again.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "sent": { + "description": "Distinct purls sent and answered.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "waited_ms": { + "description": "Milliseconds spent in those waits.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "with_purl": { + "description": "Of those, the ones carrying a purl.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "without_purl": { + "description": "The ones without a purl: not checked, and not clean.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + } + }, + "required": [ + "input", + "components_in_document", + "with_purl", + "without_purl", + "duplicates_removed", + "distinct_purls", + "batch_size", + "batches", + "batches_sent", + "sent", + "not_sent", + "not_sent_reason", + "rate_limit_waits", + "waited_ms", + "not_assessed", + "partial" + ], + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error": { + "additionalProperties": false, + "properties": { + "kind": { + "description": "What failed: the request (network, timeout), the answer (http, not_json, not_object, unexpected_shape), the input, or this server.", + "enum": [ + "network", + "timeout", + "http", + "not_json", + "not_object", + "invalid_input", + "internal", + "unexpected_shape", + "radars" + ], + "type": "string" + }, + "message": { + "description": "The cause: the API's own message, or what went wrong.", + "type": "string" + }, + "path": { + "description": "The API path requested, when a request was made.", + "type": [ + "string", + "null" + ] + }, + "status": { + "anyOf": [ + { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + { + "type": "null" + } + ], + "description": "The HTTP status, when the API answered one." + } + }, + "required": [ + "kind", + "path", + "status", + "message" + ], + "type": "object" + }, + "freshness": { + "type": "null" + }, + "measured_at": { + "type": "null" + }, + "method": { + "type": "null" + }, + "notes": { + "description": "Caveats, one sentence each.", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "failed: the lookup did not complete. invalid_input: the input was refused, so nothing was looked up. Neither is a finding.", + "enum": [ + "failed", + "invalid_input" + ], + "type": "string" + } + }, + "required": [ + "state", + "measured_at", + "method", + "coverage", + "freshness", + "notes", + "error" + ], + "type": "object" + } +]
- Changed
kev_recent2 fields changed- changed
Input schema / properties / since / descriptionPrevious value: -"earliest kev_added_date to include, YYYY-MM-DD"New value: +"earliest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as its UTC date)" - changed
Input schema / properties / until / descriptionPrevious value: -"latest kev_added_date to include, YYYY-MM-DD"New value: +"latest kev_added_date to include, YYYY-MM-DD (an RFC 3339 timestamp is read as its UTC date)"
14 tool updates
- First observed
check_affected - First observed
check_sbom - First observed
cve_exposure - First observed
cve_intel - First observed
cve_summary - First observed
epss_history - First observed
exposure_radar - First observed
get_cve - First observed
get_cwe - First observed
get_vendor_advisory - First observed
kev_recent - First observed
search_cves - First observed
search_vendor_advisories - First observed
vendor_advisories_for_cve
Related MCP Connectors
Threat intel + your scans/findings/Shield posture. CVE, EPSS, KEV, package vuln lookup, DAST.
Is a CVE exploited? CISA KEV, FIRST EPSS, CVSS and SSVC with a patch-first verdict. Free, no key.
Look up CVEs, CISA KEV, EPSS and open-source package vulnerabilities, including malicious packages.
CVE intelligence: exploitation (KEV/EPSS), detection coverage, fixed versions, CPE configurations.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceProvides keyless, read-only access to CISA KEV, SSVC, and full ICS advisory corpus, letting users check CVE statuses, compute BOD 26-04 remediation timelines, and search advisories by vendor, product, CVE, CVSS, or sector.91 npm1Apache 2.0
- AlicenseAqualityBmaintenanceChecks public IPs, domains, CVE IDs and software versions for confirmed vulnerabilities and exposure, using NVD version ranges, CISA KEV, EPSS, distro backports and published exploits. All API keys are optional.16MIT
- AlicenseNot gradedqualityBmaintenanceEnables vulnerability lookup and triage across NVD, EPSS, CISA KEV, OSV, and many other sources, while tracking an estate's exposure changes from SBOMs and lockfiles through snapshots and prioritized diffs.Apache 2.0
- AlicenseNot gradedqualityDmaintenanceProvides CVE lookup, search, and exploit intelligence from public vulnerability sources (NVD, CISA KEV, EPSS) for AI agents to produce remediation guidance without consuming LLM tokens for data fetching.1MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.