Skip to content

Vulnerability-Lookup 6.3.0 released

We are pleased to announce the release of Vulnerability-Lookup 6.3.0!

This is a large release. Two new scorecards grade the actors of the vulnerability ecosystem on what they publish: the CNA and GNA scorecard ranks assigners on the quality of their records, and the KEV catalogue scorecard ranks the known-exploited-vulnerability catalogues on how they back, situate, lead and maintain their assertions. The vulnerability page gains a timeline of everything dated the instance holds on a record, and the sighting correlation graphs are redrawn with Pivotick. Vulnerability-Lookup reads and renders GCVE-BCP-05-X-03, the handling and disclosure timeline extension, and corroborates its exploitation events with the KEV catalogues and the sightings it holds. CNAs publishing through the platform get an immutable publication audit history. The exploit hazard aggregates are corrected for the Weibull model. Also in this release: single sign-on through OpenID Connect, a bulk lookup endpoint, GCVE-0 identifiers accepted everywhere, a syntax-highlighting detection rules viewer, a statistics page that can finally draw every figure the API serves, and richer /recent feeds.

Upgrade notes

  • This release requires three PostgreSQL migrations (poetry run flask --app website.app db upgrade): the publication audit table, the removal of the hand-administered EUVD coordinated assigner setting, and a hash index on sighting.source built CONCURRENTLY, so it does not lock the sightings table.
  • Reindex after upgrading: poetry run index_vulnerabilities --source cvelistv5 (and --source gna-<id> for every GNA with records). The reindex now writes the CVSS distributions without withdrawn records, the assigner scorecard tallies and the per-source lifecycle indexes of the GNAs. Then, once the KEV catalogues are imported, poetry run euvd --stats-scan --stats-source <name> for every source you import.
  • Two new hourly passes belong in cron beside the statistics jobs: poetry run scorecard --window-only and poetry run kev_scorecard. See the prepared statistics figures, the scorecard and the KEV scorecard documentation. An instance that ran the EUVD figures of 6.2.0 also needs poetry run euvd --migrate-stats-keys once.
  • The CSAF feeders now pass a User-Agent to csaf_downloader, which needs version 2.1.0 or later.
  • The CNA partner catalogue is read from the GCVE client’s copy: run poetry run flask --app website.app update_gcve_registry (or the maintenance-page button) once. The data/cna_assigner_roots.json an earlier instance wrote is no longer read and can be deleted.
  • The detection rules viewer bundles highlight.js at npm ci time; the step needs Node.js 18 or later and is skipped with a warning on an older Node, the viewer then falling back to plain text.
  • Instances holding sightings imported before the deduplication fix should run poetry run flask --app website.app dedup_sightings (a dry run), then again with --yes.
  • A new Python dependency, joserfc, comes with poetry install. Single sign-on, the wall of shame of the assigner scorecard and the classification gate are all off by default.

What’s New

KEV catalogue scorecard

A KEV catalogue publishes assertions, not records, so the question the scorecard asks is not “how well is the record filled?” but: how well is the claim backed, how early did it come, and is the catalogue looked after. Each catalogue is graded on four pillars of 25 points over a rolling window:

  • Substantiate weighs the evidence by its provenance. Derivative evidence, which declares another origin or names another catalogue, earns a quarter for presence and nothing inherited; a catalogue whose evidence is one constant triple is templated, and its signal and confidence credits are halved.
  • Situate reads the BCP-07 timestamps, characteristics, scope and references.
  • Lead scores the first-to-list share and the median lag against independent catalogues only.
  • Maintain scores retractions within 30 days, unknown status reasons and freshness.

Mirrors are inferred from the data rather than declared (containment of at least 90%, a median lag of two days or less, downstream first in at most 5% of cases) and excluded from lead and corroboration; on the public data, the one relation found is Previdian over CISA. A catalogue sharing nothing has no lead and is scored over the 75 assessable points. Listing dates read asserted_at before first_seen_at, which may be estimated retroactively.

The ranking lives at /kev-catalogs/scorecard, with the inferred mirror relations and the rules on their own tabs. Each catalogue has a card with the credit per rule, the pillars (a lead that could not be measured reads “not assessable”), the context figures, the catalogues it mirrors and the ones mirroring it, and its score per listing year, plus an embeddable badge. Every card of the KEV catalogues page now carries its grade, the cards are ordered by subscribers, and signed-in users subscribe to a catalogue straight from its card. The figures are served by /api/stats/scorecard/catalogues and /api/stats/scorecard/catalogue, and the methodology is versioned and documented in docs/kev-scorecard.md.

