Back to write-ups Issue #2  / 

Explain This CVE

A CVE record is written for specialists. I built a one-page checker that explains any CVE in plain English, and I tried to make it hard to abuse.

CRITICAL vs
The problemA manager deciding "do we drop everything today?" gets a score, a vector string and 100 links.
NVD CISA KEV EPSS
The sourcesThree public databases, fetched in parallel and boiled down to one small, fixed answer.
treated as hostile.
The ruleEverything from the databases, and everything the AI says, is treated as hostile text.

What it does

You type a CVE ID, such as CVE-2021-44228 (Log4Shell), and get one page with seven chapters, always in the same order:

  1. The CVE ID, its title and when it was published.
  2. Severity: the CVSS score with a colour badge, and the level written as a word.
  3. Whether it is being exploited: CISA's Known Exploited Vulnerabilities list (KEV) and the EPSS probability.
  4. A plain-language summary.
  5. Which products and versions are affected.
  6. The fix and mitigation: what CISA requires, the first unaffected versions, patches and advisories.
  7. References.

There are two views of the same data. The Manager view answers "do we need to act today?". The Analyst view keeps the detail. Every brief ends with "Always verify with the official vendor advisory."

How it works

It's a static page and one serverless function, with no accounts, no database and no dependencies. For each request the function runs these steps in order:

  1. Check the method, then rate limit the client.
  2. Validate the ID. It must match ^CVE-\d{4}-\d{4,10}$, and it must be the only query parameter.
  3. Look in the cache. If another request for the same ID is already running, wait for it instead of asking again.
  4. Fetch NVD, the CISA KEV feed and EPSS in parallel, each with its own timeout.
  5. Normalise the untrusted data into a small fixed shape.
  6. Write the summary: an AI model when a key is set, fixed rules otherwise.

NVD is required. If CISA, EPSS or the AI model fails, the page still works and says what is missing. "Could not check CISA's list" is shown as unknown, never as "not exploited", because a failed lookup that reads as good news is the worst thing a security tool can do. For the same reason, a KEV feed with fewer than 100 entries is treated as broken.

The security choices

The data comes from public databases, but anyone can influence some of it, and an AI model reads it. So all of it is treated as hostile.

ThreatWhat I did
API keys leakingKeys are read from environment variables in one server file. The browser code never mentions them, and a test scans every committed file for key-shaped strings.
Bad input and SSRFOne strict, ASCII-only ID pattern. The three API hosts are constants, the ID goes in through URL.searchParams, and redirects are refused.
XSSThe server cleans text and caps lengths. The browser writes only with textContent. A strict Content Security Policy with Trusted Types is the last line.
Prompt injectionThe model gets only public facts, no tools and no secrets. Its answer must be a three-field JSON object, and it is rejected if it contains a link, a tag or a version number that isn't in the facts.
Abuse and quota20 requests a minute per client, 6 uncached lookups a minute, a shared budget just under NVD's own limit, and an hour of caching.
Hostile upstream dataEvery field is type-checked, loops and sizes are capped, and a record about a different CVE than the one asked for is refused.

There are more than 140 tests on saved real API responses, so they run offline. The most useful is an XSS drill that runs the real browser code against a response full of <img onerror> and <script> payloads and fails on any unexpected element, attribute or link.

What it can't do yet

  • The cache and the rate limiter live in the memory of one function instance, so they are best-effort. A shared store would fix that.
  • NVD's quota is shared by all visitors. If it runs out, the page shows a "busy" message.
  • A persuaded AI model can still write a misleading sentence that contains no link or version number. The checks can't catch an opinion, which is why severity, KEV and EPSS are shown separately from the summary.
  • KEV lists confirmed exploitation only, and EPSS is a probability, not a verdict.
  • I tested one Chromium browser, in both themes, at desktop and phone widths. I did not test Safari or Firefox.

I built it with AI assistance. I designed the features and the security requirements, and I reviewed and tested the code.

Try it

The live checker is at explain-this-cve.vercel.app, and the code and a study guide are on GitHub. Try Log4Shell first.