Reachability Analysis: The Six Types, and Which One Works on a Binary
Learn how reachability analysis helps manufacturers cut through CVE overload, focus on real threats, and meet EU Cyber Resilience Act requirements efficiently.

Dario Lobozzo
GM, EMEA
The EU Cyber Resilience Act (CRA) is changing the way software-defined product manufacturers approach security. Unlike legacy compliance frameworks that assess point-in-time risks, the CRA demands continuous monitoring, vulnerability disclosure, and evidence-backed assurance that products remain secure throughout their lifecycle. For many manufacturers, that mandate translates into a single, daunting reality: thousands of vulnerabilities to manage, report, and remediate—often across decades-old codebases and global product portfolios.
Prioritizing that level of risk isn’t just difficult, it’s nearly impossible without the right context. That’s where reachability analysis becomes essential. By helping teams understand which vulnerabilities are actually exploitable within a product’s architecture, reachability transforms CRA readiness from a theoretical exercise into a scalable, repeatable program.
What Is Reachability Analysis?
Reachability analysis determines whether the vulnerable code in a component can actually be executed in your product, rather than merely being present in it.
A conventional scan matches component versions against a vulnerability database and reports everything it finds. It answers whether a vulnerable library exists in your software. Reachability answers a narrower and more useful question: can anything in your product actually call the flawed code?
When the answer is no, the finding drops out of your remediation queue with a documented reason. When the answer is yes, it moves up.
The classic illustration is CVE-2014-6071, a cross-site scripting flaw in jQuery. It only triggers when a developer uses the text() method inside after(), a pattern almost nobody writes. The library is present, the CVE is real, a patch exists, and filtering on severity or fix availability keeps it on your list forever. Reachability analysis checks whether your code uses that specific combination and, if not, retires the finding.
Multiply that by 581 and you have the case for the technique.
How Reachability Analysis Works
Every implementation runs roughly the same four steps. What separates them is the evidence available at step three.
- Identify the vulnerabilities. Match components against vulnerability databases, including transitive dependencies nobody selected deliberately.
- Map what the product actually executes. Establish which code paths run, which functions get called, and which components load.
- Determine whether the two intersect. Trace whether an execution path reaches the vulnerable code specifically, not just the component containing it.
- Report with evidence. Produce the determination and the reasoning behind it, because a conclusion an engineer cannot audit is a conclusion nobody will act on.
Step three is where the six types diverge, and where most of the difference in accuracy lives.
The Three Analysis Approaches
Static analysis examines the code or the binary without running it. It integrates early, runs in a pipeline, and needs no deployed environment. Its limit is that it reasons about what could execute rather than what does.
Dynamic analysis watches the software run, usually through an agent or instrumentation. It sees actual behavior, which removes guesswork, at the cost of deploying agents and only observing the scenarios that actually occurred during monitoring.
Binary analysis examines the compiled artifact directly. It requires neither source code nor a running agent, which matters when the code came from a supplier who will not share source and the device is a sealed product in a customer's facility.
Application security tooling is built around the first two. Device manufacturers usually only have access to the third.
The Six Types of Reachability Analysis
| Type | What it asks | What it needs | Works on firmware? |
|---|---|---|---|
| Dependency-level | Is the package imported anywhere? | A manifest file | No |
| Function-level | Is the vulnerable function called? | Application source code | No |
| Package baselining | Is the package behaving abnormally? | A runtime agent | No |
| Internet reachability | How exposed is the host running it? | Cloud topology | No |
| Package used in image | Is the package present and running in the image? | A container image | No |
| Binary-level | Is the vulnerable code present and callable in what shipped? | The firmware image | Yes |
Dependency-level reachability
The coarsest form. It checks whether the vulnerable package is imported anywhere in the application, without examining how. Better than nothing, and genuinely useful for finding dependencies you can delete outright, but it leaves you with a pile of findings marked potentially reachable and a manual research job.
Function-level reachability
The precise form, and the one that made the category matter. It traces whether your code calls the specific vulnerable function, ideally through transitive dependencies and full call chains rather than stopping at the direct dependency or the class boundary.
It is also genuinely hard to build. Endor Labs, which does this well, has written that many CVE records simply do not contain function-level detail, and that the company maps vulnerable functions to CVEs manually across every affected version. Attempts to shortcut that with pattern matching or by having a language model read CVE descriptions run into the same missing data.
Function-level reachability also has a ceiling that is worth understanding before you rely on it. Endor Labs uses CVE-2022-23307 to make the point: the flaw sits in particular Log4j 1.2.x functions, but only becomes exploitable in combination with Apache Chainsaw, which is application context no call graph contains.
Package baselining
Rather than tracing code paths, this watches what a library does at runtime and flags departures from its normal behavior. A logging library making outbound network calls is doing something it has no business doing.
This is a strong runtime protection mechanism and a weak prioritization mechanism. If you imported a library and your code calls it, learning that it is also running tells you very little you did not already know.
Internet reachability
Prioritizes by how exposed the host is. Intuitive, widely marketed, and frequently misleading, because exploitability depends on permissions and usage context rather than hop count from the public internet. A privilege escalation flaw matters wherever the over-permissioned account lives, not wherever the load balancer sits.
Useful as a secondary filter once you already know how a vulnerability is exploited. Poor as a primary one.
Package used in image
Checks whether a package is present and running inside a container image. Its real value is subtractive: finding packages nobody uses so you can strip them out and remove the vulnerability rather than triage it.
Binary-level reachability
The five above assume a repository or a cloud. A connected device offers neither. There is no manifest, because embedded C and C++ have no standard package manager. There is no source, because a chipset vendor or board support package supplier compiled it. There is no agent, because the device is sealed and in the field. There is no container.
Binary-level reachability works on the shipped artifact instead. It asks whether the vulnerable function is present in the binary at all, whether the component is statically or dynamically linked, what the call graph around it looks like, and how the kernel modules are configured. Those signals combine into a judgment about whether the vulnerable code can be reached in the product as built.
Two things make this the only workable option for firmware. It needs no cooperation from a supplier, and it describes the artifact that actually shipped rather than the one the build system intended to produce.
What Reachability Analysis Does Not Tell You
The technique gets oversold, so it is worth being precise about the limits.
Reachable is not the same as exploitable. A reachable finding means your product can execute the vulnerable code. Whether an attacker can drive it to do something harmful is a further question involving input handling, privileges, and deployment context. Treating reachability as a verdict on exploitability overstates it.
Application context defeats it sometimes. The Log4j and Chainsaw case above is the standard example. Some exploit conditions live outside anything a call graph can see.
Malicious packages are a different problem. Reachability sorts known-vulnerable code by whether it executes. A package written to be malicious does not sort that way, and it usually has no CVE when it arrives. Deprioritizing a compromised dependency because it looked unreachable is the failure mode to avoid. Our guide to software supply chain security best practices covers screening for those separately.
Unreachable today is not unreachable forever. A firmware update, a configuration change, or a newly enabled feature can make previously dead code live. Reachability determinations need regenerating on every release, not filing once.
Precision and coverage trade against each other. Deeper analysis costs time and can still miss cases. An over-eager tool floods engineers with false positives; a conservative one produces false confidence.
None of this argues against using reachability. It argues for treating it as one input into prioritization rather than the answer.
Reachability Analysis Under the Cyber Resilience Act
The regulatory case changed on September 11, 2026, when Article 14 of the EU Cyber Resilience Act took effect. Manufacturers of products with digital elements on the EU market now report actively exploited vulnerabilities and severe incidents through the CRA Single Reporting Platform, with an early warning inside 24 hours, a fuller notification inside 72 hours, and a final report within 14 days of a corrective measure becoming available.
Article 14 is a reporting duty rather than a remediation duty. The broader obligations, vulnerability handling and technical documentation among them, arrive with full application on December 11, 2027.
Both dates create the same operational pressure. On a 24 hour clock you need to know within hours whether a newly disclosed CVE touches your shipped products and whether it is reachable in them. That determination cannot begin after the notification arrives.
Reachability also produces the artifact that makes a deprioritization defensible. Stating that a vulnerability is not exploitable in your product is a claim. Stating that the vulnerable function is absent from the shipped binary, with the evidence attached, is a record, and it is the kind of justification a VEX document exists to carry.
How to Evaluate a Reachability Claim
Every vendor in this market says the word. These questions separate the implementations.
- How deep does it go? Class level, function level, or the full call chain including the surrounding usage context?
- Does it cover transitive dependencies? A direct dependency can pull in dozens of indirect ones, and the indirect ones are where the unreviewed code lives.
- How far back does the vulnerable-function data reach? Reachability depends on knowing which functions a CVE affects. Coverage starting in 2023 and coverage starting in 2018 produce very different results on a product with a decade of history.
- What does it need from you? Source code, a manifest, a running agent, or the shipped artifact. This is the question that decides whether it works on your product at all.
- Does it show its reasoning? A determination without an evidence trail cannot be audited by your engineers or defended to an assessor.
- Does it run on every release? A one-time assessment describes a product you have since changed.
Run a proof of concept against your own firmware rather than a demo environment. Demo data is selected to make the tool look good.
Key Takeaways
- Six techniques share one name. They differ enormously in precision, and vendors rarely specify which they mean.
- Five of the six need source, a manifest, an agent, or a container. A firmware image supplies none of those.
- Function-level is the most precise of the source-based methods, and it is limited by CVE records that frequently omit which functions are affected.
- Binary-level reachability is the option that works on shipped firmware, because it reads the artifact instead of the build inputs.
- Reachable does not mean exploitable. Reachability narrows the queue. It does not settle the risk question on its own.
- Malicious packages sit outside the model. Do not let an unreachable determination downgrade a compromised dependency.
- Article 14 has applied since September 11, 2026. A 24 hour reporting clock assumes you can already answer whether a CVE reaches your products.
Where to Start
One first move. Take your current vulnerability list for a single shipped product and sort it by a question you probably cannot answer yet: for each finding, is the vulnerable function actually present in the binary you shipped? The proportion you cannot answer is the size of the gap.
Three questions worth putting to your team this month:
- When our scanner marks something reachable, what evidence sits behind that, and could an engineer check it?
- How many of our components arrived as supplier binaries, and what method are we using to assess reachability in those?
- If a CVE dropped tomorrow on a library in a 2021 SKU, how long before we could say whether it is reachable?
Finite State performs reachability analysis on the shipped binary, using symbol presence, linking behavior, call graph analysis, and kernel configuration, and returns the evidence behind each determination rather than a score alone. No source code required. To see it run against your own firmware, request a walkthrough.