The Known Exploited Vulnerability Catalogs page: a Scorecard button under the search box, and the catalogue cards ordered by subscribers, CISA with 1741 entries, 10 subscribers and grade C, ENISA with 65 entries, 9 subscribers and grade C, the local CIRCL catalogue with 30 entries, 8 subscribers and grade D, Shadowserver with grade C and Previdian with grade D, each card ending with Browse, Source and a Subscribed or Subscribe bell button

The KEV catalogues page: each card now carries its grade beside its entry and subscriber counts, the cards are ordered by subscribers, and the bell at the bottom subscribes or unsubscribes without leaving the page.

The KEV catalogue scorecard page on the public instance: five ranked catalogues, zero under the threshold, a 180-day rolling window and one mirror relation, then the ranking tab listing CISA, Shadowserver and ENISA with grade C and CIRCL and Previdian with grade D, each with its score, its entry count and its badge

The catalogue scorecard on the public instance: CISA, Shadowserver and ENISA at grade C, CIRCL and Previdian at grade D, over the last 180 days. Each row ends with the catalogue’s embeddable badge.

The CISA card of the KEV catalogue scorecard: grade C, 73.29 out of 100 over 172 entries listed in the last 180 days and 71.84 all-time, the Substantiate rules with the credit earned on evidence, evidence type, signal and confidence, and a Context, not score panel giving the evidence provenance, the templated-evidence note, corroboration by an independent catalogue, the median lag behind the first lister, the withdrawn entries, the latest listing and the catalogue mirroring it

One catalogue’s card: the credit per rule with the points it is worth, and beside it the context that is not scored. CISA’s evidence is templated, one constant type, signal and confidence on every entry, so its signal and confidence credits are halved.

The Mirrors tab of the KEV catalogue scorecard: the rule that a catalogue mirrors another when it holds at least 90 percent of its entries with a median lag of at most two days and is strictly first on at most 5 percent of them, and one row, Previdian mirrors CISA, holding 100 percent with a median lag of 0.0 days and strictly first on 4 percent

The one mirror relation inferred from the public data: Previdian holds every CISA entry, the same day, and is first on 4% of them. A mirror and its upstream never compete for the lead.

CNA and GNA scorecard

Every CVE JSON 5 record is scored against thirteen published rules in four pillars (describe, scope, assess, act; 25 points each), on its CNA container only. Severity and weaknesses an ADP added later are counted apart, as an enrichment dependency, rather than folded into the score; severity is any severity statement (CVSS, SSVC or a vendor rating), not CVSS alone; the rules are graded rather than binary; and the reservation-to-publication delay is displayed but never scored. A CNA is the record’s assigner and a GNA is its own source, so one engine ranks both.

The figures are prepared by poetry run scorecard and by every reindex: per-assigner tallies, a rolling 180-day ranking in which an assigner needs ten publications to be ranked, a per-year history and a versioned methodology whose history is kept in the code and in the documentation. The ranking is at /assigners/scorecard, with a hall of fame and the rules; each assigner page shows the credit rate per rule, the context figures and the trend, and offers an embeddable grade badge at /assigners/<name>/badge.svg. The assigner line of every CVE and GCVE record now carries the grade (“CNA scorecard B · 89/100”), and the /assigners/ page opens with a chart of publications per year, the eight most active assigners drawn individually, a sparkline per assigner, and a closing list of the partner-catalogue CNAs that never published.

Each CNA is enriched with the CVE Program partner catalogue (organisation, country, root, partner profile), attributed only when the catalogue identifies exactly one partner. A wall of shame naming the assigners that trip a set of thresholded practices is behind WEB_MODULES["wall_of_shame"], off by default: naming publishers is a stance an instance takes deliberately. See docs/scorecard.md.

Vulnerability timeline

A new Timeline tab on the vulnerability page, right after Sightings, lays out everything dated the instance holds on a record: publication and updates, the KEV catalogue listings, the related advisories and every sighting, day by day. Busy days unfold on demand, two hundred days at a time. It loads from one cached page endpoint instead of fanning out over several rate-limited API reads, and sightings and KEV entries are matched under every spelling of the identifier, GCVE-0 and altId-only entries included. The same events are available as an event-level export at GET /api/vulnerability/<id>/timeline, with a JSON button on the tab.

