Why Static Reachability Isn’t Enough for CVE Remediation

Why Static Reachability Isn’t Enough for CVE Remediation

Most CVE remediation tools can tell you that a vulnerability could be exploited. Few can confirm whether it actually is. A scanner flags the same CVE in two services and marks both as vulnerable. Only one of them ever runs the flawed code in production. That gap, reachable in theory versus reachable in fact, is the real problem, and static analysis alone cannot close it.

Key Takeaways

  • CVE remediation is triage under volume, not patching. Vulnerability disclosures hit a record 48,000+ new CVEs in 2025, per an independent analysis of CVE Program data, roughly 131 a day, and no security team clears that list on the day each one appears.
  • Static reachability analysis (the current best practice, most SCA and ASPM tools ship) confirms a vulnerable function is present in the call graph. It cannot confirm that the function actually executes under real traffic, configuration, and data.
  • AI-generated code is expanding the attack surface faster than security reviews can keep pace, while AI is simultaneously accelerating the rate at which disclosed CVEs are weaponized into working exploits.
  • A vulnerability assessment performed once at build time goes stale the moment new code ships or a feature flag changes, because reachability is a live property of a running system, not a fixed one.
  • Runtime-confirmed reachability turns a blanket 14-day emergency patch across every affected service into an evidence-backed decision: patch what actually executes now, schedule what does not.

What Is CVE Remediation?

Remediation Is Triage, Not Just Patching

A CVE (Common Vulnerabilities and Exposures) is a unique identifier issued by MITRE for a publicly disclosed software flaw. CVE remediation is the end-to-end process of finding a known vulnerability in the software a team actually runs, deciding how urgently it needs to be addressed, applying a fix, and confirming that the fix held. Patching is one remediation path among several. Depending on where the vulnerability lives, remediation can also mean:

  • Upgrading the version of the affected dependency to a patched release
  • Rebuilding a container image to pull in an updated base OS package
  • Disabling a feature flag that gates the vulnerable code path
  • Accepting the risk with a documented exception, when the code was never actually invoked

Consider a team running an internal reporting service that gets a critical CVE alert for a transitive logging dependency. The instinct is to patch immediately. But the vulnerable code path only fires when a specific logging appender is enabled, and this service ships with that appender disabled by default.

The right remediation here isn’t a patch at all, it’s confirming the flag stays off, documenting the exception, and moving the front-line queue to whichever other services actually run with that appender turned on. 

Remediation, in this case, means triage before it means code change, and getting that triage step wrong in either direction, patching a service that was never exposed or skipping one that was, is exactly what a volume-driven backlog produces without a way to check reachability directly.

Treating remediation as a synonym for patching is how teams end up patching components that were never at risk while a genuinely exploitable path sits further down the backlog.

Where CVSS, EPSS, and KEV Fit Into Prioritization

Because volume is the constraint, not effort, prioritization frameworks exist to rank order the backlog:

  • CVSS scores severity in the abstract, describing how bad a vulnerability could be if triggered
  • EPSS (Exploit Prediction Scoring System) estimates the probability a CVE gets exploited in the wild within the next 30 days, based on observed attacker behavior
  • CISA’s KEV (Known Exploited Vulnerabilities) catalog lists CVEs with confirmed active exploitation, and BOD 22-01 requires federal agencies to remediate KEV-listed vulnerabilities within 14 days, a timeline most private-sector security teams now treat as a de facto benchmark

A CVE with a 9.8 CVSS score, an EPSS probability above 90%, and a spot on the KEV list looks unambiguous; every framework agrees this is critical. But all three scores describe the vulnerability in the abstract, not the deployment in front of a specific team. If the vulnerable function sits behind an admin-only route nobody’s traffic ever reaches, that same CVE poses no actual risk to this particular service, regardless of how severe, how probable, or how actively exploited it is elsewhere. The frameworks rank the vulnerability. Only reachability data ranks the instance of it running in a given service, right now.

All three of these frameworks answer a version of the same question: how dangerous is this vulnerability in general? None of them answer whether the vulnerable code path executes in this specific service, in this specific environment, right now. That is a separate question, and it is the one reachability analysis exists to answer.

Why CVE Remediation Is Getting Harder in the AI Era

AI-Generated Code Ships Dependencies Faster Than Security Can Review Them

AI coding assistants generate features, pull in new libraries, and open pull requests at a pace that has outrun the review processes built for human-speed development. An AI agent asked to add PDF export to a service reaches for a well-known parsing library, pulls it in as a transitive dependency of a transitive dependency, and opens a PR within minutes. 

The PR passes CI, a reviewer approves the feature change without auditing every line of the dependency tree it just expanded, and the library ships to production. Nobody flags a CVE in it, because nobody was specifically looking for one, the review was scoped to the feature, not the supply chain behind it. 

