GitHub
ESC

Queries & Filters

Catalog#query returns a KEV::Query — a chainable, immutable filter pipeline.

catalog.query
  .vendor("Microsoft")
  .ransomware
  .added_on_or_after(Time.utc(2024, 1, 1))
  .sort_by_due_date
  .to_a

Every chain step returns a new Query, so the source catalog is never mutated.

Available filters

Method Description
vendor(name) Exact vendor match, case-insensitive
product(name) Exact product match, case-insensitive
name_matches(substr) Substring match against vulnerability_name
description_matches(substr) Substring match against short_description
cwe(code) Match by CWE code ("CWE-79" or "79" or "079")
ransomware Only knownRansomwareCampaignUse == "Known"
non_ransomware Inverse of ransomware
year(year) Match by CVE year (the YYYY portion of the id)
added_on_or_after(date) / added_on_or_before(date) Bracket by date_added
due_on_or_after(date) / due_on_or_before(date) Bracket by due_date
overdue(now = Time.utc) Past their deadline
due_within(span, now = Time.utc) Deadline in [now, now + span]
where { |v| ... } Generic escape hatch

Sorting

Query exposes two ordering helpers that produce a sorted copy:

catalog.query.ransomware.sort_by_due_date
catalog.query.vendor("Microsoft").sort_by_date_added

Materialising results

q = catalog.query.vendor("Apple").ransomware
q.size              # length (without materialising an Array)
q.to_a              # plain Array(Vulnerability)
q.first?            # nil-safe first
q.last?

Query itself is Enumerable + Indexable, so the usual collection methods also work directly:

q.each { |v| handle(v) }
q.group_by(&.vendor_project)

Examples

Critical Microsoft entries from 2024

catalog.query
  .vendor("Microsoft")
  .added_on_or_after(Time.utc(2024, 1, 1))
  .ransomware
  .to_a
  .each { |v| puts "#{v.cve_id}  #{v.due_date.to_s("%Y-%m-%d")}  #{v.vulnerability_name}" }

"Due in the next 14 days that affect Apache"

catalog.query
  .vendor("Apache")
  .due_within(14.days)
  .sort_by_due_date
  .to_a

Server-side rendering: a CWE breakdown

breakdown = catalog.cwes.each_with_object({} of String => Int32) do |cwe, h|
  h[cwe] = catalog.query.cwe(cwe).size
end

See also