The Timeline tab of CVE-2026-88771 with 342 sightings: filters for publication and reservation, sightings, KEV catalogs and other timestamps, 391 events from 2025-08-04 to 2026-10-14, a Document generated record event from the csaf_ncscnl source 402 days before the Reserved milestone, then days of 72, 117, 54 and 36 events folded with a summary of their event types

The timeline of CVE-2026-88771: a Dutch NCSC CSAF advisory generated 402 days before the identifier was reserved, then the publication, the KEV listings and hundreds of sightings folded per day with a summary of what each day holds.

The Timeline tab of CVE-2026-58457 with 33 events: on 2026-09-05 a KEV Recorded event from the Previdian catalogue at 16:00:02 followed by an Exploited sighting at 16:00:37 pointing at the known-exploited-vulnerabilities-catalog entry, and on 2026-09-09 the same pair from the Shadowserver catalogue

A smaller timeline, CVE-2026-58457: each KEV listing is followed within a minute by the exploited sighting the catalogue entry carries, Previdian on 2026-09-05 and Shadowserver on 2026-09-09.

Sighting correlation graphs redrawn with Pivotick

The correlation pane of the vulnerability page and the /sighting/<uuid>/correlations page are rebuilt on Pivotick. Both now draw a document the server builds in one window query each, served outside the API budget and also at /api/vulnerability/<id>/correlations and /api/sighting/<uuid>/correlations, instead of paging the sighting API’s substring search from the browser, which collided with the API rate limit and had no node ceiling.

Every node is a card. Sources carry their sighting count, nodes are coloured by the latest sighting type, a legend filters by kind and by type, tooltips show the sighting’s content and follow the site theme, fullscreen included, and a status line says what the caps left out.

The Sighting correlations tab of CVE-2026-88771: a Pivotick graph of 120 related vulnerabilities across 50 sources, with a note that 278 sources and up to 617 related vulnerabilities are not shown because the graph keeps the most correlated, a Select, View and Physics toolbar, and a legend counting one vulnerability, 120 related vulnerabilities and the sources by latest sighting type: 31 seen, 4 published proof of concept, 15 exploited

The correlation graph of CVE-2026-88771 in its tab: 120 related vulnerabilities across 50 sources, the sources coloured by their latest sighting type. The status line says what the caps left out.

The same graph in fullscreen: two clusters of sources and related vulnerabilities around CVE-2026-88771, with a tooltip pinned on a Telegram source node reading one sighting of this vulnerability, latest Published proof of concept on 2026-10-08

The same graph in fullscreen, with the tooltip of a Telegram source: one sighting of this vulnerability, a published proof of concept on 2026-10-08.

A small correlation graph for CVE-2026-58457: nine sources pointing at the vulnerability, two KEV catalogue entries in red, Telegram channels in orange and Bluesky posts in light orange, one related vulnerability CVE-2024-25600, and a tooltip on a bsky.app source showing the post text, Shenzhen Aitemi M300 MT02 unauthenticated OS command injection, with a Visit source link

A sparser one, CVE-2026-58457: its sightings on Telegram, Bluesky and two KEV catalogues, one related vulnerability, and the content of a Bluesky post in the tooltip.

GCVE-BCP-05-X-03, the handling and disclosure timeline, is read and rendered

GCVE-BCP-05-X-03 lets a GCVE record carry the dated events of its handling process and, optionally, the regulatory notifications that branched off it: the EU CRA early warning, vulnerability notification and final report. Until now such a record rendered the extension as raw JSON.

A record carrying x_timeline now gets its own section of the GCVE extensions panel: the event count, the time to fix, exploitation and the publisher’s CRA assessment in the folded header; the spans (report to fix, report to disclosure, exploitation to protective measure), the event list and one block per regulatory framework with its notification table in the body. The reader keeps document order for ties, reads a bare date as midnight UTC and flags a span over it as approximate, reports a malformed member rather than failing, and keeps values outside the extension’s vocabularies as written, as the extension requires of consumers. dueAt and submittedAt are read but never compared into a verdict.

An exploitation-observed event is corroborated with what the instance holds, in both directions and deriving nothing: the record page lists the catalogues listing the vulnerability with their first-listed date and its distance from the observation, and the independent exploited sightings, KEV mirrors excluded; the KEV entry page says what the record states and how many days before or after the listing. When nothing else is on record, the note says so, which is the reading a CSIRT wants: a GNA recording exploitation nobody has listed yet. Every extension section now opens with the extension key, its title as gcve.eu publishes it and a link to its text. The first real record published with the extension, GCVE-1-2026-20307, is a test fixture.

