Getting Started
Prerequisites
| Requirement | Version |
|---|---|
| Crystal | >= 1.19.0 |
kev.cr is pure Crystal with no native dependencies — it runs anywhere Crystal does.
Installation
Add the dependency to your shard.yml:
dependencies:
kev:
github: hahwul/kev.cr
Then install:
shards install
Your First Program
Save a snapshot of the KEV feed locally so you don't hit CISA on every run:
curl -o kev.json https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
Then create hello.cr:
require "kev"
catalog = KEV.parse(File.read("kev.json"))
puts "version: #{catalog.catalog_version}"
puts "entries: #{catalog.size}"
log4j = catalog["CVE-2021-44228"]
puts "log4j vendor: #{log4j.vendor_project}"
puts "log4j vendor: #{log4j.product}"
puts "ransomware? #{log4j.known_ransomware?}"
puts "remediation: #{log4j.remediation_window_days}d"
Run it:
crystal run hello.cr
Fetching the live feed
For one-off scripts you can pull directly from CISA:
require "kev"
KEV.fetch.size # => 1500+
For polling, prefer a long-lived KEV::Client so you can use conditional GETs — see Fetching the Live Feed.
Non-raising parse
When validating user input or files of uncertain provenance, prefer parse? over wrapping parse in begin/rescue:
if catalog = KEV.parse?(user_input)
# use catalog
else
# malformed JSON or schema violation
end
Next Steps
- Basic Usage — catalog lookups, predicates, equality
- Queries & Filters — chainable filter builder
- Fetching the Live Feed — HTTPS client + ETag handling
- JSON Round-Trip — serialization shape and gotchas