Every new dependency an AI agent introduces is a new potential CVE surface, and most teams do not have a security review gate that runs at the same velocity as the code generation itself. The result is a growing gap between how fast the dependency tree changes and how fast anyone can confirm what those dependencies actually do once the service is running.

AI Is Accelerating Exploitation, Not Just Development

The same acceleration is happening on the attacker side. Rapid7’s 2026 Global Threat Landscape Report found the median time between a vulnerability’s disclosure and its addition to CISA’s KEV catalog fell from 8.5 days to five days year over year, with the mean dropping from 61 days to 28.5 days, evidence that the observed exploitation timeline is compressing right alongside the theoretical one.

A CVE for a widely used parsing library can go from disclosure to a circulating proof-of-concept exploit within the same business day, well before a security team’s weekly triage cadence even surfaces the finding. A remediation process that depends on manual code tracing to confirm exploitability cannot keep pace with an exploitation timeline now measured in days, sometimes hours, rather than weeks. 

The teams still running CVE remediation as a quarterly patch cycle are triaging against a threat model that no longer matches how fast both code and exploits move.

Infographic showing the CVE triage funnel: from CVE detection through CVSS, EPSS, and KEV signals, to a runtime reachability check that determines whether to patch or accept the risk

The CVE Remediation Challenges Security and Engineering Teams Face

1. Too Many CVEs, Not Enough Signal

Security teams cannot patch all CVEs on the day they are detected, and most tooling is built to detect volume rather than filter it. Black Duck’s own research puts the average commercial codebase at over 900 open-source dependencies, and a scan that returns several hundred findings without a way to separate theoretical from confirmed exposure just shifts the triage burden downstream to whichever engineer opens the ticket.

2. Being Reachable Isn’t the Same as Actually Executing

A vulnerable function can sit in your codebase the same way an unlocked door can sit in a house: it’s a genuine risk only if someone actually walks through it. Static reachability analysis checks whether that door exists and whether the application could theoretically reach it, a real improvement over flagging every dependency as equally dangerous. 

But it stops at “the door is unlocked.” It can’t tell you whether anyone ever actually walks through, because a function can be present and technically callable in the code and still never execute in production because:

  • A config flag disables the code path entirely
  • The feature sits behind a permission level nobody actually uses
  • The code only fires under conditions that never occur in the live environment

Static analysis cannot see any of these three conditions, because none of them are visible in the source or the build artifact.

3. Point-in-Time Assessments Go Stale the Moment New Code Ships

A reachability assessment run during a CI/CD scan describes the application as it existed at that commit. Vulnerable code can be added during the next build, a feature flag can be flipped, or a dependency can be dynamically loaded at runtime in ways the static scan never modeled. CVEs discovered or published after that assessment go completely unaddressed by it, because the assessment was never designed to be continuous.

4. Emergency SLAs Force Blanket Fixes Across Unrelated Services

When a CVE lands on the KEV list, the 14-day clock does not distinguish between the service where the vulnerable path fires constantly and the service where it is dead code. Without evidence to separate the two, security teams default to patching everything the scanner flagged, which burns engineering capacity on services that were never actually at risk while adding deployment risk to services that did not need to touch that code path at all.

5. Security and Engineering Work From Different Evidence

Security teams see CVE identifiers, CVSS scores, and dependency trees. Engineering teams see services, deploy pipelines, and handle incident tickets. When a security finding lands in an engineering backlog without runtime context attached, both sides spend time reconstructing the same picture from different starting points, and coordination itself becomes part of the remediation lag.

Why Static Reachability Tools Hit the Same Wall

Most SCA and ASPM platforms that offer reachability analysis build a static call graph from source code or compiled artifacts, then check whether a path exists from an entry point to the vulnerable function. This is useful as a first-pass filter, but it operates entirely on the code as written, not the code as it behaves. Static analysis cannot see:

  • Runtime configuration values that enable or disable the vulnerable path
  • Feature flags are evaluated at request time rather than baked into the build
  • Environment-specific dependency loading that only happens in certain deployments
  • Actual traffic patterns hitting the service, and whether the vulnerable path is ever on the request path at all
  • Code paths that only become reachable after a deployment, the static scan has not yet seen

Every tool in this category converges on the same architectural limitation: they operate exclusively on the source or the build artifact, never on the running system itself. Static analysis tells you what’s possible. The next question, whether this vulnerable path actually runs in production, requires a different kind of evidence entirely.

Comparison diagram of static reachability versus runtime reachability, contrasting build-time call graph analysis with live, continuously updated execution monitoring

That distinction is the whole shift. Static reachability infers behavior from source code. Runtime reachability observes it directly, on the deployed system, as it happens.

How Runtime Reachability Changes the Remediation Math

Confirming Execution, Not Inferring It