The GCVE extensions panel of GCVE-1-2026-20116, a MISP forced-TOTP-enrolment bypass generated by patch2vuln: the assumptions and the model comparison of the patch provenance section, then the bcp-05-x-03 Vulnerability handling and disclosure timeline section with two Fix developed events dated 2026-09-23 and 2026-09-28, each naming the corrective commit, and a tooltip explaining the three BCP-05 extensions

The handling and disclosure timeline of GCVE-1-2026-20116, published by GNA-1 from two MISP commits: two fix-developed events, each linking the corrective change, under the patch provenance section of the same record.

CNA publication audit history

Every action on a publication (reserve, publish, update, reject, abort, delete) is recorded with its actor and the values before and after, and the rows are immutable: deleting a user keeps them. The publication page shows its fifty most recent entries and links to /publications/audit for the rest.

The publications list itself is reworked: one labelled primary action per row (Reserve, Publish, Update), a details link and a “more” menu for reject, abort and delete; status pills with counts replace the status select; and each action is shown only to users holding the permission its route enforces.

Improved exploit hazard

The local exploit hazard aggregates multiplied the summed instantaneous daily hazards by the horizon. That is exact for the exponential model, but under the age-dependent Weibull model the early-life hazard is not sustained across the horizon, so young vulnerabilities were overstated: about 1.6x for a day-old CVE over the 7-day report horizon, about 1.25x for a realistic weekly batch of zero-to-six-day-old CVEs.

Each instance now carries expected_events, the Weibull hazard integrated over [age, age + horizon], the same integral the per-item horizon_probability already used, and the aggregates (the subscription reports and the threshold alerts) sum that field. The instantaneous daily rate is still reported for threshold monitoring, and the payload keys are unchanged. Thanks to Laura Voicu for reporting and fixing it.

An hourly notification e-mail for the python software foundation / cpython subscription: an Exploitation hazard estimate section stating that the one vulnerability in the report carries an estimated 0.0000 expected exploitation events per day and a probability below 0.1 percent of at least one exploitation event within 7 days, a standing exposure of 0.0017 expected events per day across all 75 watched vulnerabilities, then CVE-2026-18503 with a 7-day exploitation probability below 0.1 percent at EPSS 0.12 percent and age 65 days

A notification report after the fix: the batch estimate and the standing exposure of a CPython subscription both now sum the per-instance Weibull integral over the 7-day horizon rather than the daily rate times seven.

Single sign-on with OpenID Connect

A “Sign in with …” button next to the password form runs the authorization code flow with PKCE, state and nonce, verifies the ID token against the provider’s keys, and matches an existing active, confirmed account by its verified e-mail address; nothing is provisioned. Local two-factor authentication still applies unless a configured claim proves the provider did it, and required claims (groups, tenant) gate sign-in. It is configured on /admin/sso/ or pinned read-only by OIDC_* keys in config/website.py, and off by default. The flow was hardened end to end before release: settings and provider metadata checked on every flow, no redirects followed, rate limits keyed on the real client, a flow redeemed once, a __Host- flow cookie over https, and a failed sign-in that tells the user why without logging out an existing session. Documented in docs/sso.md. Contributed by Jeroen Trappers.

Statistics: every figure drawn, scoped and dated

  • The statistics page draws the four prepared figures that had no chart (severity distribution, CVSS version distribution, known-exploited inclusion, time to exploit) in a Composition of a source section with its own source picker, and is organised in named sections with a jump line.
  • /api/stats/vulnerability/status and /api/stats/time_to_exploit take a period, and /api/stats/kev a granularity of year or month bucketed on the date a catalogue listed the record, so a year selector applies to every figure of the page. Time to exploit per publication year draws a mean and a median bar per year.
  • STATS_KEV_CATALOGS scopes a source’s known-exploited figure to the catalogues it publishes; EUVD defaults to CISA KEV and EU KEV. The prepared figures record the scope they were measured over, so a change of configuration cannot be claimed over figures measured without it.
  • /api/stats/vulnerability/status reports the current lifecycle state beside the date-based counts, which differ by roughly 12,000 withdrawn CVE records, and the severity distributions no longer count withdrawn records.
  • The exploited CVE ratio gets a stacked view and a monthly drilldown, both sides now bucketed by the publication date, and every chart shows the API query behind it. The rankings accept a limit up to 100.
  • euvd --stats-scan prepares the known-exploited share, the per-period series and the time to exploit for every source, GNAs included, and index_vulnerabilities no longer empties a source’s derived keys before walking it, so the figures stay readable during a rebuild.

