Vulnerability Research

Vulnerability Reachability Analysis: Is the Code Exposed?

A proof based guide to static and runtime reachability, VEX decisions, blind spots, and remediation order.

Chris Seymour, Co-Founder and Principal at Artemes AI
Chris Seymour
Co-Founder, Principal
Jul 26, 2026 10 min read
Vulnerability reachability analysis ladder from dependency presence to a satisfied attack trigger

The problem is not whether a vulnerable library exists in the build. Vulnerability reachability analysis asks whether an attacker can drive execution from a real entry point into the affected code.

Presence is a useful warning. It is not proof of a path. A package may be installed but unused, a vulnerable method may never be called, or a route may exist without attacker controlled input.

Reachability narrows the question. It does not finish exploitability. Teams still need configuration, access, trigger conditions, controls, consequence, and a fix decision.

Infographic

Presence is not a path

Each layer adds evidence, but only the full chain supports an urgent exploitability claim.

Vulnerability reachability proof ladderFive connected layers move from a vulnerable dependency being present, to a vulnerable symbol being called, to an entry point, attacker control, and a satisfied trigger condition. Side branches show static evidence, runtime evidence, and deployment evidence.1 · COMPONENT PRESENTManifest, lockfile, binary, SBOM2 · VULNERABLE SYMBOL CALLEDCall graph reaches the affected function3 · REAL ENTRY POINT EXISTSRoute, queue, CLI, file, plugin, job4 · ATTACKER CONTROLS THE INPUTAccess, identity, data flow, trust boundary5 · TRIGGER CONDITION CAN SUCCEEDConfiguration, state, privileges, controlsReachable does not automatically mean exploitableSTATICCall graphData flowSymbol mapBroad coverageRUNTIMELoaded codeTracesTest coverageNarrow observationRecord the path, uncertainty, source revision, owner, and expiration

What is vulnerability reachability analysis?

Vulnerability reachability analysis determines whether an application can execute a code element associated with a known vulnerability. For dependency findings, it usually connects a vulnerable symbol in a third party component to application code through a call graph, data flow, runtime trace, or a combination.

This is narrower than vulnerability exploitability. A call path can exist while the attacker lacks access, the input is constant, a required configuration is disabled, or a control blocks the trigger. The exploitability evidence guide covers the rest of that chain.

Reachability is also narrower than dependency use. Importing a package or loading a module shows activity. It does not prove the affected function receives data from an entry point.

Why does code reachability change vulnerability priority?

Software composition analysis starts with component identity and version. That gives broad coverage, which is valuable. It also creates a predictable problem: one vulnerable dependency can generate findings in every application that carries it, even when only a small subset calls the affected code.

Reachability turns a package match into a path claim. A confirmed path deserves faster review because the application already connects to the vulnerable symbol. A credible unreachable result can justify a different schedule, provided the evidence is recorded and rechecked when code changes.

The distinction matters most when the fix is expensive. A major dependency upgrade can require refactoring, regression tests, rollout work, and a rollback plan. Spend that effort first where the path exists. Do not use reachability to leave obsolete software in place forever.

How do static and runtime reachability differ?

Static analysis examines code without executing it. It builds possible calls from application entry points through direct and transitive dependencies. Its strength is coverage. Its weakness is precision when languages use reflection, dynamic dispatch, generated code, native bindings, callbacks, or configuration selected at runtime.

Runtime analysis observes what executes during tests or production activity. Its strength is proof that a path ran. Its weakness is coverage. A route used once each quarter will look absent during a seven day observation. An attack path may never appear in normal tests.

MethodStrong claimBlind spotBest use
Manifest or SBOMComponent is declared or detectedNo function pathBroad inventory
Static call graphA possible code path existsDynamic behavior and feasibilityEarly review in CI
Data flowInput can propagate toward a sinkRuntime configuration and controlsAttacker influence review
Runtime traceThe path executed in this observationUntested and rare pathsConfirmation and coverage gaps
Controlled trigger testThe condition can be invoked safelyProduction differencesLab validation

