Blog
|
SECURITY 101

SCA: Prioritizing Reachable Vulnerabilities (June 2026)

By
Arnica
5
Reachable vulnerabilities in SCA

When you pull in an npm library with npm install, you're also pulling in every transitive dependency it carries, each with its own CVE vulnerability history. Most software composition analysis tools stop at inventory, they tell you what's installed and what the National Vulnerability Database says about it. What they don't answer is whether your code ever calls the vulnerable function buried four dependencies deep. Reachability analysis closes that gap by tracing actual code paths, filtering out the 85% of findings that exist in your node_modules folder but never execute in your application.

TLDR:

  • Node.js apps pull in hundreds of transitive dependencies, and npm audit flags CVEs in all of them whether your code calls the vulnerable function or not.
  • Reachability analysis cuts SCA findings by over 85% by tracing call graphs to filter out vulnerabilities in code paths your application never invokes.
  • CVSS scores rate CVE severity without your runtime context, so a Critical-rated flaw in an installed package doesn't mean your application is exploitable.
  • The May 2026 Mini Shai-Hulud attack published 639 malicious npm versions in one hour across 323 packages, the largest single-hour supply chain attack on record.
  • Arnica applies function-level reachability to filter CVEs and reassesses historical findings when new threat intel arrives, routing alerts to current code owners instead of departed developers.

What Is an npm Library and Why It Powers Most JavaScript Applications

An npm library is a reusable package of JavaScript code published to the npm registry, which hosts over 2 million packages. When developers run npm install, they pull these packages directly into their projects, along with every dependency those packages carry. A single npm library can introduce dozens of transitive dependencies, each with its own version history and vulnerability record.

This matters because JavaScript applications built on Node.js or React rarely contain just a handful of dependencies. They contain hundreds. That scale is exactly where open-source risk accumulates quietly, and where software composition analysis tools earn their keep.

How npm Dependencies Create Both Velocity and Risk

The npm registry hosts over 2.1 million packages, and the average Node.js application pulls in hundreds of transitive dependencies. That velocity is the point. Developers move fast because they can reach for a tested, community-maintained npm library instead of writing everything from scratch.

But each dependency is a trust decision made at speed. A single npm audit run routinely surfaces dozens of CVEs across a project's dependency tree, many of them inherited three or four levels deep from packages the team never consciously chose.

The core tension is straightforward:

  • The same open-source ecosystem that accelerates delivery also expands attack surface with every package.json update, often without any developer noticing.
  • Transitive dependencies are largely invisible at code review time, yet they account for the majority of vulnerabilities flagged by software composition analysis tools.
  • Severity scores miss real versus theoretical risk, leaving security teams buried in findings that have no actionable path forward.

That gap between "vulnerability exists" and "vulnerability is reachable in our runtime" is where most SCA programs lose the plot.

What Is a CVE Vulnerability and Why Not All Are Equal

CVE stands for Common Vulnerabilities and Exposures, a publicly disclosed security flaw catalog maintained by MITRE. Every entry gets a unique identifier so security tools, vendors, and teams can reference the same flaw without ambiguity.

Where it gets complicated is severity scoring. CVSS (Common Vulnerability Scoring System) rates each CVE from 0 to 10, but those scores are assigned without your environment's context. A Critical-rated CVE in an installed dependency does not mean your application is exploitable. It means a flaw exists somewhere in that package. Whether your code ever invokes the vulnerable function is a separate question entirely, and one that most tooling never answers.

The npm Supply Chain Attack Surface in 2026

The Axios compromise of late March 2026 clarified what supply chain risk looks like in practice. Axios, the HTTP client with over 100 million weekly downloads, was hijacked through a maintainer account takeover, not a code vulnerability anyone had previously flagged.

A technical illustration showing npm package supply chain attack vectors. Display a central npm registry hub with multiple package nodes radiating outward, connected by dependency chains. Show one compromised maintainer account node highlighted in red with malicious code flowing through dependency connections to downstream packages. Use a dark background with glowing connection lines in blue and purple, with the compromised path shown in red. Include visual elements representing the cascade effect of a single account compromise spreading through multiple packages. Modern, clean cybersecurity visualization style.

Six weeks later, the Mini Shai-Hulud campaign escalated further. Back on May 19, 2026, the npm maintainer account atool was compromised. In roughly one hour, 639 malicious package versions were published across 323 unique packages, which stood as the largest single-hour npm supply chain attack on record at the time.

Definition of SCA: Software Composition Analysis Explained

Software Composition Analysis is the practice of automatically inventorying every open-source component in an application and checking each one against known vulnerability data. SCA tools parse your dependency manifests (package.json, pom.xml, requirements.txt, and others), walk the full dependency tree, and cross-reference every component against databases like the NVD (National Vulnerability Database), the GitHub Advisory Database, and OSV.

The output is a findings list: component, version, associated CVEs, severity scores, and available patches. Many tools also produce an SBOM (Software Bill of Materials), giving you a structured snapshot of everything that went into a given build at a point in time.

That process (inventory, match, report) is where most SCA conversations start and, unfortunately, where many stop. The harder question, which findings represent exploitable risk in your application instead of theoretical exposure in a library you happen to have installed, is where most SCA programs stall out.

Why npm Audit Produces More Noise Than Signal

Running npm audit feels productive. It returns a list of vulnerabilities, you patch what you can, and you move on. But security teams who rely on it heavily tend to hit the same wall: the list never shrinks in any meaningful way.