Lightrun’s Runtime Sensor instruments a running service in a patented, read-only sandbox and observes whether a specific vulnerable code path actually executes under real production traffic, without a redeployment and without any risk to the running application. Instead of a call graph saying a method could be invoked, the Runtime Sensor confirms:

  • Whether that method was invoked at all
  • How often it is fired, over any window, the team queries
  • Under what conditions, including the runtime configuration and request context in play

That turns a probabilistic finding into a factual one.

Continuous Reassessment Without Redeployment

Because the Runtime Sensor operates against the live service rather than a single build artifact, reachability is no longer a snapshot taken once during a CI/CD scan; it becomes a property that can be checked on demand at any point after deployment. As Lightrun’s own reachability use case describes it, this is how teams “stay ahead of vulnerability backlogs,” cutting the noise from unreachable findings while keeping the assessment current as the running system itself changes.

Validating the Patch Itself Before It Ships

Confirming reachability answers whether a CVE needs fixing now. It does not answer whether the fix itself is safe to merge, and AI-generated patches carry the same unverified-until-proven risk as AI-generated features. 

Lightrun’s Runtime Aware PR Verifier reads the diff for a proposed CVE fix, simulates how that change behaves against live system state, and risk-scores it so you can decide if it’s safe, needs review, or is blocked before it merges.

AI is accelerating vulnerability exploitation on one side of the timeline, and the same acceleration now applies to how fast a patch can be validated against real runtime behavior on the other, closing the loop between confirming the problem and confirming the fix.

Lightrun Hands-On: Confirming Reachability for a Live CVE

The intro described this pattern in the abstract: a scanner flags the same CVE across two services, but only one actually runs the vulnerable code. Here is that pattern with real services attached. 

A scanner flags a jackson-databind polymorphic deserialization CVE, remote code execution when default typing is enabled, one of several dozen individually numbered CVEs that share this exact root cause (CVE-2017-7525) is a representative, well-documented example), in a shared PayloadDeserializer utility pulled into two services through a common internal module: account-service and market-data-service.

Both are flagged as potentially reachable by the static scanner, and both are staring down the same 14-day KEV SLA. 

The on-call engineer opens the Lightrun AI SRE and asks one question: does account-service actually invoke this deserialization path under current traffic?

The same query works identically from inside an AI coding assistant connected to Lightrun MCP; the engineer doesn’t have to leave the IDE to ask it.

Lightrun Snapshot hits panel showing zero captured invocations for account-service, confirming the vulnerable deserialization path is never reached

As you can see in the screenshot above:

  • The vulnerable deserialization method is present in the shared common-model dependency, but the snapshot shows zero captured invocations for account-service, because the code path that calls it is never reached under real traffic
  • The Runtime Sensor confirms this without a redeploy, pulling the answer directly from the running service in the same session

The engineer runs the identical query against market-data-service, where the same shared deserializer is called from a live, internet-facing trade endpoint.

Lightrun stacktrace snapshot showing a live BUY trade order for AAL invoking PayloadDeserializer.deserialize() in market-data-service

The screenshot above shows one real captured invocation: a live BUY order for AAL flowing straight into PayloadDeserializer.deserialize(), real trade data, not a synthetic probe. The snapshot panel itself only retains a sample of individual captures, not a running total, so the full picture comes from the underlying service log, which confirms the shared deserialization method was invoked 1,309 times over roughly an hour of live traffic on market-data-service, while the identical watch on account-service recorded zero.

The two services, flagged identically by the static scanner, resolve to two completely different remediation paths once runtime evidence is applied.

account-service moves into the next scheduled release instead of an emergency deployment. market-data-service gets the same-day patch the KEV SLA calls for.

The fix itself is small: replace the permissive PolymorphicTypeValidator (allowIfBaseType(Object.class)) in PayloadDeserializer with an allowlist that only accepts the concrete types the deserializer is actually expected to handle, closing the path an attacker would use to name an arbitrary class in the payload.

A small diff carries the same unverified-until-proven risk as any AI-assisted change, so before it merges, the Runtime Aware PR Verifier reads the diff against market-data-service’s live behavior: it replays the same trade-submission traffic pattern the Runtime Sensor already confirmed is hitting this line hundreds of times an hour, and confirms the new validator still accepts every legitimate payload shape while rejecting an arbitrary class hint. The patch merges with that evidence attached, not just a passing test suite.

That resolution is what runtime evidence looks like applied to a single confirmed CVE. Zooming out, the same interface can also show the raw scale of the problem before any of it gets triaged.

To see what that volume looks like in practice, the engineer opens Lightrun AI SRE with GitHub repositories connected and asks one question: are there any CVEs in this codebase?

Lightrun AI SRE chat interface listing confirmed CVE findings across five dependencies, including fastjson and keycloak-admin-client, with affected and fixed versions

