threat-finder – open-source runtime CVE scanner
OffSeq open-source tools
threat-finder is an open-source, Rust command-line scanner from OffSeq that finds CVEs in the software actually running on a host — not what a manifest claims — and ranks them by how network-reachable each affected service is, so operators fix what an attacker can actually touch first.
2025 4 min read
§ 01. What it is
threat-finder is a command-line runtime vulnerability scanner written in Rust and published by OffSeq under a dual MIT / Apache-2.0 license. Rather than parsing a project manifest or lockfile, it inspects the software that is genuinely present and running on a host, resolves each service to an exact package coordinate, and reports the CVEs that affect it.
The central design goal is to answer a narrower, more actionable question than a generic scanner: of everything that is vulnerable on this machine, which findings are attached to services that are actually reachable over the network? It is one of the public tools OffSeq develops and uses during engagements, and ships as a library crate (find_threats) with a thin CLI wrapper so it can be embedded as well as run directly.
It runs on Linux (systemd, SysV, OpenRC with dpkg/rpm/pacman/apk), macOS (Homebrew), the BSDs, Solaris/illumos, and Windows (PowerShell with registry, winget, Appx, Chocolatey, Scoop, npm, pip and dotnet mapping). Installation is via Homebrew tap, cargo binstall, cargo install, or prebuilt archives.
§ 02. How it works
By default the tool enumerates running services; with --scope all it additionally walks every installed OS package. Each asset is converted into a precise Package-URL that carries the full version — including epoch and distro revision — and a distro qualifier, for example pkg:deb/ubuntu/openssh-server@1:8.9p1-3ubuntu0.6?distro=jammy. That inventory is matched against the OffSeq Radar catalog using ecosystem-native version rules, so backported security fixes are not mistaken for vulnerable builds — a common source of false positives when a scanner compares version strings naively.
For exposure, threat-finder maps each running service's process to the sockets it is listening on — /proc/net on Linux, lsof on the other Unixes, Get-NetTCPConnection or netstat on Windows — and classifies reachability as loopback, private, or public. This is done by reading local state; no packets are sent during assessment, so it does not probe or scan the network. A vulnerable daemon bound to 0.0.0.0 is therefore treated very differently from the same daemon bound to 127.0.0.1.
Findings are then scored 0–100 and placed into SSVC-style decision bands — act-now, soon, schedule, track — combining severity, EPSS probability, CISA KEV known-exploited status, and the asset's measured network exposure. Output is emitted as deterministic JSON (confirmed findings, unconfirmed triage matches, per-asset exposure data, per-CVE rollups, and errors) and as SARIF 2.1.0 for code-scanning UIs.
§ 03. Why it matters
Most vulnerability tooling reports on what is installed or what a dependency file declares, producing long lists that mix idle packages, patched-but-not-yet-upgraded versions, and services that are only listening on localhost. The result is a backlog that is hard to triage and easy to deprioritize incorrectly.
threat-finder narrows this to what is running and, crucially, what is reachable. Correlating each CVE with a specific listening socket and its exposure class lets an operator distinguish a critical bug on an internet-facing service from the identical bug on a loopback-only helper. Combined with KEV and EPSS signals, exposure-aware ranking pushes the genuinely urgent, exploitable, externally-reachable issues to the top.
The ecosystem-native version matching also directly reduces alert fatigue: distributions routinely backport fixes without changing the upstream version number, and flagging those as vulnerable is a frequent way scanners lose operator trust. Matching on exact distro coordinates avoids that class of false positive.
§ 04. Using it
Set an OFFSEQ_API_KEY environment variable and run threat-finder; the default scan covers running services and their correlatable exposure. --scope all expands to every installed package (a 10–50x increase in assets), --severity filters by level, and --strict drops unconfirmed matches.
For automation, --fail-on any|critical|high|medium|low|kev|exposed makes the process exit non-zero (exit code 5) when a threshold is met, which fits CI and scheduled-host checks; other exit codes distinguish an error (1), a missing key (2), an unsupported OS (3), and rate limiting (4). --json prints the full report to stdout, and on Windows --windows-missing-updates lists pending security updates.
--register enables continuous monitoring: a host's coordinates are registered once with Radar so that newly published CVEs affecting them trigger alerts — via email and console, ordered by exposure — without needing to re-scan, and host inventory drift is tracked over time. The project is structured to extend toward lockfiles, containers, and SBOMs in future versions.