Safeguard
Vulnerability Analysis

CVE-2019-11358: Prototype pollution in jQuery $.extend

CVE-2019-11358 lets attackers pollute Object.prototype via jQuery's $.extend() deep merge. Here's the impact, affected versions, and how to fix it.

Aman Khan
AppSec Engineer
7 min read

Lede

CVE-2019-11358 is a prototype pollution vulnerability in jQuery's $.extend() function when it is called in its recursive ("deep") merge mode. When an application uses $.extend(true, {}, ...) to merge an object that an attacker can influence — for example, JSON parsed from a URL parameter, a form field, or an API response — the attacker can inject a __proto__ key that jQuery fails to filter out. Because __proto__ is a live reference to Object.prototype in JavaScript, this lets the attacker write arbitrary properties onto the prototype shared by every plain object in the running application, not just the object being merged.

The practical impact ranges from denial of service (crashing the app by polluting a property that other code depends on) to logic corruption — for example, silently flipping a property like isAdmin or enabled that other code checks with if (obj.someFlag). In more complex applications, prototype pollution has been chained with other "gadgets" to achieve cross-site scripting or, in server-side Node.js code, remote code execution. jQuery itself doesn't execute code from the polluted property, but downstream application logic often does.

What makes CVE-2019-11358 particularly notable from a supply chain perspective isn't the vulnerability class itself — prototype pollution bugs were found across the JavaScript ecosystem around the same period (lodash, minimist, and others had similar issues) — it's jQuery's sheer footprint. jQuery ships inside countless CMS themes, admin panel templates, WordPress/Drupal plugins, and legacy internal tools, frequently as a vendored or minified copy that never appears in a package.json and is therefore invisible to naive dependency scanning.

Affected Versions and Components

  • Affected: jQuery versions prior to 3.4.0.
  • Fixed in: jQuery 3.4.0, which added filtering so that __proto__ (and related unsafe keys) are skipped during $.extend()'s deep-merge logic.
  • Trigger condition: The vulnerable code path is $.extend(true, target, ...sources) — the deep/recursive merge form. The shallow form, $.extend(target, source) (no true flag), is not affected by this specific issue.
  • Exposure surface: Any application, plugin, or theme that (a) bundles a pre-3.4.0 copy of jQuery and (b) passes attacker-influenced data into a deep $.extend() call — directly or through a plugin that does so on the app's behalf.

Because jQuery is so frequently vendored rather than declared as a managed dependency, this CVE tends to persist far longer in the wild than its age would suggest. It's common to find pre-3.4.0 jQuery bundled inside admin themes, marketing site templates, and internal tooling long after the "main" application dependencies have been patched.

CVSS, EPSS, and KEV Context

NVD's published CVSS v3.x score for CVE-2019-11358 is in the medium range (commonly cited as 6.1), reflecting that exploitation typically requires an attacker to get a specifically crafted payload processed by the deep-merge path (often needing some form of user interaction or a specific application pattern), and that the direct confidentiality/integrity impact is limited rather than a straightforward full compromise.

As of this writing, CVE-2019-11358 is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, and we're not aware of a specific EPSS score high enough to suggest sustained, widespread exploitation campaigns tied to this identifier. That said, EPSS scores drift over time and should be checked against a live feed rather than a fixed number in a blog post — the absence from KEV also doesn't mean the risk is zero, particularly for applications that pass untrusted JSON directly into deep-merge utilities. Teams should treat the medium CVSS score as a floor, not a ceiling: the real-world severity depends entirely on what the polluted property is later used for in your specific application, which generic scoring can't fully capture.

Timeline

  • jQuery's prototype pollution weakness in $.extend()'s deep-merge behavior was identified and reported to the jQuery project as part of a broader wave of prototype pollution research affecting popular JavaScript utility libraries in this period.
  • The jQuery team shipped a fix in jQuery 3.4.0, adding a check to skip __proto__ (and similar unsafe keys) when performing recursive merges via $.extend().
  • CVE-2019-11358 was subsequently assigned and published to track the issue, pointing users of jQuery to upgrade to 3.4.0 or later.
  • In the years since, jQuery has continued to release further 3.x versions (3.5.x, 3.6.x, and beyond) that include this fix along with additional hardening; any currently supported jQuery release is unaffected.

If your priority is precise dates for a compliance record, pull the authoritative timestamps directly from the NVD entry for CVE-2019-11358 and the jQuery release changelog rather than relying on a summary — this post intentionally avoids stating exact dates we can't verify with full confidence.

Remediation Steps

  1. Upgrade jQuery to 3.4.0 or later. The current stable 3.x line (and jQuery 4.x, once broadly adopted) includes the fix. This is the definitive remediation — no configuration flag or workaround replaces it.
  2. Find every copy, not just the declared one. Search your codebase, build artifacts, and static asset directories for vendored or minified jQuery files (jquery.min.js, jquery-1.x.js, theme-bundled copies, etc.) that won't show up in npm ls or a package.json audit. This is the step teams most often skip, and it's where old, vulnerable jQuery tends to hide the longest.
  3. Audit third-party themes and plugins. CMS themes, admin dashboard templates, and browser extensions frequently pin an old jQuery version internally. Confirm with the vendor or maintainer that their bundled copy has been updated, or replace/patch it yourself if it's abandoned.
  4. Never pass untrusted input directly into a deep merge. Regardless of jQuery version, treat $.extend(true, ...), Object.assign-style recursive merges, and similar utilities in other libraries (lodash merge, etc.) as sensitive sinks. Validate or allow-list keys before merging attacker-controlled JSON, and reject payloads containing __proto__, constructor, or prototype keys as a defense-in-depth measure.
  5. Add monitoring for prototype pollution patterns in your SAST/DAST tooling if you maintain custom merge utilities elsewhere in the stack — the underlying pattern (recursive merge without key filtering) recurs well beyond jQuery.
  6. Re-scan after remediation. Confirm the fix by re-running your SCA/SBOM tooling against the updated build artifacts, including any minified bundles, to make sure the vulnerable version is actually gone from what ships to production — not just from source control.

How Safeguard Helps

CVE-2019-11358 is a textbook example of why supply chain visibility has to go deeper than package.json. The riskiest instances of this vulnerability aren't the ones sitting in a top-level dependency that your package manager already flags — they're the vendored, minified, or theme-bundled copies of jQuery that traditional software composition analysis never sees because there's no manifest entry pointing to them.

Safeguard's SBOM generation is built to catch exactly this gap: we analyze actual build artifacts and shipped assets — not just declared dependency manifests — to identify embedded and transitive copies of libraries like jQuery, including versions bundled inside themes, plugins, and third-party widgets. When a vulnerable version surfaces anywhere in that graph, it's attributed back to the artifact and component that introduced it, so your team isn't left guessing which of a dozen internal tools or marketing sites is still running jQuery 1.x or 2.x.

From there, Safeguard's continuous monitoring correlates known CVEs like this one against your live component inventory, layering in CVSS, EPSS, and KEV context as it updates, so you can prioritize based on current exploitation signals rather than a static severity number frozen at disclosure time. For CVE-2019-11358 specifically, that means surfacing not just "jQuery is outdated" but which of your applications actually invoke a deep $.extend() merge against attacker-reachable input — turning a broad, ecosystem-wide advisory into a short, actionable list of what genuinely needs attention first.

Finally, Safeguard's policy engine can gate builds and deployments on dependency risk thresholds, so a reintroduced vulnerable jQuery copy — say, from a new theme or a reverted upgrade — gets caught before it reaches production rather than being rediscovered in the next periodic audit.

Never miss an update

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