As you can see in the screenshot above:

  • The scan surfaces CVEs across five separate dependencies in one pass, from fastjson to keycloak-admin-client, each with a specific CVE ID, affected version, and fixed version
  • None of these findings say whether the vulnerable code path is actually invoked under real traffic; that confirmation is the harder problem.The account-service/market-data-service example above solves for one CVE at a time

This is the identification part of the solution, fast and comprehensive. The harder part is confirming which of these findings is real exposure versus dead code, and this is exactly what the reachability check above resolves. 

The account-service and market-data-service example is what that resolution looks like when it’s run against a specific flagged CVE instead of a whole codebase at once.

How Lightrun Addresses Each CVE Remediation Challenge

CVE Remediation Challenge How Lightrun Resolves It
Too many CVEs, not enough signal Runtime reachability confirms actual execution, separating real exposure from scanner noise
Static reachability answers “could,” not “does” The Runtime Sensor observes live execution paths directly inside the running service
Point-in-time assessments go stale Reachability can be reassessed on demand at any point after deployment, without redeploying
Emergency SLAs force blanket patches Evidence-based prioritization lets teams patch what executes now and schedule what does not
Security and engineering work from different evidence A shared runtime evidence trail replaces reconstructed context on both sides
Unverified patches introduce new risk The Runtime Aware PR Verifier risk-scores each CVE fix against live behavior before merge

Governing CVE Remediation: Evidence Trail for Compliance

Every reachability query and every patch validation Lightrun runs produces a structured, auditable record:

  • What was checked, down to the specific method and service
  • What the runtime evidence showed, including invocation counts and the conditions under which the code fired
  • What decision followed from it, whether that was an emergency patch, a scheduled fix, or a documented risk acceptance

For teams operating under SOC 2, HIPAA, or similar frameworks, that trail matters as much as the fix itself, because it turns “we patched what the SLA required” into a documented, defensible remediation decision rather than a best-effort blanket patch.

From Static Guesswork to Runtime Confirmation

CVE remediation has always been a triage problem disguised as a patching problem, and the tooling built to solve it has mostly automated the wrong half of that equation. 

Static reachability improved on flagging every dependency equally, but it still is limited to answering how the code was written, not how the system actually runs. The gap between “theoretically reachable” and “actually exploited” remains open; it just moved one layer deeper into the toolchain.

This gap is architectural. Static analysis, however sophisticated its call-graph modeling gets, is bounded by the artifact it was run against at build time. It cannot observe runtime configuration, feature flags evaluated per request, or dependency behavior that only manifests under live traffic, because that information simply does not exist until the code is running.

As AI accelerates how quickly new dependencies ship and how quickly disclosed CVEs get weaponized, runtime-confirmed reachability compounds in value at both ends of the remediation lifecycle. 

Lightrun’s Runtime Sensor closes the confirmation gap on the assessment side by proving whether a vulnerable path executes, rather than merely guessing it might. The Runtime Aware PR Verifier closes it on the fix side, confirming a patch behaves correctly under live conditions before it ships. Evidence from the running system will always outlast an assumption made about it at build time.

FAQ

What is CVE remediation?

CVE remediation is the process of identifying, prioritizing, and resolving Common Vulnerabilities and Exposures across the software an organization runs in production. It goes beyond patching to include upgrading dependencies, rebuilding artifacts, disabling vulnerable features, or documenting an accepted risk; it is fundamentally a triage exercise, given that thousands of new CVEs are disclosed every year.

How is reachability analysis used to prioritize CVE remediation?

Reachability analysis checks whether a vulnerable code path in a flagged dependency is actually reachable by the application, rather than treating every disclosed CVE in the dependency tree as equally urgent. Most implementations do this statically, tracing a call graph from source code or build artifacts to see if a path theoretically exists to the vulnerable function.

Why isn’t static reachability analysis enough to confirm a CVE is exploitable?

Static reachability confirms a vulnerable function is present in the call graph, not that it executes under real conditions. It cannot see runtime configuration, feature flags, or environment-specific dependency loading, and it is assessed once at a single point in time, so it goes stale the moment new code ships or a config value changes after that assessment runs.

How is AI changing CVE remediation?

AI coding assistants are introducing new dependencies into codebases faster than manual security review can evaluate them, expanding the CVE surface at the same pace as code ships. At the same time, AI is accelerating the speed at which attackers turn a newly disclosed CVE into a working exploit, compressing the remediation window on the other end of the same problem.

How is Lightrun different from traditional vulnerability scanning or SCA tools?

Traditional SCA and reachability tools operate on source code or build artifacts and infer whether a vulnerability could be reachable. Lightrun’s Runtime Sensor instruments the live, running service in a read-only sandbox to confirm whether the vulnerable code path actually executes under real production traffic, and the Runtime-Aware PR Verifier validates that the resulting fix behaves correctly against live system behavior before it merges.