Safeguard
Open Source Security

npm prototype pollution trends report 2025

Safeguard's 2025 analysis of npm prototype pollution advisories reveals rising volume, deeper transitive exposure, and why reachability—not CVSS alone—now separates real risk from noise.

Safeguard Research Team
Research
7 min read

SAN FRANCISCO — July 2025. Prototype pollution has quietly become one of the most persistent and misunderstood vulnerability classes in the npm ecosystem. Once dismissed as a theoretical JavaScript quirk, it has spent the last eighteen months proving itself a practical vector for remote code execution, authentication bypass, and denial of service across some of the most widely deployed packages in the registry. Safeguard's research team spent the first half of 2025 aggregating advisory data from the GitHub Advisory Database, the National Vulnerability Database, and npm's own security advisories, cross-referencing them against real-world dependency graphs pulled from customer SBOMs. The resulting picture is a vulnerability class that isn't going away — it's evolving, and in some ways getting harder to catch with static tooling alone.

This report summarizes what changed in 2025, why prototype pollution keeps resurfacing in new forms even after years of high-profile fixes, and what security and platform engineering teams should be watching for through the rest of the year.

What Prototype Pollution Is, Briefly

Prototype pollution exploits JavaScript's prototype-based inheritance model. When an application merges, clones, or deep-sets attacker-controlled object properties without sanitizing keys like __proto__, constructor, or prototype, an attacker can inject properties onto Object.prototype itself. Because nearly every object in a JavaScript runtime inherits from Object.prototype, a single unsanitized merge operation deep inside a transitive dependency can silently affect application logic far removed from the vulnerable code path — enabling privilege escalation, property injection that leads to RCE via gadget chains, or crashes that amount to denial of service.

The class first drew mainstream attention with lodash's merge and defaultsDeep functions (CVE-2018-3721, CVE-2019-10744) and minimist's argument parser (CVE-2020-7598), but 2025's data shows the pattern has spread well beyond utility libraries into templating engines, ORM query builders, configuration loaders, and JSON schema validators — categories of packages that are almost always present multiple layers deep in a typical Node.js dependency tree.

The 2025 Numbers

Based on Safeguard's aggregated analysis of advisories disclosed between January 2024 and June 2025, prototype pollution findings in the npm ecosystem grew at a materially faster rate than the broader advisory volume:

  • Prototype pollution accounted for roughly 6–8% of all new npm advisories tracked in the first two quarters of 2025, up from an estimated 3–4% in 2022–2023, based on GHSA category tagging and Safeguard's own re-classification of ambiguous "improper input validation" entries that were functionally prototype pollution.
  • Packages with weekly download counts over 1 million accounted for a disproportionate share of newly disclosed cases — consistent with the pattern that popular, deeply-nested transitive dependencies remain the highest-leverage targets for researchers and attackers alike.
  • Median time-to-patch for prototype pollution advisories affecting top-1000 npm packages held steady at roughly 3–4 weeks from disclosure to a published fix release — faster than the ecosystem average for high-severity findings, but still leaving a meaningful exposure window given how deeply these packages get vendored.
  • In Safeguard's customer SBOM telemetry, a majority of scanned Node.js applications carried at least one transitive dependency with a historical or currently unpatched prototype pollution advisory — underscoring how rarely these issues get remediated proactively once a direct dependency is updated but its own dependencies lag behind.

The recurring theme across the data: prototype pollution is not a "solved" bug class from a few years ago. It's a structural property of how JavaScript object merging works, and new instances keep surfacing as libraries add features, refactor internals, or get forked and re-implemented without carrying forward earlier sanitization fixes.

Where It's Showing Up in 2025

Three categories stood out in this year's advisory data:

1. Deep-merge and configuration utilities. Libraries that recursively merge configuration objects — a common pattern for CLI tools, build systems, and framework config loaders — continue to be the single largest source of new findings. Several widely used config-merging packages received patches in 2025 after researchers demonstrated that nested __proto__ keys in user-supplied JSON or YAML could pollute shared prototypes used elsewhere in the same process.

2. Query-string and JSON parsing. Parsers that convert URL query strings or JSON payloads into nested objects remain a favorite target because the attack surface is directly exposed to untrusted network input. A pollution bug in a parsing library sitting behind an Express or Fastify route can be reachable from any unauthenticated HTTP request, which is exactly the kind of finding that turns a "medium severity" CVSS score into a genuinely urgent incident once reachability is confirmed.

3. Schema validation and templating libraries. A newer trend in 2025 is prototype pollution findings in JSON Schema validators and server-side templating engines, where polluted prototype properties can influence validation logic or, in worse cases, be chained into arbitrary code execution through template rendering gadgets. This category is notable because these libraries are frequently trusted as a security control (validating untrusted input), making a pollution bug inside the validator itself especially damaging.

Why Static Scanning Alone Keeps Missing This

A recurring frustration voiced by security teams in 2025 is that traditional SCA tools flag prototype pollution advisories at the package-version level without answering the question that actually matters: is the vulnerable code path reachable from user-controlled input in our application? Because prototype pollution's impact depends entirely on whether attacker-influenced data ever reaches the vulnerable merge, set, or parse operation, a huge share of "critical" advisory matches in dependency trees turn out to be unreachable in practice — while a smaller number of genuinely exploitable paths get buried in the noise of hundreds of other flagged packages.

This is compounded by the transitive nature of the problem. A direct dependency might be clean, but if it calls into a vulnerable deep-merge utility three layers down, standard manifest-based scanning frequently fails to surface that relationship clearly enough for a team to prioritize a fix — or to know that bumping the direct dependency won't actually resolve the issue if the transitive package is pinned elsewhere in the tree.

What This Means for Security and Platform Teams

The practical takeaway from a year of prototype pollution data is that volume-based vulnerability management — patch everything flagged, in order of CVSS score — doesn't scale against this bug class. Teams need three things: an accurate, complete SBOM that captures transitive depth (not just direct dependencies); reachability context that distinguishes "present in the tree" from "exploitable from an entry point"; and a fast path to remediation once a genuinely reachable finding is confirmed, because the fix itself is usually a routine version bump rather than a complex refactor.

Organizations that treat every prototype pollution CVE as equally urgent tend to burn engineering trust in the security program — teams get asked to patch dozens of packages, most of which pose no real risk to that specific application, and the actual exploitable finding gets lost in the backlog. The organizations that fare better in 2025 are the ones pairing SBOM depth with call-graph-level reachability analysis before anything hits an engineer's queue.

How Safeguard Helps

Safeguard is built around exactly this gap between advisory noise and exploitable reality. Our platform generates and ingests deep, transitive SBOMs for your Node.js and JavaScript applications so prototype pollution findings buried three or four dependency layers down are never invisible. Griffin AI then performs reachability analysis on top of that graph, tracing whether attacker-influenced input can actually reach a vulnerable merge, parse, or set operation in your specific codebase — separating the handful of genuinely exploitable prototype pollution paths from the hundreds of advisories that pose no real risk in your context. When Griffin confirms a reachable finding, Safeguard can open an auto-fix pull request with the patched dependency version already validated against your build, cutting the time-to-remediate window that this report shows attackers rely on. The result is a prioritized, evidence-backed queue instead of a flat list of CVEs — so security and engineering teams spend their time on the prototype pollution risks that actually matter.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.