Combine methods. Static analysis finds possible paths. Runtime evidence confirms some of them. Tests target gaps. Deployment evidence checks whether the entry point and required configuration exist where the application runs.

How do you perform vulnerability reachability analysis?

Use a review that an engineer can repeat after the next code change.

  1. Identify the affected symbol. Find the function, class, module, code range, or behavior named by the maintainer or advisory.
  2. Resolve the exact component. Confirm package URL, version, artifact, fix commit, and whether the vulnerable code exists in the built output.
  3. Enumerate entry points. Include web routes, message consumers, scheduled jobs, file parsers, plugins, command interfaces, and exported APIs.
  4. Build possible paths. Trace calls and data flow from entry points to the affected symbol across direct and transitive dependencies.
  5. Test feasibility. Check attacker control, required state, privileges, configuration, and controls.
  6. Record the decision. Store path evidence, uncertainty, source revision, owner, action, and expiration.

If the advisory does not identify an affected symbol, say so. Package level reachability may be the strongest available claim. Do not invent function precision from a vague CVE description.

Which entry points should reachability analysis include?

Start with places where data or control enters the application. Web handlers are obvious. Message consumers, file imports, scheduled work, administration commands, plugin hooks, template engines, deserializers, and exported library methods are easier to miss. A service with no public route may still process attacker supplied data from a queue.

Build the entry point list from framework registration, deployment configuration, API descriptions, queue bindings, command definitions, and runtime traces. Do not rely on source file names. A function calledinternalImport can receive a file uploaded through another service. A route calledhealth can invoke far more code than its name suggests.

Trust boundaries belong in the map. Mark whether an entry point accepts anonymous internet traffic, authenticated customer data, partner messages, internal service input, administrator actions, or local files. Then trace which fields remain under attacker influence. A call to the affected symbol is more urgent when the attacker controls the argument that triggers the flaw.

Include nonproduction paths when they can reach production secrets, artifacts, or deployment authority. A build worker that parses an untrusted pull request may offer a shorter path to impact than the production service. Reachability follows execution and trust, not environment labels.

Version the inventory. New routes and jobs should trigger analysis. Removed entry points should not close a finding until the deployed artifact and routing state confirm the removal. This prevents a source branch from becoming evidence for a production state that does not exist yet.

What can reachability analysis miss?

Reflection and dynamic loading can hide calls from static analysis. Native code can cross a boundary the analyzer does not understand. Framework inversion can make a library call application code rather than the other way around. Deserialization, templates, plugin registration, and generated routes add more gaps.

Build and runtime differences matter too. Feature flags, environment variables, dependency injection, optional modules, and platform specific code can change the graph. A source result from the main branch may not describe the artifact running in production.

Runtime evidence has the opposite failure. It proves what happened, not everything that can happen. Low traffic jobs, disaster recovery paths, admin functions, and attacker supplied inputs may remain unobserved.

Use three result states: reachable, not shown reachable, and proven not reachable under named conditions. The middle state is uncertainty. Treating it as safe is how a useful analysis becomes a false negative machine.

How should reachability evidence appear in VEX?

Vulnerability Exploitability eXchange, or VEX, carries product specific status and reasoning. CycloneDX's official SBOM guide provides a VEX example with state set to not_affected and justification set to code_not_reachable.

{
  "analysis": {
    "state": "not_affected",
    "justification": "code_not_reachable",
    "response": ["will_not_fix"],
    "detail": "Static call graph found no path from registered entry points at commit 8c14. Recheck on dependency or route change."
  }
}

The syntax is the easy part. The detail should name the method, source revision, entry point coverage, uncertainty, and recheck trigger. A permanent not_affected claim based on an old scan is weak evidence.

OASIS makes the accountability requirement explicit in the CSAF version 2.0 VEX profile. A product marked known_not_affected needs an impact statement explaining why the vulnerability cannot be exploited. Status without reason does not meet the intent.