Most of this work was contributed by Nikiforos Archakis for the EUVD, and is documented in docs/statistics.md.

Bulk lookup and GCVE-0 identifiers

POST /api/vulnerability/bulk serves up to a hundred records in one call, read in one MGET with their metadata in three pipelined round-trips; a corrupt stored value is a null slot rather than a 500 that loses the other results, and with_linked is accepted for at most ten identifiers. GCVE-0 is the CVE namespace, and a GCVE-0-YYYY-NNNN identifier is now resolved at the storage layer, so it works wherever a CVE identifier does: every API route, search, and the comments, sightings and bundles filed under either spelling.

Detection rules viewer

The Detection rules tab syntax-highlights YARA, Suricata and TOML rules with the grammars of rulezet-core’s own code viewer, and adds a search box, a format filter, a page size control and pagination. Every rule page is fetched, and only a 404 reads as “no rule”: an outage surfaces as an error. Contributed by ecrou-exact.

The Detection rules tab of CVE-2026-19490, served via Rulezet: a search box, an All formats filter, a 10 per page control and Showing 1-1 of 1, then one Suricata rule card, SH3LLC0D3 - Exploit Attempt Citrix NetScaler Pre-Auth RCE Zero-Day (watchTowr Advisory), by Sh3llc0d3, created 2026-09-27, with its single syntax-highlighted alert line and a copy button

The Detection rules tab of CVE-2026-19490: a Suricata rule from Rulezet, syntax-highlighted, with the search, format filter and page size controls above it.

And more

  • Feeds — The /recent Atom and RSS entries carry the record’s own title, the affected vendor and product (CVE 5, GCVE) or ecosystem package (OSV sources) and the description, and are spelled as the record spells its identifier.

  • Unknown identifiers — The page of an id no source holds states the three honest explanations (reserved, not imported yet, withheld), summarises the sightings recorded on it, links the assigner’s own page, and accepts comments again.

    The page of CVE-2026-92392 with a Not in any source badge: a note that none of the followed sources has a record yet and that it may be reserved, published but not imported or withheld, a summary of 6 sightings from 6 sources by 1 reporter first seen 2026-10-12 and last seen 2026-10-14, Check upstream links to CVE.org and NVD, Share, Add a sighting and Add a comment buttons, and the Timeline tab listing the six Seen sightings from Bluesky and Mastodon

    CVE-2026-92392, which no source holds yet: six sightings on Bluesky and Mastodon over three days, the upstream links to check, and the buttons to record a sighting or a comment in advance.

  • VLAI — Classification answers are cached for 30 days, so a text is classified once whoever views it, and VLAI_CLASSIFICATION_REQUIRE_AUTH can gate the two classification endpoints behind a session, an API key or the signed token the page sends with its own calls.

  • Sightings — export_sightings and import_sightings move sightings between instances as NDJSON, streaming on both sides; dedup_sightings removes duplicate observations; the API deduplicates URL sightings across days while keeping another author’s report of the same source; and the client’s creation_timestamp is stored again.

  • EUVD — The EU CSIRT coordinated assigner list is mirrored from the table the CSIRTs Network publishes rather than administered through the API.

  • Administration — The maintenance page describes every action it offers and gains the registry update and the organization sync; the running version is shown in the footer of every page.

Changes

  • CNA partner catalogue — Read from the GCVE client’s copy of cna_partners.json on every registry refresh, the bundled snapshot is gone.
  • CSAF — The feeders identify the instance to the providers; Cisco refused the anonymous client with a 403 before a single advisory was requested.
  • Dashboard — A shared URL carries the selected tab as #tab-<name>.
  • Website — The topbar is sticky again, and the administration sidebar scrolls in a short window.
  • Dependencies — Updated Python and frontend dependencies; joserfc is added for the ID token verification.

Changelog

📂 For the full list of changes, including the fixes, check the GitHub release:
https://github.com/vulnerability-lookup/vulnerability-lookup/releases/tag/v6.3.0

🙏 A big thank you to all contributors and testers!

Feedback and Support

If you encounter any issues or have suggestions, feel free to open a ticket on our GitHub repository:
https://github.com/vulnerability-lookup/vulnerability-lookup/issues/
Your feedback is always appreciated!

Follow Us on Fediverse/Mastodon

You can follow us on Mastodon and get real-time information about security advisories:
https://social.circl.lu/@vulnerability_lookup/