Boottrace

Which CVEs really matter in your firmware (and which you can justify don't)

A scanner gives you hundreds of CVEs. The CRA asks for no known exploitable vulnerabilities. How to get from one list to the other: KEV, EPSS, severity and, above all, the context of your device.

Run a scanner on any embedded Linux image and you’ll get hundreds of CVEs. The Cyber Resilience Act doesn’t ask you to bring that list to zero. It asks that the product be placed on the market without known exploitable vulnerabilities (Annex I) and that you handle new ones throughout the support period. The word that matters is exploitable.

This article is the method to get from the scanner’s list to that other, much shorter one: what to fix now, what can wait, and what you can justify in writing doesn’t affect you.

Why severity isn’t enough

The scanner’s “Critical / High” column is the CVSS base score. It measures how serious the vulnerability is in the abstract, knowing nothing about your device. Two examples of what it misses:

  • A critical CVE in a library function your firmware never calls weighs the same as one in the function your web server uses.
  • The attack vector is part of the score (AV:N is network, AV:L local, AV:P physical access), but the scanner doesn’t know whether your device has that port open, that USB port reachable, or anyone with a shell.

Severity helps you order within a group. It doesn’t tell you what matters.

Two outside signals: KEV and EPSS

Before looking at the device, cross the list with two free public sources:

Common scanners already include them: Grype, for example, adds EPSS and KEV to each result. One important nuance: EPSS is for ordering, not for dismissing. A low probability doesn’t mean it doesn’t affect you, only that nobody is exploiting it at scale today.

And a link to the regulation: since 11 September 2026, if a vulnerability in your product is being actively exploited, you have 24 hours to send an early warning. Watching KEV and the EUVD against the SBOM of every release you’ve shipped is the most direct way to find out in time.

What no catalogue knows: your device

This is where the list really shrinks. For each remaining CVE, five questions, in this order:

  1. Is the component in the image? It sounds obvious, but scanners that only look at versions often get it wrong: packages with the same name, build tools that never reach the rootfs.
  2. Is the vulnerable code built? Many CVEs affect an optional feature: a kernel module, a PACKAGECONFIG option in Yocto, a library backend. If your build doesn’t include it, it doesn’t affect you.
  3. Does it run? The binary may be in the image without any service using it.
  4. Can an attacker reach it? An image-parsing bug matters if your device processes images from outside; a bug in a service matters if that service listens on the network. This is where open ports, physical interfaces and the origin of the data it processes come in.
  5. Is something mitigating it? The service only listens on localhost, runs unprivileged, sits behind a firewall that can’t be disabled, or the vulnerable option is turned off in the configuration.

Every “no” is a dismissal, and every dismissal has a standard name. VEX formats (OpenVEX, CycloneDX, CSAF) use almost the same justifications as those questions: component not present, vulnerable code not present, vulnerable code not in execute path, vulnerable code cannot be controlled by adversary, inline mitigations already exist. Whatever you write must be checkable by someone else: “nscd is not installed” works; “we don’t think it applies” doesn’t.

The kernel

The kernel deserves its own section. Since February 2024 the project itself is a CVE Numbering Authority and assigns one to almost any fix that may have security impact: its policy starts from the idea that almost any kernel bug could end up being exploitable. The result is thousands of CVEs a year (over five thousand in 2025, according to Greg Kroah-Hartman’s figures) and a product kernel that piles up hundreds.

Two filters cut them down a lot:

  • The stable branch. For each CVE, the project publishes which stable versions fix it (the vulns repository on kernel.org). If your kernel is an up-to-date LTS, many are already closed even though the scanner, which only sees “6.6”, doesn’t know.
  • Your .config. Many kernel CVEs are in specific drivers and subsystems. Matching the files each fix touches against what your configuration builds, a good share falls at question 2.

What’s left after those two filters is what needs a manual look. And the bigger decision, whether to move to the next stable release or to a newer branch, comes out of that.

A working order

With all of the above, the queue looks like this:

  1. Exploited (KEV or EUVD) in components that are present: fix now and assess whether you have to report.
  2. Network-exposed services (SSH, web server, MQTT broker, management API) with a network attack vector, ordered by EPSS.
  3. Code that processes outside data: TLS, format parsers, image or compression libraries.
  4. The kernel, already filtered by stable branch and configuration.
  5. The rest: documented in your VEX with its justification, and reviewed with every new release.

Step 5 isn’t wasted work. It’s exactly the evidence the CRA expects to see in the technical documentation, and what you’ll show when a customer or an authority asks why your image “has 300 CVEs”. How to declare it in the build is in the previous article, on how to get the SBOM of your firmware.

If you’d rather we do it

That triage is the core of our Quick Scan: you send us the image, we cross the SBOM with KEV, EPSS, the kernel data and your device’s configuration, and within 48 business hours you get the vulnerabilities that really apply, the justified dismissals and what’s missing for the CRA. If you’d rather go through your case first, book 30 minutes.

Does your product have to comply with the CRA?

Start with a €1,900 Quick Scan or book 30 minutes to talk it through.

← All articles