What does a reachability decision look like?

A vulnerable parsing function appears in a common Java library used by 80 services. A package scan opens 80 findings.

  • Six services call the affected parser from internet facing upload routes.
  • Four call the parser only from an authenticated internal import job.
  • Fifty include the library through a framework but never reference the parser in the static graph.
  • Twenty have incomplete graphs because reflection and generated configuration hide the binding.

The first six need urgent validation and remediation. The next four need a shorter clock tied to identity and input controls. The 50 can receive a documented lower schedule with recheck triggers. The 20 remain unknown and need targeted runtime tests. They are not safe.

Assume a major upgrade takes three engineer hours per service. Treating all 80 as immediate work consumes 240 hours. Completing the first ten paths consumes 30 hours, while targeted analysis of the 20 unknowns at 30 minutes each adds ten. That directs 40 hours toward evidence and current paths before committing the remaining 200. The upgrade may still happen. The sequence is better.

What changed in the last year?

CISA published its 2025 Minimum Elements for a Software Bill of Materials on August 22, 2025. The guidance says VEX and CSAF can correlate with SBOM data to narrow the scope of software components at risk. That puts product context beside inventory instead of treating the SBOM as a final risk answer.

OWASP also expanded vulnerable and outdated components into A03:2025 Software Supply Chain Failures. Its published category data says exactly 50 percent of survey respondents ranked the category first. The score table contains 215,248 occurrences and an average incidence rate of 5.72 percent.

Inventory is becoming richer and the supply chain problem is becoming broader. The operational gap is proof: which component, which path, which deployed product, and which action.

How should reachability affect remediation policy?

Use reachability to order work, not erase obligations. A reachable KEV path on an exposed service should jump the queue. A proven unreachable path can take a normal upgrade clock if policy permits. Unknown stays visible.

Measure the policy with three numbers. Count the share of package findings with symbol level coverage, the share of reachable results that lead to completed action, and the share of not reachable results later reversed by a code or deployment change. The reversal rate is not automatically failure. An undocumented reversal is.

Add expiration rules. Recheck when the dependency version changes, a new entry point appears, build configuration changes, an analyzer gains coverage, or new exploit evidence changes the trigger model. Link the result to the vulnerability risk scoring model as a local evidence input, not a universal zero.

Artemes uses deep endpoint context with AI driven analysis to compare vulnerable software with actual runtime and configuration state. For application code, keep the same discipline: the model can explain a path, but the underlying graph, artifact, and deployment evidence must remain inspectable.

Frequently asked questions

Does an installed vulnerable dependency mean the code is reachable?

No. Installation proves presence. Reachability needs a call or data path from application code or an entry point to the affected symbol.

Does reachable code mean the vulnerability is exploitable?

No. Exploitability also depends on attacker control, access, configuration, trigger conditions, controls, and the reliability of the attack.

Is static or runtime reachability better?

Neither is complete. Static analysis offers broader possible coverage. Runtime analysis proves observed execution. Combine them and document each method's blind spots.

How long is a not reachable decision valid?

Only until a named trigger changes the evidence. Common triggers include a dependency update, new route, build change, feature enablement, or improved analyzer coverage.

Executive takeaway

Take the 25 dependency findings with the highest fix cost. Require an affected symbol, call path, entry point, attacker influence, deployment proof, uncertainty, and expiration. Route reachable paths first. Keep unknowns visible. A package match starts the investigation. It should not end it.

Artemes AI

See which of your findings actually matter

Artemes AI combines deep endpoint context with AI-driven analysis to show which findings are actually exploitable on your hosts—not just everything a scanner can list. We are onboarding early access teams now.

Chris Seymour, Co-Founder and Principal at Artemes AI

Chris Seymour

Co-Founder, Principal

Chris writes about vulnerability prioritization, exploitability, AI-assisted remediation, and the engineering realities of turning scanner output into remediation decisions.

Context-Aware Scanning
Risk-Based Prioritization
CVE Analysis
Found this useful? Share it.