{"slug": "show-hn-i-built-a-local-first-cve-triage-app-in-rust", "title": "Show HN: I built a local-first CVE triage app in Rust", "summary": "A developer released CVE Intel, a local-first vulnerability triage desktop application written in native Rust that queries up to 40 public data sources — including CISA's KEV catalog, FIRST's EPSS and ENISA's EU Vulnerability Database — and returns a 0-to-100 risk score with evidence and a recommended action for each CVE. The app ships 41 MCP tools for AI agents and coding assistants alongside a CLI and REST API, reads CycloneDX and SPDX SBOMs and lockfiles, and writes scans back out as CycloneDX 1.5 SBOMs with findings and recorded decisions. The release cites 48,185 CVEs published in 2025 (20.6% more than 2024) and over 86,000 by 27 October 2026, plus NIST's April 2026 statement that the National Vulnerability Database cannot keep up and Mandiant's M-Trends 2026 estimate of a mean time to exploit of −7 days.", "body_md": "Know which vulnerabilities matter, and what to do about them.\n\n  A private desktop app for vulnerability triage and scanning, written in native Rust, with a CLI, REST API and MCP server for developers and AI agents.\n\n  41 MCP tools, 40 data sources, SBOMs in and out, on-device AI.\n\n[What it is](#what-is-cve-intel) ·\n  [Getting started](#getting-started) ·\n  [Features](#features) ·\n  [Install](#install) ·\n  [Local AI](#local-ai) ·\n  [Data sources](#data-sources) ·\n  [Developer notes](#developer-notes) ·\n  [Citing](#citing-and-attribution)\n\n<sub>Sped-up demo on macOS ([1080p video](https://github.com/Fazmin/cve-intel/blob/main/assets/core-functions-demo.mp4)): the threat landscape, triage and recording a decision, the decision ledger, a scan with attack chains and an SBOM, and the watchlist.</sub>\n\nEvery known software vulnerability gets a public ID, such as CVE-2024-3400.\nFor each one, security, IT and development teams face the same question:\n*does this affect us, and do we fix it now or can it wait?* Answering it\nusually means checking NVD, CISA, FIRST, GitHub and vendor advisories by\nhand, one browser tab at a time.\n\nCVE publication keeps rising\n([48,185 in 2025](https://jerrygamblin.com/2026/01/01/2025-cve-data-review/),\n20.6% more than 2024, and\n[over 86,000 by 27 October 2026](https://craci.com/resources/CVE-publication-trends)),\nand in April 2026\n[NIST said](https://www.nist.gov/news-events/news/2026/04/nist-updates-nvd-operations-address-record-cve-growth)\nthe National Vulnerability Database cannot keep up, so it will enrich CVEs in\nCISA's Known Exploited Vulnerabilities (KEV) catalog, federal-use software\nand critical software first, and move its unenriched backlog from before\n1 March 2026 to \"Not Scheduled\". Meanwhile,\n[Mandiant's M-Trends 2026](https://cloud.google.com/blog/topics/threat-intelligence/m-trends-2026)\nestimates the mean time to exploit at −7 days, so exploitation routinely\nbegins before a patch is released, and exploits were the most common initial\ninfection vector for the sixth year running (32% of intrusions).\n\nGive CVE Intel a CVE ID, a project folder, a lockfile or SBOM, a container image, the software on this computer, your own domains, or a suspicious IP address, file hash or domain. It queries up to 40 public sources, including CISA KEV, FIRST's EPSS and ENISA's EU Vulnerability Database alongside NVD, and returns what the vulnerability is, a risk score from 0 to 100, whether attackers are already using it, the evidence behind each signal and what to do next. It also shows what changed this week across those sources, and watches the vendors, products and packages you run.\n\n- **40 data sources** for vulnerability, exploit, network and threat\nintelligence, listed under[Data sources](#data-sources) . Many need no\nAPI key.\n- **41 MCP tools** for AI agents and coding assistants. The same program is\nalso a command line and a REST API (see[Developer notes](#developer-notes) ).\n- **SBOMs in and out.** It reads CycloneDX and SPDX SBOMs along with\nlockfiles, and**Save SBOM** (or`scan deps . --format cyclonedx` ) writes\nany scan as a CycloneDX 1.5 SBOM with the findings, their risk signals and\nyour recorded decisions.\n- **Local.** There is no CVE Intel account or server. Lookups go straight\nfrom your computer to the public sources, and the AI assistant runs on a\nlocal model unless you choose a cloud provider.\n\nIt is for security analysts, IT and operations teams, developers checking their dependencies, and anyone learning vulnerability management.\n\n- **Decide whether to patch now.** Enter a CVE ID and get a risk score from\n0 to 100, a plain recommendation and how urgent it is, with the evidence\nbehind it.\n- **Put a list of vulnerabilities in order.** Paste up to 10 CVE IDs from a\nscanner report and get the order to patch them in.\n- **Check your project's dependencies.** Drop a project folder on the\nwindow, or paste a lockfile or SBOM. You see which packages have known\nvulnerabilities, ranked by how likely they are to hurt you (Log4Shell\nfirst, not just the highest CVSS), and which version fixes them. Scan\nagain later to see what is new, fixed or riskier since last time, or\nsave the scan as a CycloneDX SBOM with the findings in it.\n- **Check what you run and ship.** Scan the apps and operating system on\nthis computer, or a container image you build (no Docker needed). Or see\nwhat public sources already know about your own domains and servers,\nwithout CVE Intel ever connecting to them.\n- **See what affects the products you run.** List the known vulnerabilities\nfor a product and version, such as Apache Tomcat 9.0.80, with actively\nexploited ones first.\n- **See what changed this week.** Open**Landscape** for new CISA KEV\nentries, CVEs ENISA marks exploited that KEV does not list yet, rising\nEPSS scores, new Metasploit modules and PoCs, new critical CVEs, Project\nZero's in-the-wild zero-days and the latest CISA advisories. CVEs that\nseveral sources agree on are listed first.\n- **Watch the products you run.** Add a vendor, product, package or CVE to\nthe local watchlist. Each refresh records what changed: new CVEs, KEV\nlistings, EPSS jumps, new exploits, CVSS revisions and newly available\nfixes.\n- **Remember what you decided, and hear when the reasons change.** Record\na decision on a CVE (patch now, defer until a date, accept the risk, not\naffected, mitigated) with the assumptions it rests on. Every refresh\nre-checks them: a deferral turns stale the day the CVE enters CISA KEV\nor an exploit appears, and the ledger tells you how your past calls held\nup.\n- **Keep an eye on what attackers are exploiting.** Filter CISA's catalog of\nactively exploited vulnerabilities by vendor, product, ransomware use or\ndate.\n- **Investigate something suspicious.** Check an IP address from your logs,\na file hash your antivirus flagged, or an unfamiliar domain or URL against\nthreat-intelligence sources.\n- **Ask questions in plain English.***\"Should we patch CVE-2024-3400 this\nweekend?\"* The AI assistant looks up the facts first, then explains them,\nand shows which sources it used.\n- **Give AI coding assistants the same knowledge.** Claude Code, Cursor, VS\nCode and other tools can use CVE Intel while they work, through MCP.\n\n| Term | What it means | \n|---|---|\n| **CVE** | A public ID for one known vulnerability, such as CVE-2021-44228 (Log4Shell). | \n| **CVSS** | A 0–10 severity score: how bad the flaw is if someone exploits it. It says nothing about how likely an attack is. | \n| **EPSS** | The probability that a vulnerability will be exploited in the next 30 days, published daily by FIRST. | \n| **CISA KEV** | The US government's catalog of vulnerabilities known to be exploited by attackers. A CVE on this list is urgent. | \n| **ENISA EUVD** | The EU vulnerability database. Its own \"exploited\" flag is independent of CISA KEV and can raise the SSVC Exploitation input. | \n| **Exploit / PoC** | Public code that demonstrates or carries out an attack. A Metasploit module means the attack is packaged and easy to use. | \n| **SSVC** | A decision method from CISA and CERT/CC that ends in one of four actions: *Act* ,*Attend* ,*Track** or*Track* . | \n| **SBOM / lockfile** | A list of every package your software uses, with exact versions. | \n| **MCP** | Model Context Protocol, the standard way AI assistants call outside tools. | \n\nThe **risk score** combines these signals: severity (CVSS), the chance of\nexploitation (EPSS), confirmed exploitation (CISA KEV) and public exploit\ncode. Anything on CISA KEV is always CRITICAL. See [Risk score](#risk-score)\nfor the formula.\n\nCVE Intel helps you decide what to patch. It does not probe, port-scan or attack anything, and it does not apply fixes. Scans read what is already on your machine (dependency files, the software installed on this computer, a container image you choose) and send only package and product names and versions to OSV.dev and NVD. The exposure check is passive: it asks public sources (Shodan, certificate transparency logs) what they already know about domains and addresses you own, and sends nothing to them. Results are only as current as the public sources.\n\nYou don't need an account or any API keys to start. Most people are looking at their first result within a couple of minutes:\n\n1. [Download the app](#install) for your operating system and open it. The**Landscape** view loads first: what changed this week across the public\nsources.\n2. Open **CVE Triage** , type a CVE ID such as`CVE-2024-3400` and press**Triage** , or click one of the examples under the search box. Press**Watch CVE** (or**Watch** next to the vendor) to be told when it\nchanges.\n3. Drag a project folder onto the window to check its dependencies, or open\n**Scan** and choose**This computer** to check the software installed on\nthis machine. Findings come back ranked by real-world risk, with the\nversion that fixes each one.\n4. Press `⌘K` (`Ctrl+K` on Windows and Linux) to open**Quick Find** . Paste\nanything there (a CVE, IP address, file hash, domain, URL or`package:ecosystem:version` ) and CVE Intel picks the right lookup.\n5. *Optional:* in**Settings → Data source API keys** , add free API keys for\nfaster lookups and more exploit data. See[API keys](#api-keys) .\n6. *Optional:* open**Local Model** and download a model to use**Ask AI** with answers that never leave your computer.\n7. *Optional:* open**MCP Server** to connect your AI coding assistant.\n\nThe buttons at the bottom of the sidebar switch between the light and dark themes and make the text larger or smaller. The version you are running is shown below them.\n\nEverything up to [Developer notes](#developer-notes) is about the desktop\napp. To use CVE Intel from a terminal, a script, a CI pipeline or another\nprogram, go straight to that section.\n\nWhat changed recently, from several independent sources at once: new CISA\nKEV entries (with ransomware flags and vendor counts), CVEs ENISA EUVD\nmarks exploited that CISA KEV does not list, the largest EPSS rises, new\nor updated Metasploit modules and PoC-in-GitHub repositories, newly\npublished critical NVD CVEs, Project Zero's in-the-wild zero-days and the\nlatest CISA advisories. Each panel names its source and when it was\nfetched, and the ⓘ on each tile explains what it counts. Your watchlist\ncomes first, then the CVEs that appear in two or more panels. Each watched\nitem is a chip that opens it in the **Watchlist**. Copy the\nbriefing as Markdown for a ticket or weekly note. Ask *\"What's new this\nweek?\"* in **Ask AI** for the same briefing.\n\nWatch the vendors, products, packages and CVEs you run. Each refresh\ncompares them with the last check and records what changed: new CVEs, KEV\nlistings, ransomware use, EPSS jumps, new exploits or Metasploit modules,\nCVSS changes, newly available fixes and ENISA exploitation reports. The\nfirst check of an item records a silent baseline. The list lives only on\nthis machine (`~/.cve-intel/watch.db`, owner-only). While the app is open\nit can refresh on a schedule (every 6 hours by default; change or turn it\noff in **Settings**). AI agents can read the watchlist over MCP but cannot\nchange it.\n\nEvery tool says what is risky. None remembers what you decided, why, and\nwhether the reasons still hold. **Decisions** does. Press **Record\ndecision** on a triage result, a scan finding or a comparison, choose a\nverdict (patch now, defer until a date, accept the risk, not affected,\nmitigated) and tick the assumptions it rests on. The machine-checked\nones are pre-ticked from today's evidence: not in CISA KEV, EPSS below a\nthreshold, no public exploit, no Metasploit module, local access only,\nneeds privileges, needs user interaction, no fix yet, not marked exploited\nby ENISA, no ransomware use, CVSS below a threshold, the sources agree,\nNVD has not analysed it yet. The manual ones (not internet-facing, behind\na WAF, a compensating control, not reachable, the vendor says not\naffected, or your own words) carry a review date.\n\nRecording a decision adds the CVE to the watchlist, and every refresh\nre-checks the assumptions. The day the CVE enters KEV, EPSS crosses the\nthreshold, an exploit or a fix appears, or NVD publishes its analysis, the\ndecision turns **stale** with the exact reason, an event lands in the\nwatchlist feed, and the Landscape counts it under **Decisions to\nrevisit**. A deferral past its date is **expired**; a manual assumption\npast its review date is **review due**. Re-decide replaces a decision and\nkeeps the old one as history; Close records whether it was patched,\naccepted for good, won't be fixed, or other.\n\nThe ledger also tells you how your judgment held up: of the CVEs you held\nback in the last 30, 90 or 365 days, how many later entered KEV, gained\nan exploit or rose in EPSS, and how many days after the decision; of the\npatch-now calls, how many were confirmed by KEV, an exploit or a high\nEPSS at the time or since. Export the ledger as OpenVEX or CycloneDX VEX\nfor scanners and SBOM consumers (the CycloneDX document lists each\ndecided-on package as a component, so its references resolve in\nDependency-Track and the like). It lives only on this machine\n(`~/.cve-intel/decisions.db`, owner-only); AI agents can read it over MCP\n(`list_decisions`, `get_decision_calibration`) but never change it, and\n**Ask AI** mentions your decision when you ask about a CVE you decided on.\nFrom the terminal: `cve-intel decide record CVE-2025-12345 --verdict defer --until 2026-12-31 --auto`, then `decide list`, `decide check`,\n`decide calibration` and `decide export`.\n\nOne lookup across NVD, CVE.org, EPSS, CISA KEV, ENISA EUVD and public\nexploit sources. The result includes the risk score, a plain recommendation\nand urgency, and the evidence behind it: CVSS (and where it came from),\n30-day EPSS probability and its recent trend, KEV dates, ENISA's exploited\nflag, CIRCL sightings (deep triage), and the exploit evidence found in\nMetasploit, Exploit-DB, Nuclei, GitHub, PoC-in-GitHub and, with a\nVulnCheck token, VulnCheck KEV and XDB. When NVD has not scored a CVE yet,\nthe CNA's or CISA's score from the CVE.org record is used. Deep triage\nalso returns a CISA SSVC decision, using CISA's own published SSVC\nassessment (Vulnrichment) where one exists. ENISA EUVD or VulnCheck KEV\ncan raise SSVC Exploitation to `active`; they do not change the risk\nscore.\n\n**Who says what.** Every triage result also lays the sources side by side:\nNVD's own score and analysis status, the CNA's score, CISA's ADP\n(Vulnrichment) score and SSVC assessment, EPSS, CISA KEV, ENISA EUVD,\nVulnCheck KEV and, in deep triage, Microsoft, Red Hat and Ubuntu (press\n**Check vendors** on a standard triage to add them). It names where they\ndisagree: scores 2 or more points apart, a CVE that NVD has not analysed\n(common since NVD limited its analysis in 2026), a critical score that\nattackers have ignored for six months, exploitation reported by a source\nother than CISA KEV, a distribution that says its build is not affected or\nwill not be fixed, and rejected or disputed CVEs. The card is marked\n**Sources agree**, **Sources disagree** or **Thin evidence**, and the\nsame appears as the **Agreement** row in **Compare CVEs**, in the\n`consensus` field of `triage_cve`, and in the CLI's triage output. None of\nit changes the risk score.\n\n**Exploit speed.** EPSS is a daily statistical model and the exploit\nindexes record what already exists; both lag. With language models\nreading patches, the public fix commit of an open-source CVE is itself a\nleading signal. A standard or deep triage therefore shows an **Exploit\nspeed** estimate: **Hours**, **Days**, **Weeks**, **Unknown**, or\n**Exploit exists** when a PoC or a KEV listing already makes the question\nmoot. It starts at 30 points and adds or subtracts for the fix (a small,\nlocalised public fix with a test that encodes the trigger counts most; no\npublic fix at all counts against), the weakness class (injection,\ntraversal, authentication bypass and deserialisation are fast; memory\ncorruption and races are slow), the CVSS vector (network, no privileges,\nno user interaction) and the time already elapsed without a PoC. Every\nline of the rationale is shown, the label says *estimate*, the confidence\nnever exceeds *medium*, and without a public fix the label is capped at\nDays. Fix commits come from the references NVD, CVE.org, OSV and GitHub\nAdvisories tag as the patch and are read from GitHub (two requests per\nCVE at most; a free token raises the limit from 60 to 5,000 an hour). The\nsame estimate is a row in **Compare CVEs**, a chip on the riskiest\nunexploited findings of a scan, the `exploit_speed` field of `triage_cve`\nand `scan_dependencies`, and the fix date on `get_cve_timeline`. It never\nchanges the risk score.\n\nThe interface follows your system's light or dark theme until you pick one\nwith the sun and moon button at the bottom of the sidebar. Beside it,\n**A−** and **A+** make the text and controls smaller or larger in every\nview (`⌘ −`, `⌘ +` and `⌘ 0` on macOS; `Ctrl` on Windows and Linux), and\nthe size is remembered.\n\nAsk questions such as *\"Which is worse: CVE-2024-3400 or CVE-2023-44487?\"*\nCVE Intel runs the lookups first, then the model explains the results and\nlists the tools it used. Small local models can still get details wrong, so\ncheck an answer you will act on against **CVE Triage**.\n\nPaste 2 to 10 CVE IDs to compare them and get a patch order based on KEV\nstatus, score, EPSS and exploit evidence, not on CVSS alone. Not sure where\nto start? The examples under the box (**KEV vs. CVSS**, **VPN & firewall\nzero-days**, **Microsoft patch day** and **Open-source libraries**) each\nshow one way the order can surprise you.\n\nCISA KEV CVEs come first, then the risk score. Equal scores are common (exploited CVEs with a high EPSS all reach 100), so ties are broken by known ransomware use, EPSS, exploit maturity, CVSS and the earlier KEV due date. Each CVE says why it sits above the next one.\n\n- **Side by side** : one column per CVE, with rows for the score's parts, KEV\ndates, ransomware use, who reports exploitation, EPSS and its 30-day trend,\nexploit sources, CVSS attack vector, complexity, privileges, user interaction\nand impact, product, CWE and age. Riskier values that differ are in red.**Only rows that differ** hides the rest.\n- **What they have in common** : CVEs in the same product (one update may cover\nthem) or from the same vendor, ransomware use, exploitation reported outside\nCISA KEV (which the score doesn't count), network access without sign-in or\nuser action, public exploits, rising EPSS, and shared weaknesses.\n\nDrop a project folder or dependency files anywhere on the window, or use\n**Choose folder…** / **Choose files…**. A folder is searched, including\nsubfolders, for the lockfiles, manifests and SBOMs listed below. The search\nskips `node_modules`, virtualenvs, `vendor`, build output and hidden\nfolders, and skips a `package.json` or `go.sum` that sits next to the\nlockfile that pins it. Each file found is listed with its format and\npackage count. Untick any you don't want, then press **Scan**. Every file is\nparsed on its own, a package listed in several files is checked once, and\neach finding names the files it came from. Files are read on your machine;\nonly package names and versions are sent to OSV.dev.\n\nYou can also paste a lockfile (`package-lock.json`, `yarn.lock`, `Pipfile.lock`,\n`poetry.lock`, `uv.lock`, `Cargo.lock`, `go.sum`, `go.mod`, `composer.lock`,\n`Gemfile.lock`), an SBOM (CycloneDX JSON or XML, SPDX JSON or tag-value), a\n`requirements.txt`, `package.json` or `pom.xml`, purls, or\n`name:ecosystem:version` lines (for example from `apk info -v` or\n`dpkg -l`; Alpine needs its release, as in `openssl:Alpine:v3.19:3.1.4-r0`).\nThe format is detected automatically and up to 10,000 packages are checked\nagainst OSV.dev.\n\nFindings are ranked by risk, not just severity. Each one gets the same\nsignals as **CVE Triage**: whether its CVE is in CISA KEV (and used by\nransomware), its EPSS score, exploit evidence from Exploit-DB and\nMetasploit, and the [risk score](#risk-score). Log4Shell in an old\n`log4j-core` comes out on top; a CVSS 9.8 nobody exploits does not. When\nGitHub, PyPI and a distribution each publish the same issue, it is shown\nonce. Filter by risk, KEV or whether a fix exists, or switch to **By\npackage** to see each vulnerable package with its advisories and the\nversion that fixes them. In a CI pipeline the same scan can fail the build\nor feed GitHub code scanning; see [CI and automation](#ci-and-automation).\n\nEvery scan is saved in **History**, on this computer only. Scan the same\nfolder again (or press **Scan again**) and the results say what changed\nsince the scan before: findings that are new, resolved (and whether an\nupgrade or a removal fixed them), or riskier because they were added to\nCISA KEV, gained an exploit or jumped in EPSS. A pasted list is saved under\na hash of its packages, never its text. **Copy as Markdown** puts the\nfindings table on the clipboard for a ticket, and **Forget** deletes every\nscan of a target.\n\n**Save SBOM** writes the scan you just ran as a CycloneDX 1.5 document:\nevery package or app it read, clean ones included, each finding as a\nvulnerability affecting its component with the risk signals (KEV, EPSS,\nexploit evidence, risk score) and the fix version, and your recorded\n[decision](#decisions) on it as the `analysis`. It is a scan-derived\ninventory (what the lockfiles, image or this computer declared, with no\nsupplier, hashes, licences or dependency graph), and says so in its\nmetadata; a build-time generator such as Syft or cdxgen remains the\nauthoritative source for those. Load it into Dependency-Track, attach it to\na release, or hand it to an auditor. The same document comes from\n`cve-intel scan deps . --format cyclonedx` on the command line.\n\n**Chains.** A ranked list hides chains: a LOW local privilege escalation\nand a HIGH network RCE on the same host are a full compromise together.\nThe **Chains** tab of every scan links the findings of a target into\nattack chains, from network entry through code execution, privilege\nescalation, credential access or persistence to an outcome. Each step\nnames its basis: the CVSS vector (network, no privileges, scope change),\nthe weakness, CTID's curated KEV → ATT&CK mapping, or an inference from\nthe weakness through CAPEC. Chains get a transparent score (stages\ncovered, the riskiest step, an exploited entry, an unfixed privilege\nescalation) that never touches a finding's risk score, and the callout\nat the top names the **break point**: the finding whose fix cuts the most\nchains, which may well be that LOW. On this computer and in a container\nimage a chain may start at code execution, since code already runs\nthere. Every result states its assumptions: all findings of a target are\ntreated as present together, and nothing is known about reachability or\nmitigations. The chains are in the scan's Markdown, in `scan … --chains`\nand `scans show … --chains` on the command line, and in the read-only\n`get_scan_chains` tool for local agents.\n\n**Watch all affected** adds the affected packages and apps of a scan to\nthe [Watchlist](#watchlist), riskiest first, so you hear when one of them\nis added to CISA KEV or gains an exploit. Tick **Monitor** next to a target\nin History to have CVE Intel scan it again every day while the app is open\n(the same folders, this computer, the same image or the same exposure\ntargets); what becomes new or riskier appears in the Watchlist feed and on\nthe Landscape.\n\n**Scan → This computer** checks the operating system and the apps installed\non this machine. On Windows they come from the registry (the programs in\n**Installed apps**, including per-user installs) and the Windows build; on\nmacOS from **Applications**, **~/Applications**, Homebrew (Apple silicon and\nIntel) and the macOS version. **List installed software** shows what was\nfound and what will be checked, without contacting anything. **Check**\nsends NVD only the vendor, product and version of the apps CVE Intel\nrecognises (browsers, Java, Acrobat, archivers, remote-access tools, VPN\nclients, developer tools and about 100 more) and of the OS, then ranks the\nfindings like any other scan.\n\nApps CVE Intel does not recognise are listed as not checked, with the\nreason. Tick **Also look up apps CVE Intel does not recognise** to ask NVD's\nproduct dictionary for them: this sends their names to NVD, and a match is\nkept only when NVD's vendor fits the app's publisher. Without an NVD API key\nNVD allows a few requests a minute, so a first scan checks the riskiest\napps (browsers, Java, Acrobat, the OS) first and leaves the rest for the\nnext scan; answers are cached, so later scans are quicker. Programs that are\nparts of others (system components, drivers) are skipped, and Microsoft 365\nand the Visual C++ runtimes are reported as not checked because NVD lists\nthem without versions.\n\n**Scan → Container image** checks a saved image without Docker: drop a\n`docker save` or OCI archive (`.tar`, `.tar.gz`) on the window, or choose an\nOCI layout folder. The image is read on your computer in one pass, layer by\nlayer, without unpacking anything to disk. Its operating system packages\n(Debian, Ubuntu, Alpine, Wolfi, Chainguard, Red Hat, Rocky, AlmaLinux, Azure\nLinux and openSUSE) and any lockfiles, manifests or SBOMs inside it are\nchecked with OSV.dev and ranked like any other scan. A multi-platform image\nis scanned for this computer's architecture unless you name another\nplatform. Images whose distribution OSV does not cover (Fedora, Amazon\nLinux, SUSE Linux Enterprise, Debian testing) and older rpm databases are\nlisted as not checked rather than reported clean.\n\n```\ndocker save myapp:latest -o myapp.tar\ncve-intel scan image myapp.tar --fail-on kev\n```\n\n**Scan → Public exposure** shows what public sources already know about\ndomains and addresses you own. Enter domains or public IP addresses, confirm\nthey are yours (or that you are authorised to assess them), and press **Find\naddresses**: CVE Intel collects host names from certificate transparency\nlogs (crt.sh, keeping only names under your domain), resolves them, and\nlists the public addresses, dropping private and reserved ones. Untick any\nthat are not yours, then press **Check**. For each address it asks Shodan\n(with a Shodan key) or the free Shodan InternetDB what services, software\nversions and CVEs have been seen there, then checks the versions with NVD\nand ranks the findings like any other scan.\n\nThe check is passive: CVE Intel never connects to the targets, and nothing is port-scanned. Addresses that belong to a CDN or hosting platform are flagged and left out, because the software seen there is the provider's. CVEs Shodan infers from a banner are marked as reported, not verified, and distribution builds (Ubuntu, Debian, RHEL) may have the fix backported.\n\n```\ncve-intel scan exposure example.com --authorized --list-only   # names and addresses only\ncve-intel scan exposure example.com 203.0.113.10 --authorized --max-ips 20\n```\n\nSee every upstream source: what it provides, whether it needs a key, whether\nyour key is set, how long results are cached, and which tools use it. Press\n**Check connectivity** to probe all of them live. The view also shows the\nlocal cache, downloaded models and the model runtime.\n\nGive AI agents CVE Intel's 41 tools while they work. Start the server from the app, choose your agent, and copy setup steps with the correct address and executable path already filled in. Guides are included for Claude Code, Cursor, VS Code, Claude Desktop, Windsurf and any other MCP client.\n\n- **Two ways to connect.** The agent can connect over HTTP to the server the\napp runs, or launch its own copy over stdio. The stdio option works even\nwhen the app is closed.\n- **Simple control.** Start and stop the server, pick a port (8000 by\ndefault), and optionally start it whenever the app opens. The sidebar\nshows whether it is running.\n- **Local only.** The server listens on`127.0.0.1` and refuses requests\nfrom web pages, so websites and other computers cannot use it.\n- **Uses your saved keys.** Agents get the same data sources and API keys\nyou configured in**Settings** .\n\nTo configure an agent by hand instead, see\n[MCP server setup](#mcp-server-setup).\n\n- **Quick Find** (`⌘K` or`Ctrl+K` ): paste a CVE, IP, hash, domain, URL or`package:ecosystem:version` and CVE Intel picks the right lookup.\n- **Fixed versions:** the version to upgrade a package to so that every\nknown vulnerability is fixed, re-checked against OSV. Quick Find`lodash:npm:4.17.15` to see it, or ask in**Ask AI** .\n- **Product and KEV search:** every CVE affecting a product and version,\nexploited ones first, and filters over the CISA KEV catalog by vendor,\nproduct, ransomware use or date. Available in**Ask AI** , the CLI and MCP.\n- **MITRE ATT&CK mapping:** curated CTID mappings for KEV-listed CVEs, plus\ntechniques inferred from the CVE's weaknesses through CAPEC, labelled as\ninferred. Available to AI agents over MCP and through the REST API.\n- **IP, hash and domain intelligence** from AbuseIPDB, GreyNoise, Shodan,\nVirusTotal, MalwareBazaar, crt.sh and more. Private and internal IPs are\nrejected before any lookup is made.\n- **Activity** view: a searchable local history of your lookups, answers\nand the tool calls agents made, which you can pause or clear.\n- **Local Model** view: install the runtime and download a model in one click.\n- **System** view: health and version information.\n\n| Situation | What to do in the app | \n|---|---|\n| What happened this week? | Open **Landscape** , or ask*\"What's new this week?\"* in**Ask AI** . | \n| A new CVE is in the news. Do we drop everything? | Enter it in **CVE Triage** , or ask*\"Should we patch CVE-2024-3400 this weekend?\"* in**Ask AI** . | \n| We run Fortinet (or another vendor). Tell me when something new hits it. | Add the vendor on **Watchlist** , or press**Watch** next to the vendor on a triage result. | \n| We decided not to patch something yet. Tell me if that stops being safe. | Press **Record decision** on the triage result and tick the reasons.**Decisions** marks it stale the moment one of them breaks. | \n| A scanner reported 40 findings. Which come first? | Paste the IDs into **Compare CVEs** , up to 10 at a time. | \n| Checking dependencies before a release. | Drop the project folder on **Scan** , or paste the lockfile or SBOM. Press**Watch all affected** to follow them, or**Monitor** in History to have it scanned again daily. | \n| Is anything installed on this laptop being exploited? | **Scan → This computer** , then**Check** . Findings in CISA KEV come first. | \n| Is the image we ship affected by a new KEV entry? | `docker save` it and drop the`.tar` on**Scan → Container image** . | \n| What does the internet see on our servers? | **Scan → Public exposure** with your domain; passive, nothing connects to your hosts. | \n| Which version of a library fixes everything? | Open **Quick Find** and paste`lodash:npm:4.17.15` . | \n| What is known about the Tomcat version we run? | Ask *\"Which CVEs affect Apache Tomcat 9.0.80?\"* in**Ask AI** .¹ | \n| Is anything from a vendor being exploited right now? | Ask *\"Which Fortinet vulnerabilities are in CISA KEV?\"* in**Ask AI** .¹ | \n| An unknown IP appears in firewall or login logs. | Paste it into **Quick Find** . | \n| EDR flags an unknown file. | Paste its SHA-256 hash into **Quick Find** . | \n| You work in an AI coding tool. | Open **MCP Server** , start the server and copy the setup steps for your agent. | \n| You are new to vulnerability management. | Ask *\"Explain EPSS and CISA KEV like I'm new.\"* | \n\n¹ For these questions the model has to pick the right lookup itself, which\nlarger local models and cloud providers do more reliably. The same searches\nare always available from the terminal (see [Recipes](#recipes)).\n\nDownload the file for your OS from the\n[latest release](https://github.com/Fazmin/cve-intel/releases/latest). The\ndesktop app, CLI, MCP server and REST API are all **one executable**, with\nnothing else to install.\n\n| OS | File | How to run | \n|---|---|---|\n| Windows | `CVE-Intel_<version>_windows-x64-setup.exe` (or`…-portable.exe` ) | Run the installer, then open **CVE Intel** | \n| macOS (Apple Silicon and Intel) | `CVE-Intel_<version>_macos-universal.dmg` | Drag **CVE Intel** to Applications | \n| Linux | `CVE-Intel_<version>_linux-x64.AppImage` (or`.deb` ) | `chmod +x` the file and run it | \n\nEach file has a `.sha256` checksum next to it. Builds are not code-signed\nyet, so Windows SmartScreen and macOS Gatekeeper warn on first launch. On\nmacOS, right-click the app and choose **Open**.\n\nTo build it yourself or run the headless server in Docker, see\n[Build from source and Docker](#build-from-source-and-docker).\n\n**Ask AI** uses a small language model that runs on your computer, so your\nquestions stay private. Before the model runs, CVE Intel finds the CVE IDs,\nIPs, hashes and domains in your question, runs the matching lookups and\ngives the model the results as facts to rely on. If no model is running,\nAsk returns those lookup results directly, so it is useful before any\ndownload finishes.\n\nOpen the **Local Model** view to install the llama.cpp runtime and download\na model, one click each (files go under `~/.cve-intel/`). The default is\nQwen 2.5 3B Instruct, a ~1.9 GB download that needs 6 GB of RAM; the 1B and\n1.5B models need 4 GB and Qwen 2.5 7B needs 10 GB. On Apple silicon the view\nalso offers two MLX models that run on the GPU and answer faster. The model\nserver listens on `127.0.0.1` only. Already running Ollama, LM Studio or\nyour own llama-server? See\n[Use your own model server](#use-your-own-model-server).\n\nFor stronger answers, choose OpenAI, Anthropic or Google Gemini under\n**Settings → AI provider**, pick a model and paste your API key. While one\nis selected, each question and its lookup results are sent to that vendor\nunder their terms, and the Ask view shows a banner. Keys stay in\n`~/.cve-intel/settings.db` with owner-only permissions and are never shown\nor logged (see [SECURITY.md](https://github.com/Fazmin/cve-intel/blob/main/SECURITY.md)). All three are called through\ntheir OpenAI-compatible chat APIs; for Claude-specific features, use CVE\nIntel through MCP in a Claude client.\n\nThe **Databases** view lists all 40 sources, and the CLI, REST API and MCP\nserver report the same list.\n\n| Category | Sources | \n|---|---|\n| Vulnerability intelligence | NVD, NVD change history, CVE.org, CISA Vulnrichment, EPSS (FIRST) and its daily score files, CISA KEV, ENISA EUVD, VulnCheck NVD++, VulnCheck KEV, MSRC, Red Hat, Ubuntu | \n| Exploit intelligence | GitHub PoC search, PoC-in-GitHub (nomi-sec), Exploit-DB, Metasploit modules, Nuclei templates, GitHub commits and pull requests (fix size for the exploit-speed estimate), Project Zero 0day In the Wild | \n| Network intelligence | AbuseIPDB, GreyNoise, Shodan, crt.sh, CIRCL Passive DNS | \n| Threat intelligence | VirusTotal, MalwareBazaar, ThreatFox, URLScan, CISA advisories (RSS), CIRCL Vulnerability-Lookup sightings, Ransomwhere, CIRCL hashlookup | \n| DevSecOps and reference | OSV.dev, GitHub Advisories, MITRE ATT&CK (STIX), CTID KEV → ATT&CK mappings, MITRE CAPEC, HIBP Pwned Passwords | \n\nMany tools need no API key at all: EPSS and its daily files, KEV, ENISA EUVD, CVE.org and CISA Vulnrichment, OSV, CVSS, Exploit-DB, Metasploit, PoC-in-GitHub, Project Zero, CISA advisories, CIRCL sightings, ATT&CK, CAPEC, crt.sh, Ransomwhere, hashlookup, Pwned Passwords, and NVD at a lower rate limit. Large feeds (EPSS daily files, Exploit-DB, Metasploit, ATT&CK, CAPEC, the CTID mappings) are downloaded once, reduced to a small index, and refreshed daily or every few hours.\n\n```\nRisk = CVSS×0.20 + EPSS×0.35 + KEV×0.30 + PoC×0.15   (boosters up to ×1.27, capped at 100)\n```\n\n- **KEV override:** a CVE in CISA KEV is confirmed exploited, so it is always**CRITICAL** with a score of at least 76. Only CISA KEV earns the KEV\npoints and the override.\n- EPSS measures the probability of exploitation. CVSS is treated as severity, not likelihood.\n- **PoC** is the strongest public exploit evidence. A Metasploit exploit\nmodule counts as weaponized (the full 15 points); Exploit-DB entries and\nVulnCheck XDB exploits count as public exploits.\n- Deep triage also returns the **SSVC v2** CISA Deployer decision:`Act` ,`Attend` ,`Track*` or`Track` . Its inputs come from CISA's published\nSSVC assessment when there is one. Because that assessment is a snapshot,\nnewer evidence can raise Exploitation: a CISA KEV, VulnCheck KEV or ENISA\nEUVD exploited listing, or an EPSS of 0.90 or more, makes it`active` .\nEUVD and VulnCheck do not change the risk score.\n- Bands: 0–25 LOW, 26–50 MEDIUM, 51–75 HIGH, 76–100 CRITICAL.\n- This is scoring version 1.1, reported as `scoring_version` in results.\n\nKeys are optional. Each one unlocks more data or raises a rate limit. In the\napp, open **Settings → Data source API keys**, press **Get a key** to open\nthe sign-up page, paste the key and press **Save**. The key is used on the\nnext lookup, with no restart needed.\n\n| Key | What it unlocks | Get it | \n|---|---|---|\n| NVD API key | 10× faster CVE lookups | [nvd.nist.gov](https://nvd.nist.gov/developers/request-an-api-key) | \n| GitHub token (no scopes) | Exploit search, Nuclei templates and advisory fixed versions (5,000 instead of 60 requests/hour) | [github.com/settings/tokens](https://github.com/settings/tokens) | \n| VulnCheck token | VulnCheck KEV (exploitation reports and XDB exploit links), and backup CVE data if NVD is down | [vulncheck.com](https://www.vulncheck.com/community) | \n| AbuseIPDB key | IP abuse score | [abuseipdb.com](https://www.abuseipdb.com/api) | \n| GreyNoise key | Whether an IP is harmless background noise | [docs.greynoise.io](https://docs.greynoise.io/docs/using-the-greynoise-community-api) | \n| Shodan key | Open ports and services on an IP | [account.shodan.io](https://account.shodan.io) | \n| VirusTotal key | 70+ antivirus verdicts for a file hash | [virustotal.com](https://www.virustotal.com/gui/my-apikey) | \n| URLScan key | Higher limits for URL checks | [urlscan.io](https://urlscan.io/docs/api/) | \n| abuse.ch Auth-Key | MalwareBazaar and ThreatFox lookups | [auth.abuse.ch](https://auth.abuse.ch/) | \n| CIRCL passive DNS login | Historical DNS records (access by request) | [circl.lu](https://www.circl.lu/services/passive-dns/) | \n\nKeys are stored in `~/.cve-intel/settings.db` with owner-only permissions\nand shared by the app, CLI, MCP server and REST API on the same machine. A\nkey saved in the app takes precedence over an environment variable. Free\ntiers and sign-up steps are set by each vendor, so check their pages. To\nmanage keys from a terminal or with environment variables, see\n[Terminal configuration](#terminal-configuration).\n\n- All network traffic is outbound HTTPS: to the data sources, to the cloud\nAI provider if you opt in to one, and for the model and runtime\ndownloads you start (Hugging Face, the llama.cpp release on GitHub and,\nfor MLX, `uv` and a Python 3.12 build from GitHub plus`mlx-lm` from\nPyPI).\n- API keys are never logged, cached, shown in the UI or returned by any tool.\n- Private and reserved IPs are rejected before any network lookup.\n- The local model server and the app's MCP server bind to loopback only.\n- SQLite files are created on first use: `cache.db` , a disposable lookup\ncache;`~/.cve-intel/settings.db` , which holds keys, provider settings\nand the watchlist auto-refresh interval; and`~/.cve-intel/watch.db` ,\nthe local watchlist (items, snapshots and change events). Clearing the\ncache never touches settings or the watchlist.\n- While the app is open, an optional background task can refresh the\nwatchlist (every 6 hours by default). It only contacts the public\nsources needed for the items you watch, and you can turn it off in\n**Settings** . Nothing runs while the app is closed.\n- The desktop app keeps an activity log in `~/.cve-intel/activity.db` (owner-only). It records what you look up and ask, the answers, setting\nand model changes, the tools agents call through the app's MCP server, and\nwhich hosts each action contacted. API keys are never recorded, only key\nnames. Upstream requests are stored as host and path, without query\nstrings. Open**Activity** to search it, pause it or clear it. It keeps\nthe latest 20,000 entries. The CLI and`cve-intel mcp` record nothing.\n\nSee [SECURITY.md](https://github.com/Fazmin/cve-intel/blob/main/SECURITY.md) for the full security model and how to report\na vulnerability.\n\nEverything in this section is for using CVE Intel from a terminal, scripts, CI pipelines, other programs or AI agents, and for building it yourself. The desktop app needs none of it.\n\n- [The `cve-intel` executable](#the-cve-intel-executable) : where it is and how one file runs every mode\n- [Command line (CLI)](#command-line-cli) : every command, with[recipes](#recipes) for common tasks\n- [CI and automation](#ci-and-automation) : fail a build, upload SARIF to GitHub code scanning, JSON output\n- [REST API](#rest-api) : endpoints and examples\n- [MCP server setup](#mcp-server-setup) : connect AI agents by hand\n- [Terminal configuration](#terminal-configuration) : keys, environment variables, your own model server\n- [Build from source and Docker](#build-from-source-and-docker)\n- [Architecture](#architecture) and[Development and tests](#development-and-tests)\n\nThe desktop app and the command-line tool are the same file. Double-clicking it opens the app; running it with any argument starts the CLI, the MCP server or the REST server instead.\n\n| OS | Executable | \n|---|---|\n| macOS | `/Applications/CVE Intel.app/Contents/MacOS/cve-intel` | \n| Windows (default per-user install) | `%LOCALAPPDATA%\\CVE Intel\\cve-intel.exe` | \n| Linux | `/usr/bin/cve-intel` (`.deb` ), or the downloaded`.AppImage` | \n\n```\n# macOS\n\"/Applications/CVE Intel.app/Contents/MacOS/cve-intel\" triage CVE-2024-3400\n# Linux\n./CVE-Intel_<version>_linux-x64.AppImage triage CVE-2024-3400\n# Windows (default per-user install)\n\"%LOCALAPPDATA%\\CVE Intel\\cve-intel.exe\" triage CVE-2024-3400\n```\n\nOn Windows the executable is a windowed program, so the terminal does not\nwait for it. To see the output in order, use\n`start /wait \"\" \"…\\cve-intel.exe\" triage CVE-2024-3400`, or in PowerShell\n`& \"…\\cve-intel.exe\" … | Out-Host`. MCP clients start it directly and are\nnot affected.\n\nFor servers and containers there is also a headless build without the GUI\n(`cargo build --release -p cve-server`, which produces\n`target/release/cve-intel`). From a source checkout, replace `cve-intel`\nwith `cargo run -p cve-server --`. The examples below assume `cve-intel` is\non your `PATH`.\n\n```\ncve-intel triage CVE-2024-3400 --depth deep\ncve-intel ask \"Should we patch CVE-2021-44228?\" --model qwen2.5-3b\ncve-intel quick-find 185.220.101.34\ncve-intel scan deps .                          # every lockfile, manifest and SBOM here, ranked by risk\ncve-intel scan deps . --fail-on kev            # exit 3 if anything is in CISA KEV\ncve-intel fix lodash npm 4.17.15               # version that fixes every known vulnerability\ncve-intel product confluence_data_center --vendor atlassian --version 8.5.0\ncve-intel kev-search --vendor microsoft --ransomware-only --epss\ncve-intel landscape --days 7                    # what's new; --markdown for a ticket\ncve-intel watch add vendor fortinet\ncve-intel watch refresh && cve-intel watch changes --unread\ncve-intel decide record CVE-2025-12345 --verdict defer --until 2026-12-31 --auto --note \"waiting for the vendor\"\ncve-intel decide list --state needs_attention   # decisions whose reasons stopped holding\ncve-intel decide calibration                    # how your decisions held up\ncve-intel compare CVE-2024-3400 CVE-2023-44487\ncve-intel password-check                       # hidden prompt; only a 5-character hash prefix is sent to HIBP\ncve-intel sources --probe                      # every data source, with live status\n```\n\n| Command | What it does | \n|---|---|\n| `triage <CVE> [--depth quick\\|standard\\|deep]` | Risk score, recommendation, KEV, EPSS and exploit evidence; `deep` adds SSVC | \n| `lookup <CVE>` | The NVD and CVE.org record | \n| `search <keyword> [--severity …] [--limit N]` | Keyword search in NVD | \n| `compare <CVE> <CVE> … [--json]` | Compare 2–10 CVEs: patch order with the reason for each place, and what they have in common | \n| `epss <CVE,CVE,…>` | EPSS scores | \n| `kev <CVE>` | CISA KEV status, and VulnCheck KEV with a token | \n| `kev-search [--vendor] [--product] [--keyword] [--ransomware-only] [--added-since] [--due-before] [--epss]` | Filter the CISA KEV catalog, newest first | \n| `landscape [--days N] [--markdown]` | Threat briefing for the last 1–30 days | \n| `watch add vendor\\|product\\|package\\|cve …` | Watch a vendor, product, package or CVE | \n| `watch list\\|remove\\|refresh\\|changes` | List items, stop watching, refresh, or show recorded changes | \n| `product <name> [--vendor] [--version] [--cpe]` | CVEs affecting a product, KEV-listed first | \n| `fix <package> <ecosystem> <version>` | The version that fixes every known vulnerability | \n| `scan deps <path>… [--format text\\|json\\|sarif\\|markdown\\|cyclonedx] [--fail-on …] [--fail-on-severity …]` | Scan files or folders ( `-` for stdin); findings ranked by risk;`cyclonedx` writes an SBOM with the findings in it. See[CI and automation](#ci-and-automation) | \n| `scan-deps <file> [--sarif]` | Scan one lockfile, SBOM, manifest or package list; prints JSON | \n| `scan exposure <domain\\|ip>… --authorized [--no-subdomains] [--max-ips N] [--list-only]` | Passive public exposure: certificate logs, DNS, and what Shodan or InternetDB has seen on your addresses | \n| `scan image <file or folder> [--platform os/arch] [--list-only]` | A container image ( `docker save` , OCI archive or folder): OS packages and lockfiles, checked with OSV | \n| `scan host [--list-only] [--lookup-unknown] [--max-products N]` | This computer's OS and installed apps, checked with NVD; `--list-only` contacts nothing | \n| `scans list\\|show <id\\|latest>\\|forget <key>` | Saved scans ( `scan … --save` and the app), each with what changed since the scan before | \n| `cvss <vector>` | Score a CVSS vector | \n| `quick-find <anything>` | Detect the input type and run the right lookup | \n| `ip <address>` ,`hash <hash>` ,`domain <name>` | Threat intelligence for an IP, file hash or domain | \n| `password-check` | Check a password against HIBP Pwned Passwords | \n| `ask \"<question>\" [--model …] [--provider …]` | Ask a question; `--provider openai\\|anthropic\\|gemini` uses a cloud model | \n| `models list\\|download\\|remove` ,`llama status\\|install\\|install-mlx` | Set up the local model and its runtime ( `install-mlx` on Apple silicon) | \n| `keys list\\|links\\|set\\|remove` | Manage API keys (see [Terminal configuration](#terminal-configuration) ) | \n| `sources [--probe]` ,`health` ,`clear-cache` | Data sources, health check, clear the lookup cache | \n| `mcp` ,`serve` | Start the MCP server over stdio, or the HTTP server (MCP and REST) | \n\n`triage`, `fix`, `product`, `kev-search`, `landscape`, `watch`, `sources`\nand `ask` print readable text; add `--json` for JSON. `lookup`, `epss` and\n`kev` print text, and the other lookup commands print JSON, ready for `jq`.\nRun `cve-intel <command> --help` for every option.\n\n| Situation | Command | \n|---|---|\n| What happened this week? | `cve-intel landscape --days 7` (add`--markdown` for a ticket) | \n| Watch Fortinet and see what changed | `cve-intel watch add vendor fortinet` then`cve-intel watch refresh` and`cve-intel watch changes --unread` | \n| A new CVE is in the news. Do we drop everything? | `cve-intel triage CVE-2024-3400 --depth deep` | \n| A scanner reported 40 findings. Which come first? | `cve-intel compare CVE-… CVE-…` | \n| Which version of a library fixes everything? | `cve-intel fix lodash npm 4.17.15` | \n| What is known about the Tomcat version we run? | `cve-intel product tomcat --vendor apache --version 9.0.80` | \n| Is anything from a vendor being exploited right now? | `cve-intel kev-search --vendor fortinet --added-since 2026-01-01` | \n| An unknown IP appears in firewall or login logs. | `cve-intel ip 185.220.101.34` | \n| EDR flags an unknown file. | `cve-intel hash <sha256>` checks MalwareBazaar, VirusTotal and CIRCL hashlookup. | \n| Checking dependencies before a release. | `cve-intel scan deps .` | \n\nFail a CI build on the findings that matter. `scan deps` takes files and\nfolders (searched like the app does), ranks the findings by risk and exits\nwith code 3 when a gate trips:\n\n```\ncve-intel scan deps . --fail-on kev                 # anything in CISA KEV\ncve-intel scan deps . --fail-on exploited           # in KEV, or a public or weaponized exploit\ncve-intel scan deps . --fail-on high                # risk HIGH or CRITICAL\ncve-intel scan deps . --fail-on-severity critical   # the advisory's own rating, ignoring risk\n```\n\n| Exit code | Meaning | \n|---|---|\n| 0 | No gate tripped | \n| 1 | An error; or `--strict` and something could not be checked; or a KEV-based gate when CISA KEV could not be loaded | \n| 2 | Wrong command-line arguments | \n| 3 | A gate tripped (change it with `--exit-code N` ) | \n\nThe risk score weighs exploitation, so a CVSS 9.8 that nobody exploits can\nrank LOW. Use `--fail-on-severity` to gate on advisory severity instead, or\nboth. Without `--strict`, anything that could not be checked (a package OSV\nrejected, EPSS or the exploit indexes unreachable) is reported on stderr and\ndoes not fail the build. `--enrich basic` skips the exploit indexes (about\n50 MB, downloaded once a day); on CI runners, cache `CACHE_DB_PATH` to avoid\nfetching them on every run.\n\n`--format markdown` writes a summary table for `$GITHUB_STEP_SUMMARY` or a\npull request comment, `--format json` the full result for `jq`,\n`--format cyclonedx` a CycloneDX 1.5 SBOM of everything scanned with each\nfinding, its risk signals and your decisions attached (for Dependency-Track,\na release artifact or an auditor; it works for `scan image` and `scan host`\ntoo), and `-o FILE` writes to a file:\n\n```\ncve-intel scan deps . --format markdown >> \"$GITHUB_STEP_SUMMARY\"\ncve-intel scan deps requirements.txt --format json | jq '.summary'\ncve-intel scan deps . --format cyclonedx -o sbom.cdx.json\n```\n\nShow the findings in GitHub code scanning (the **Security** tab and pull\nrequest annotations) by uploading SARIF:\n\n```\n# .github/workflows/dependencies.yml\non: [push, pull_request]\npermissions:\n  contents: read\n  security-events: write\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Scan the dependencies with CVE Intel\n        run: cve-intel scan deps . --format sarif -o cve-intel.sarif\n      - uses: github/codeql-action/upload-sarif@v3\n        with:\n          sarif_file: cve-intel.sarif\n          category: cve-intel\n```\n\nThis assumes `cve-intel` is on the runner's `PATH` (for example the release\nAppImage, or `cargo build --release -p cve-server`). Each vulnerability is a\nrule with an OSV link and a `security-severity`. Each result points at the\nfile and line that declares the package, names the advisory and the fixed\nversion, and carries the risk score, KEV status and EPSS. Findings in KEV or\nwith HIGH or CRITICAL risk are errors whatever the advisory's own rating.\n\nGet a machine-readable verdict for a ticket or dashboard:\n\n```\ncve-intel triage CVE-2024-3400 --depth deep --json | jq '.risk | {risk_score, risk_label, urgency}'\n```\n\n`cve-intel serve` starts an HTTP server on `127.0.0.1:8000` (set `HOST` and\n`PORT` to change it) with the REST API under `/api/v1` and MCP at `/mcp`.\nThe server the desktop app starts from **MCP Server** serves the same\nendpoints.\n\n| Method and path | Returns | \n|---|---|\n| `GET /health` | Version, scoring version, NVD and KEV status | \n| `GET /api/v1/triage/{cve_id}?depth=quick\\|standard\\|deep` | The full triage report | \n| `GET /api/v1/cves/{cve_id}` | The NVD and CVE.org record | \n| `GET /api/v1/search?q=…&severity=…&limit=…` | NVD keyword search | \n| `POST /api/v1/quick-find` with`{\"input\": \"…\"}` | Auto-detected lookup | \n| `GET /api/v1/kev` | CISA KEV catalog summary | \n| `GET /api/v1/landscape?days=7` | The threat-landscape briefing ( `format=markdown` for Markdown) | \n| `GET /api/v1/watch` | The local watchlist (read-only) | \n| `GET /api/v1/watch/changes?unread_only=true` | Recorded watchlist changes (read-only) | \n| `GET /api/v1/scans` ,`GET /api/v1/scans/{id}` ,`GET /api/v1/scans/findings?min_risk=HIGH` | Saved scans and their findings (read-only; only on the server the app starts) | \n| `GET /api/v1/tools` | The tools with their input schemas: 38 on the server the app starts, 36 from `cve-intel serve` , which leaves out the scan history tools | \n| `POST /api/v1/tools/{name}` with the tool's arguments | Runs any tool | \n| `GET /api/v1/sources` ,`POST /api/v1/sources/probe` | The source catalog, and live connectivity checks | \n| `DELETE /api/v1/cache` | Clears the lookup cache | \n| `GET /api/v1/models` | The local model catalog | \n| `POST /api/v1/ask` with`{\"question\": \"…\"}` | An Ask answer from the local model | \n| `POST /mcp` | MCP over streamable HTTP | \n\nErrors return HTTP 400 with `{\"error\": \"…\"}`.\n\n```\ncurl -s \"http://127.0.0.1:8000/api/v1/triage/CVE-2024-3400?depth=deep\" | jq '.risk'\n\ncurl -s -X POST http://127.0.0.1:8000/api/v1/tools/find_fixed_version \\\n  -H 'content-type: application/json' \\\n  -d '{\"package\": \"lodash\", \"ecosystem\": \"npm\", \"version\": \"4.17.15\"}'\n\ncurl -s -X POST http://127.0.0.1:8000/api/v1/tools/get_attack_mapping \\\n  -H 'content-type: application/json' -d '{\"cve_id\": \"CVE-2024-34102\"}'\n```\n\n- `/api/v1/ask` only uses the local model (or`CVE_LLM_BASE_URL` ), never a\ncloud provider, so a caller cannot spend your cloud key.\n- `cve-intel serve` has no authentication and allows cross-origin requests,\nso browser front ends can call it. That also means any web page open in\nyour browser can reach it while it runs. Keep it on loopback, stop it when\nyou're done, or put it behind your own authenticated reverse proxy. The\nserver the desktop app starts refuses web pages instead (see below).\n\nMCP is an open protocol and works with many clients, not only Claude. The\neasiest setup is the **MCP Server** view in the desktop app (see\n[MCP server for AI agents](#mcp-server-for-ai-agents)). To configure it by\nhand:\n\n```\n# HTTP: connect to the server started from the app, or from `cve-intel serve`\nclaude mcp add --transport http cve-intel http://127.0.0.1:8000/mcp\n\n# stdio: the agent launches its own copy (macOS app path shown)\nclaude mcp add cve-intel -- \"/Applications/CVE Intel.app/Contents/MacOS/cve-intel\" mcp\n\n# stdio, using the headless binary\nclaude mcp add cve-intel -- /absolute/path/to/target/release/cve-intel mcp\n```\n\nReady-made configs for Claude Code, Claude Desktop, Cursor, VS Code and\nother clients are in [`examples/mcp/`](https://github.com/Fazmin/cve-intel/blob/main/examples/mcp).\n\nThe server exposes 41 tools, resources (`kev://catalog`,\n`epss://scores/{cve_id}`, `manifest://tool-hash`) and prompts\n(`patch_decision`, `compare_and_prioritize`, `dependency_triage`). It never\nregisters a sampling handler or issues `sampling/createMessage`. Older tool\nnames that duplicated other tools (`prioritize_cves`,\n`check_exploit_availability`, `scan_container_packages`,\n`scan_repo_secrets`) are no longer listed but still work. The watchlist\ntools (`list_watchlist`, `get_watchlist_changes`) are read-only: agents\ncannot add, remove or refresh items. The scan history tools (`list_scans`,\n`get_scan_findings`) are read-only too, and only answer local callers: MCP\nover stdio and the server the app starts. `cve-intel serve` accepts\nrequests from any web page, so it does not serve saved scans.\n\nThe server started from the app always binds to `127.0.0.1` and checks the\n`Host`, `Origin` and `Sec-Fetch-Site` headers to refuse cross-site browser\nrequests, which protects against DNS rebinding. It has no sign-in, so any\nprogram on the same computer can use it with your saved keys. Stop it when\nyou don't need it.\n\nManage API keys without the app:\n\n```\ncve-intel keys list                          # which keys are set and where from (never prints values)\ncve-intel keys links                         # where to get each key\ncve-intel keys set SHODAN_KEY                # hidden prompt, keeps the key out of shell history\necho \"$KEY\" | cve-intel keys set SHODAN_KEY  # or pipe it in from a script\ncve-intel keys remove SHODAN_KEY\n```\n\nFor headless use, copy [`.env.example`](https://github.com/Fazmin/cve-intel/blob/main/.env.example) to `.env`, or set\nenvironment variables. Everything works without keys, with fewer results. A\nkey saved in the app takes precedence over an environment variable.\n\n| Purpose | Variables | \n|---|---|\n| Data sources | `NVD_API_KEY` ,`GITHUB_TOKEN` ,`VULNCHECK_TOKEN` ,`ABUSEIPDB_KEY` ,`VIRUSTOTAL_KEY` ,`SHODAN_KEY` ,`GREYNOISE_API_KEY` ,`URLSCAN_KEY` ,`CIRCL_PDNS_USER` ,`CIRCL_PDNS_PASS` ,`ABUSECH_AUTH_KEY` | \n| Cloud AI | `OPENAI_API_KEY` ,`ANTHROPIC_API_KEY` ,`GEMINI_API_KEY` | \n| Local AI | `CVE_LLM_BASE_URL` ,`CVE_LLM_MODEL` ,`LLAMA_SERVER_BIN` ,`MLX_LM_SERVER_BIN` | \n| Storage and server | `CACHE_DB_PATH` ,`CVE_INTEL_HOME` ,`HOST` ,`PORT` ,`REQUEST_TIMEOUT` | \n\nSet `CVE_LLM_BASE_URL` to any OpenAI-compatible endpoint, such as Ollama\n(`http://127.0.0.1:11434/v1`), LM Studio or your own llama-server, and\noptionally `CVE_LLM_MODEL` to the model name. Ask then uses it instead of\nthe built-in runtime. To use a `llama-server` or `mlx_lm.server` you\ninstalled yourself, set `LLAMA_SERVER_BIN` or `MLX_LM_SERVER_BIN` to its\npath. To use a cloud provider from the CLI:\n`cve-intel ask \"Should we patch CVE-2024-3400?\" --provider anthropic`.\n\n```\n# Desktop app (debug)\ncargo build -p cve-intel-desktop\n./target/debug/cve-intel-desktop\n\n# Installable bundle (.dmg / .exe / .AppImage)\ncargo install tauri-cli --version \"^2\" --locked\ncd apps/desktop/src-tauri && cargo tauri build\n\n# Headless binary only (servers, Docker)\ncargo build --release -p cve-server\n```\n\nDocker runs the headless MCP server over HTTP, plus the REST API:\n\n```\ndocker build -t cve-intel .\ndocker run --rm -p 127.0.0.1:8000:8000 --env-file .env cve-intel\ncrates/cve-core     Harness-agnostic engine: 38 source clients, risk scorer,\n                    SSVC, CVSS, validators, lockfile/SBOM parsers, SARIF\n                    and CycloneDX output, SQLite cache, settings DB, activity log and\n                    watchlist, landscape briefing, source catalog,\n                    llama.cpp and MLX manager, cloud-provider settings and\n                    the Ask agent. No MCP, Tauri or CLI types.\ncrates/cve-server   The cve-intel binary: MCP (stdio and streamable HTTP),\n                    REST (/api/v1) and the CLI, as thin adapters over cve-core.\napps/desktop        Tauri app linking cve-core and cve-server natively. The\n                    same executable runs the GUI, the CLI and the MCP server,\n                    and can host MCP over HTTP in-process. The model server\n                    (llama-server, or mlx_lm.server on Apple silicon) is the\n                    only child process.\nexamples/mcp        Client configs for common MCP clients.\ncargo test -p cve-core -p cve-server   # scorer, SSVC, CVSS, validators, cache, parsers, agent routing, source catalog\ncargo test -p cve-core -p cve-server -- --ignored   # live checks against the real sources (network)\ncargo build --release                  # cve-intel and the desktop binary\n```\n\nSee [CONTRIBUTING.md](https://github.com/Fazmin/cve-intel/blob/main/CONTRIBUTING.md) for the full development setup and\nthe checks CI runs.\n\nCVE Intel gathers facts from public sources; it is not the source. When you\nrecord a decision, cite the **primary source and the retrieval date**, not\nthe app or the AI's wording:\n\n*Example (illustrative values):* CVE-2021-44228: CVSS 10.0 (NVD); listed in\nCISA KEV, added 2021-12-10 (CISA); EPSS 0.94 as of 2026-10-18 (FIRST).\nRetrieved 2026-10-18 with CVE Intel 0.3.0, scoring v1.1.\n\n- **Scores change.** EPSS updates daily, KEV grows and NVD entries are\nrevised. Results are cached for minutes to hours, and up to a day for some\nfeeds. The**Databases** view shows each source's cache time.\n- **The risk score is CVE Intel's own.** Cite it as*\"CVE Intel risk score\n(scoring v1.1)\"* alongside the underlying CVSS, EPSS and KEV values.`cve-intel health` and the**System** view show the version.\n- **An AI answer is not evidence.** Local or cloud, a model can be wrong.\nCite the data shown beside the answer and verify it against the source.\n\n```\n@software{cve_intel,\n  title   = {CVE Intel: local security intelligence for CVE triage},\n  author  = {{CVE Intel contributors}},\n  year    = {2026},\n  version = {0.3.0},\n  url     = {https://github.com/Fazmin/cve-intel},\n  license = {MIT OR Apache-2.0},\n  note    = {Native Rust desktop app, CLI, MCP server and REST API}\n}\n```\n\nUse the version you ran (`cve-intel --version`).\n\nCVE Intel only queries these services. It does not own or republish their data, and their terms apply to anything you copy out of the app. Check each provider's current terms, especially before commercial use. This is not legal advice.\n\n| Source | Credit and terms | \n|---|---|\n| **NVD** (NIST) | Products using the NVD API should state: *\"This product uses data from the NVD API but is not endorsed or certified by the NVD.\"* See the[terms of use](https://nvd.nist.gov/developers/terms-of-use) . | \n| **EPSS** (FIRST) | Attribute FIRST and link [first.org/epss](https://www.first.org/epss/) . Daily score files are hosted at[epss.empiricalsecurity.com](https://epss.empiricalsecurity.com) . | \n| **CVSS** (FIRST) | [first.org/cvss](https://www.first.org/cvss/) | \n| **CISA KEV** | Credit CISA: [Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) . | \n| **ENISA EUVD** | EU Vulnerability Database: [euvd.enisa.europa.eu](https://euvd.enisa.europa.eu/) . Subject to ENISA's terms. | \n| **CISA advisories** | RSS feed of CISA alerts and ICS advisories: [cisa.gov](https://www.cisa.gov/news-events/cybersecurity-advisories) . | \n| **PoC-in-GitHub** | Repository index by [nomi-sec/PoC-in-GitHub](https://github.com/nomi-sec/PoC-in-GitHub) . Repositories are listed, not scanned. | \n| **Project Zero 0day In the Wild** | Google Project Zero's public spreadsheet: [0day.html](https://googleprojectzero.blogspot.com/p/0day.html) . | \n| **CIRCL Vulnerability-Lookup** | Sightings from [vulnerability.circl.lu](https://vulnerability.circl.lu/) . | \n| **CVE.org** | CVE records are provided under the [CVE Terms of Use](https://www.cve.org/Legal/TermsOfUse) . CVE® is a registered trademark of The MITRE Corporation. | \n| **CISA Vulnrichment** | CISA's ADP enrichment (SSVC, CVSS, CWE), released under CC0 1.0: [github.com/cisagov/vulnrichment](https://github.com/cisagov/vulnrichment) . | \n| **SSVC** | CERT/CC and CISA: [github.com/CERTCC/SSVC](https://github.com/CERTCC/SSVC) | \n| **VulnCheck KEV, XDB and NVD++** | Shown with VulnCheck's attribution, *\"VulnCheck KEV (VulnCheck Known Exploited Vulnerabilities), [https://vulncheck.com/kev](https://vulncheck.com/kev)\"* . Use is subject to[VulnCheck's terms](https://vulncheck.com/terms) . | \n| **Metasploit Framework** | Module metadata from [rapid7/metasploit-framework](https://github.com/rapid7/metasploit-framework) , BSD-3-Clause. | \n| **MITRE ATT&CK®** | Registered trademark of The MITRE Corporation. See the [terms of use](https://attack.mitre.org/resources/terms-of-use/) . | \n| **MITRE CAPEC™** | Attack patterns from [capec.mitre.org](https://capec.mitre.org) ; see the[terms of use](https://capec.mitre.org/about/termsofuse.html) . | \n| **CTID Mappings Explorer** | KEV → ATT&CK mappings by the Center for Threat-Informed Defense, Apache-2.0: [mappings-explorer](https://github.com/center-for-threat-informed-defense/mappings-explorer) . | \n| **OSV.dev** ,**GitHub Advisory Database** | Attribution varies by database; the GitHub Advisory Database is CC BY 4.0. See [osv.dev](https://osv.dev) and[github.com/advisories](https://github.com/advisories) . | \n| **abuse.ch** (MalwareBazaar, ThreatFox) | Community data; see [abuse.ch](https://abuse.ch) . | \n| Others | VirusTotal, Shodan, AbuseIPDB, GreyNoise, URLScan, CIRCL, Red Hat, Ubuntu, Microsoft MSRC, crt.sh, Exploit-DB, Ransomwhere and HIBP each have their own terms and rate limits. Free tiers are often limited to non-commercial use. | \n\n**Local AI models** are not part of this project and carry their own\nlicences, such as the Llama 3.2 Community License and size-dependent Qwen\nlicences. Read the model's page before commercial use. GGUF files come from\nthe Hugging Face repositories listed in `crates/cve-core/src/llm.rs` (the\nvendors' own for Qwen, bartowski's builds for Llama), and MLX builds from\nthe [mlx-community](https://huggingface.co/mlx-community) conversions. The\nruntimes are [llama.cpp](https://github.com/ggml-org/llama.cpp) (MIT) and,\non Apple silicon, [mlx-lm](https://github.com/ml-explore/mlx-lm) (MIT).\n\n- [CONTRIBUTING.md](https://github.com/Fazmin/cve-intel/blob/main/CONTRIBUTING.md) : development setup and pull request guidelines\n- [CODE_OF_CONDUCT.md](https://github.com/Fazmin/cve-intel/blob/main/CODE_OF_CONDUCT.md) : community standards\n- [SECURITY.md](https://github.com/Fazmin/cve-intel/blob/main/SECURITY.md) : reporting a vulnerability privately\n\nCopyright 2024-2025 Fazmin Nizam. Licensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](https://github.com/Fazmin/cve-intel/blob/main/LICENSE-APACHE) or[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) )\n- MIT License ([LICENSE-MIT](https://github.com/Fazmin/cve-intel/blob/main/LICENSE-MIT) or[https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) )\n\nat your option. See also [NOTICE](https://github.com/Fazmin/cve-intel/blob/main/NOTICE).\n\nThese licenses cover the CVE Intel code. Data and models the app downloads\nkeep their own terms; see [Data source terms](#data-source-terms).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.", "url": "https://wpnews.pro/news/show-hn-i-built-a-local-first-cve-triage-app-in-rust", "canonical_source": "https://github.com/Fazmin/cve-intel", "published_at": "2026-10-29 17:58:41+00:00", "updated_at": "2026-10-29 18:17:38.907329+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "developer-tools", "ai-safety"], "entities": ["CVE Intel", "Rust", "CISA", "FIRST", "ENISA", "NIST", "National Vulnerability Database", "Mandiant"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-i-built-a-local-first-cve-triage-app-in-rust", "markdown": "https://wpnews.pro/news/show-hn-i-built-a-local-first-cve-triage-app-in-rust.md", "text": "https://wpnews.pro/news/show-hn-i-built-a-local-first-cve-triage-app-in-rust.txt", "jsonld": "https://wpnews.pro/news/show-hn-i-built-a-local-first-cve-triage-app-in-rust.jsonld"}}