Home / Docs / Reachability Engine

Reachability Engine

A technical look at how Patchlynx constructs a call graph, maps CVE-affected functions to graph nodes, and determines whether a vulnerable function is reachable from your configured production entry points.

What is reachability?

A CVE describes a vulnerability in a function (or set of functions) within a package. A CVE is reachable if there exists a call path from any of your configured entry points to a vulnerable function. If no such path exists, the CVE is not reachable — it cannot be triggered by your code as deployed.

Patchlynx performs a conservative static analysis: if it cannot confirm that a path is absent, it marks the CVE reachable. False negatives (missed reachable CVEs) are more harmful than false positives.

How the call graph is built

  1. Entry point discovery — Patchlynx identifies your entry points from package.json main, framework patterns, or your .patchlynx.yml.
  2. AST-level import resolution — Every import, require, and export is resolved to a canonical file path. Dynamic imports are followed where the specifier is a string literal.
  3. Function-level edge creation — Call expressions create directed edges from caller → callee function. Callbacks and event emitters are handled via pattern libraries per language.
  4. Transitive closure — The graph is expanded across package boundaries into node_modules (or site-packages, vendor/, etc.) following the same rules.
  5. CVE function mapping — NVD + language-specific advisory databases map CVE IDs to affected function names within package versions. These form the target nodes.
  6. Reachability query — For each CVE, we query: is the affected function reachable from any entry point? The answer (with path evidence) becomes the finding.
Precision over speed. Analysis runs asynchronously in an isolated sandbox. Average time to verdict is 8.4 seconds; complex monorepos may take up to 45 seconds. Your CI pipeline is not blocked waiting for the result — the check is posted as soon as analysis completes.

Advisory database sources

SourceLanguagesRefresh
NVD (NIST)AllHourly
GitHub Advisory Databasenpm, pip, Maven, Cargo, GoReal-time
OSV.devAllHourly
npm Security AdvisoriesJavaScriptReal-time
RustSecRustDaily

Known limitations

We document these explicitly so you know where the analysis may produce conservative results (false positives) rather than false negatives:

  • Dynamic imports with variable specifiersrequire(someVar) or import(computedPath) are not fully resolved. Calls through these paths are treated as potentially reachable.
  • Reflection-based dispatch — Java's Class.forName(), Python's importlib.import_module(varName), and similar reflection patterns are handled conservatively. If the class/module name cannot be statically resolved, the CVE is marked reachable.
  • Post-bundling analysis — If you submit a bundled output (webpack bundle, esbuild output) rather than source, intra-bundle call resolution may be incomplete. We recommend pointing entry-point config at source files, not build output.
  • Native extensions — C/C++ extension modules (.node bindings in Node.js) are analyzed by heuristic only. If a CVE is in a native addon, the reachability verdict is a best-effort approximation.