Repository navigation
Releases: nlink-jp/cve-lookup
Releases · nlink-jp/cve-lookup
Release list
v0.1.3
get --raw is now described as upstream's own document rather than its bytes: terminal-obeyed characters are escaped, a carriage return between tokens becomes a newline, and a cached copy is compacted with <, > and & escaped. Output is unchanged. See CHANGELOG.md.
v0.1.2
Fixed
get --rawcould let an upstream document overwrite the lines already
printed. A carriage return is legal whitespace between JSON tokens and an
instruction to a terminal — it returns the cursor to the start of the line.
It cannot be escaped there (between tokens an escape is not valid JSON), so a
CRLF now loses the carriage return and a lone one becomes a newline. The
document a parser sees is unchanged.
v0.1.1
Fixed
search --min-cvss NaNwas accepted and sent upstream asmin_cvss=NaN,
where an ignored filter comes back looking like a filtered list. The range
check was written as "below 0 or above 10", which NaN passes; the config
parser already stated its ranges from the inside, the flags did not.
--timeout NaN,Infand1e300were accepted too, and the config file's
one-hour ceiling did not apply to the flag. Both now take the same rule.- A numeric flag given as 0 was read as the flag's absence.
--limit 0
printed the default page,--year 0every year, and--timeout 0the
configured timeout, without a word — 0.1.0 said this was fixed and had fixed
it for--min-cvssonly. They are refused, at the MCP surface too
(search_cveswithyear: 0).match --limit -1was the last of them — -1
was that flag's own "not given" — and is refused as well. - A timeout or TTL so small that it rounds to no time at all (
1e-10seconds)
was accepted and became a zero duration, which means "not set" to the config
loader and "no timeout" to the HTTP client: the smallest value one could
write behaved as the largest. It is refused, from the flag, the environment
and the config file alike. - Upstream's error text reached stderr with bidirectional controls intact.
The three places that neutralise third-party text each kept their own list of
what a terminal obeys, and the one for error messages had no bidi controls, so
an error body could reorder the line it was printed on — against what this
README says. There is one list now (internal/termsafe).
v0.1.0
First release.
Added
get <CVE-ID>...: CVSS by version with who rated it, CISA KEV, EPSS, SSVC,
exploitation evidence, patch availability and EchelonGraph's fused score —
as this tool's own projection, every block naming its source. A block
upstream holds nothing for is omitted and named inabsent; a score of 0 is
never passed on as a rating.--sectionopenscpe/references/
score-factorsin full;--rawprints upstream's body as it arrived.search [<text>]: free-text search over descriptions with--severity,
--basis,--min-cvss,--kev,--year,--sort,--limit,--offset.
Enums are validated before the request, because upstream silently ignores an
invalidsort.match --product P [--vendor V]: CVEs that apply to a product at the CPE
layer, paged locally. An unknown product isproduct_known: false, not an
empty list. No version is sent upstream. Upstream does not filter by vendor:
rows whose vendor it could not confirm carryvendor_unverified, the result
counts them, and the headline saysVENDOR NOT CONFIRMEDwhen the vendor
matched nothing.exposure <CVE-ID>: internet-exposure footprint. A CVE the radar does not
follow istracked: false, never "0 hosts"; a key upstream leaves out stays
absent instead of becoming a zero.related <CVE-ID>: CVEs sharing a product, a vendor advisory or a CWE, up to
ten per relation, each with what ties it. A CVE upstream does not index is
reported as such, never as three empty lists; when that cannot be checked
the answer isincompleteand the run exits 1.advisories [--vendor V] [--has-cve | --no-cve]: vendor advisories from
Microsoft, Red Hat, GitHub, Cisco, AWS, Google Cloud and GitLab, newest
first —--no-cvelists what vendors disclosed before a CVE ID existed.
The vendor is a closed set, because upstream answers an unknown one with an
empty list.advisory <vendor> <id>: one advisory in full, by the vendor's own
identifier.status: feed freshness and counts by severity, always live.cache status|clear, and a fixed-TTL result cache holding upstream's body
with three freshness windows. Errors,not_foundand an unverified empty
answer are never cached;--refreshbypasses it.mcp: a local stdio MCP server with ten tools —get_cve,search_cves,
match_product,get_exposure,get_related,search_advisories,
get_advisory,feed_status,cache_status,get_usage. Results are sized
for a model's context: compact by default, every cap counted, and everything
left out reachable throughsection, paged (text by characters). Behind the
caps, any other string over 1000 characters is shortened and named, and no
result leaves the server over 128 KB (response_too_large).get_usage
carries the tool reference, the result schemas and how to read the "upstream
has no data" shapes.- Stable error codes end to end:
not_found(worded "not in EchelonGraph's
index", and only for the API's own 404 on a single resource),
endpoint_unavailable(a path outside the public API — a wrongbase_url—
or a listing that answers 404),rate_limited,bad_request,
upstream_error,network_error,timeout,decode_error,
invalid_argument,unknown_tool,response_too_large,internal_error. - Input that is not understood is refused rather than ignored: unknown config
sections and keys, a key set to"", a number outside its range, a
--configpath that does not exist, a flag value that used to double as
"not given", stray arguments, and MCP arguments a tool does not declare are
each an error naming the offender. - Text output makes every string from upstream inert before it is printed —
control characters, escape sequences and the Unicode bidirectional controls
are shown as escapes — and prints third-party text behind a gutter.--json
and--rawwrite the same characters as the\uescapes they equal. - Sectioned-TOML configuration with
CVE_LOOKUP_*overrides and a validated
base_url. The file is searched in$XDG_CONFIG_HOME/cve-lookup/,
~/.config/cve-lookup/and, on macOS,~/Library/Application Support/;
cache statusprints the file that was read. - Per-process request pacing with a short burst, 30 requests per minute by
default — half the 60 per minute upstream allows per IP address. A 429 is
reported, not retried. - A live end-to-end suite (
make e2e) that pins the upstream behaviours the
design rests on, and a drift check against the CISA KEV catalogue and FIRST
EPSS with tolerances — a release gate that fails, rather than skips, when it
could not compare.