The core problem is that npm audit reports every CVE in your dependency tree regardless of whether your code ever calls the vulnerable function. A CVE flagged in a deeply nested transitive dependency may have zero reachable code paths in your application. It still shows up. It still demands triage time.

At scale, this creates real fatigue. Teams spending hours on vulnerabilities that pose no actual risk have less time for the ones that do.

Capabilitynpm auditReachability Analysis
Coverage scopeEvery CVE in full dependency treeCVEs in callable code paths only
Analysis methodDependency manifest matching against vulnerability databasesCall graph tracing from application entry points to vulnerable functions
Findings volumeReports all CVEs regardless of reachabilityReduces findings by over 85% through call path filtering
Transitive dependenciesFlags vulnerabilities in nested dependencies whether invoked or notTraces whether application code calls vulnerable functions in transitive dependencies
ActionabilityHigh noise-to-signal ratio, demands triage time for unreachable vulnerabilitiesSurfaces exploitable risk in live code paths

Reachability Analysis: The Filter That Actually Reduces Noise

Reachability analysis cuts through the volume problem by asking a deceptively simple question: is this vulnerable code path actually callable from your application, present in a dependency but never invoked, or reachable through real execution flows?

Most SCA tools flag every CVE vulnerability found in every dependency you pull in, whether your code ever touches the affected function or not. Reachability analysis traces call graphs from your application's entry points down through transitive dependencies to determine which vulnerabilities sit in live code paths.

The practical impact is real. Studies show reachability filtering can reduce actionable findings by over 85%, cutting through the noise to surface what genuinely warrants attention.

How Reachability Analysis Works: Call Graphs and Code Paths

Reachability analysis works by building a call graph of your codebase, mapping which functions call which other functions, all the way down through third-party dependencies. When a CVE is published against an npm library, the tool traces whether your actual code ever invokes the vulnerable function. If no call path exists, the vulnerability is flagged as unreachable.

What a Call Graph Actually Shows

A call graph is a directed graph where each node is a function and each edge is a call relationship. SCA tools that support reachability walk this graph from your application's entry points outward, checking whether a path exists to the flagged code inside a vulnerable dependency. No path means no exploitable exposure in your running application.

How Arnica Reduces SCA Noise Through Reachability and Context

Arnica's SCA includes function-level reachability analysis that filters CVEs by whether the vulnerable code is actually invoked from your application. What separates it from standalone reachability tools is how findings evolve over time. The Continuous Backlog Management layer reassesses every historical SCA finding when a CVE enters CISA's KEV catalog, an EPSS score changes, or a patch becomes available. When a trigger fires, the finding routes through an identity graph to whoever currently owns that code.

That routing matters more than it sounds. Per Arnica's internal benchmark, 82% of findings were originally authored by developers who had already left the company, so routing to git author email fails most of the time. The identity graph handles departed authors and agent-authored commits, reaching a current owner instead of a dead inbox.

Delivery runs pipelineless across 100% of connected repositories, so reachability context arrives at push time with no CI/CD dependency. Security teams can tune the AI triage layer using plain-English prompts per product, directing the scanner to weight specific risk categories more aggressively without writing a single custom rule.

Final Thoughts on Software Composition Analysis That Actually Reduces Noise

Most teams run npm audit, see hundreds of CVEs, and have no idea which ones represent real risk. Reachability analysis solves that by tracing call graphs from your code to vulnerable functions, filtering out what you can't actually reach. You can keep patching everything, or you can focus on the 15% of findings that sit in live code paths. Start filtering SCA noise with Arnica and route findings to current owners instead of defunct inboxes.

FAQ

What is software composition analysis and how does it work?

Software composition analysis (SCA) automatically inventories every open-source component in an application and checks each against known vulnerability databases like the NVD, GitHub Advisory Database, and OSV. SCA tools parse dependency manifests (package.json, requirements.txt, pom.xml), walk the full dependency tree including transitive dependencies, and cross-reference components against CVE records to produce findings lists with severity scores and available patches.

npm audit vs reachability analysis: which actually reduces your backlog?

npm audit reports every CVE in your dependency tree regardless of whether your code calls the vulnerable function, creating overwhelming noise. Reachability analysis filters vulnerabilities by tracing call graphs from your application's entry points to determine which CVE code paths are actually callable in your runtime, reducing actionable findings by over 85% in most codebases.

What is a CVE vulnerability and why does severity scoring miss the point?

A CVE (Common Vulnerabilities and Exposures) is a publicly disclosed security flaw with a unique MITRE identifier and CVSS severity score from 0 to 10. The scoring problem is context: a Critical-rated CVE in an installed dependency means a flaw exists in that package, not that your application is exploitable. Whether your code ever invokes the vulnerable function is a separate question that CVSS scores never answer.

Can reachability analysis catch supply chain attacks like the Axios compromise?

No. Reachability analysis filters known CVE vulnerabilities by call paths, but supply chain attacks like the March 2026 Axios maintainer account takeover or the May 2026 Mini Shai-Hulud campaign that published 639 malicious package versions in one hour introduce malicious code with no prior CVE record. These attacks require runtime behavior monitoring, provenance verification, and SBOM tracking alongside reachability-based SCA.

How do most SCA programs handle findings for developers who left the company?

Most SCA tools route findings to the git author email from the original commit, which fails when that developer has left or changed teams. Per Arnica's internal benchmark, 82% of findings were authored by developers no longer at the company, meaning static email-based routing sends most alerts to dead inboxes or unmonitored group aliases instead of current code owners who can act.

Reduce Risk and Accelerate Velocity

Integrate Arnica ChatOps with your development workflow to eliminate risks before they ever reach production.  

Try Arnica