How to Patch jQuery Vulnerabilities in Production Without a Full Rewrite
A practical guide to remediating jQuery CVEs in legacy production systems—without breaking your application or delaying compliance.

jQuery’s adoption is massive - it runs on more than 70% of the most popular websites. It powers WordPress themes, enterprise intranets, government portals, legacy CRMs, and everything in between. Most of it is old. A 2023 survey across 500 organizations found that 59% are still running jQuery versions between 1.x and 3.5., all of which carry known, actively exploited vulnerabilities.
In January 2025, CISA added CVE-2020-11023, a persistent cross-site scripting (XSS) flaw present in jQuery 1.0.3 through 3.4.1, to its Known Exploited Vulnerabilities (KEV) catalog. The flaw had been linked to Chinese APT activity. Federal agencies were given until February 13 to remediate. That directive applies to government systems, but if you're subject to SOC 2, PCI DSS, FedRAMP, or the EU Cyber Resilience Act, the implications are the same: unpatched jQuery is a compliance problem, not just a technical one.
The standard advice is "upgrade to jQuery 3.5.0 or later." That's fine if you're running a greenfield project. But if you're managing a production system that was built on jQuery 1.x or 2.x , with plugins, custom code, and deeply intertwined DOM manipulation logic then a major version upgrade is a rewrite. And rewrites don't pass change advisory boards overnight.
This post is about what you do instead. How you patch jQuery vulnerabilities in production systems without a full migration, and how long that approach can realistically sustain you.
The jQuery Vulnerabilities That Actually Matter
Not every jQuery CVE carries the same risk. Here's a breakdown of the ones you need to prioritize, based on real-world exploitation and compliance impact.
CVE-2020-11023: XSS via DOM Manipulation Methods (CISA KEV)
Affected versions: jQuery 1.0.3 through 3.4.1
This is the big one. Passing HTML containing <option> elements from untrusted sources to jQuery's DOM manipulation methods (.html(), .append(), .prepend(), etc.) can execute arbitrary JavaScript even after the input has been sanitized with common libraries. CISA flagged it as actively exploited in the wild, and it's been linked to APT1 campaigns targeting vulnerable web infrastructure.
The dangerous pattern looks like this:
// VULNERABLE: untrusted HTML passed to .html()
const userContent = getUntrustedInput();
$('#container').html(userContent);If userContent contains something like <option><style></option></select><img src=x onerror=alert(1)>, jQuery's internal HTML parsing will execute the injected script.
CVE-2020-11022: XSS via HTML Preprocessing
Affected versions: jQuery 1.2 through 3.4.1
Similar to 11023, but triggered through jQuery's regex-based HTML preprocessing. Untrusted HTML passed to DOM insertion methods can execute scripts due to how jQuery cleans and prepares HTML fragments before insertion.
CVE-2019-11358L Prototype Pollution via $.extend
Affected versions: jQuery < 3.4.0
jQuery.extend(true, {}, untrustedObject) with a deep merge will follow __proto__ properties, allowing an attacker to inject properties onto Object.prototype. This can escalate to XSS, denial of service, or authorization bypass depending on how your application consumes object properties downstream.
// VULNERABLE: deep extend with untrusted source
const malicious = JSON.parse('{"__proto__":{"isAdmin":true}}');$.extend(true, {}, malicious);
// Now every object in the runtime has isAdmin === trueconsole.log({}.isAdmin); // true
CVE-2015-9251: XSS via Cross-Domain Ajax
Affected versions: jQuery < 3.0.0
When performing cross-domain Ajax requests without specifying a dataType, jQuery will execute text/javascript responses automatically. An attacker controlling a cross-domain endpoint can deliver executable JavaScript that runs in the context of your application.
CVE-2020-7656: XSS in .load() Method
Affected versions: jQuery < 1.9.0
The .load() method executes JavaScript included in the fetched HTML fragment. If you're loading content from URLs that could be influenced by user input, this becomes a stored or reflected XSS vector.
Option 1: Mitigate in Place (Short-Term)
If you can't upgrade jQuery tomorrow, you can reduce your attack surface with targeted mitigations. These are stopgap measures that reduce risk, but they don't eliminate the CVE from your dependency tree, and most compliance audits will still flag them.
Sanitize Before Insertion with DOMPurify
DOMPurify is the most reliable client-side HTML sanitizer. For CVE-2020-11023 and CVE-2020-11022, the jQuery project specifically recommends using DOMPurify with the SAFE_FOR_JQUERY flag:
// Install: npm install dompurify
import DOMPurify from 'dompurify';
// Sanitize before any jQuery DOM insertion
const clean = DOMPurify.sanitize(untrustedHTML, {
SAFE_FOR_JQUERY: true });
$('#container').html(clean);Apply this everywhere your application passes dynamic HTML to .html(), .append(), .prepend(), .after(), .before(), .replaceWith(), or .wrap().
Block Prototype Pollution via Object.freeze
For CVE-2019-11358, you can freeze Object.prototype to prevent pollution:
// Prevent prototype pollution (may break some libraries - test thoroughly)
Object.freeze(Object.prototype);This is aggressive. Some libraries and frameworks rely on extending Object.prototype, so test extensively before deploying. A less disruptive approach is to validate or strip __proto__, constructor, and prototype keys from untrusted objects before passing them to $.extend.
Specify dataType on All Ajax Calls
For CVE-2015-9251, always declare the expected response type:
// VULNERABLE
$.ajax({ url: crossDomainUrl });
// PATCHED
$.ajax({ url: crossDomainUrl, dataType: 'json' });Deploy a Content Security Policy
A well-configured CSP won't fix the underlying vulnerability, but it limits what an attacker can do if they achieve XSS:
Content-Security-Policy: default-src 'self'; script-src 'self';
style-src 'self' 'unsafe-inline'Avoid 'unsafe-eval' and 'unsafe-inline' for scripts wherever possible. This significantly reduces the blast radius of any successful XSS exploitation.
Option 2: Upgrade to jQuery 3.5+ (If You Can Absorb the Breaking Changes)
jQuery 3.5.0, released in April 2020, addressed CVE-2020-11023 and CVE-2020-11022 directly. jQuery 3.4.0 fixed the prototype pollution bug. If you're on jQuery 3.x already, upgrading to 3.5+ may be a manageable lift.
But if you're on jQuery 1.x or 2.x, the jump is significant. The jQuery team published a migration guide, but in practice, upgrading across major versions means dealing with removed APIs, changed behaviors in .ready(), stricter handling of data- attributes, and broken plugins.
Some common breaking changes that bite production teams:
- .andSelf() removed - replaced by .addBack()
- .size() removed - use .length instead
- $.ajax deferred behavior changed - jQuery 3.x uses Promises/A+ semantics, which changes callback timing
- .load(), .unload(), .error() shorthand removed
- Selector engine changes - some non-standard selectors that worked in Sizzle may break
For many enterprise applications, this isn't a weekend task. It's a multi-sprint effort with regression risk. The applications most affected by these jQuery CVEs, the old, complex, jQuery-heavy ones, are precisely the ones that are hardest to upgrade.
Option 3: Drop-In Patched Replacement (No Code Changes)
This is what we built NES for jQuery to solve.
HeroDevs NES for jQuery provides secure, patched versions of jQuery 1.x, 2.x, and 3.x that address known CVEs, including CVE-2020-11023, CVE-2020-11022, CVE-2019-11358, and others, without changing the API surface. Your application code stays the same. Your plugins keep working. Your QA cycle is a verification pass, not a regression hunt.
How It Works
The setup takes minutes. Three steps:
1. Update package.json
Point your jQuery dependency to the NES-patched version via npm aliasing:
{
"dependencies": {
"jquery":
"npm:@neverendingsupport/jquery@1.12.4-jquery-1.12.6"
},
"overrides": {
"jquery": {
".": "npm:@neverendingsupport/jquery@1.12.4-jquery-1.12.6"
}
}
}The version number maps to your current jQuery version. NES publishes patched builds for jQuery 1.3.x, 1.5.x, 1.6.x, 1.7.x, 1.12.x, 2.2.x, and 3.5.x.
2. Create or update .npmrc
Point the @neverendingsupport scope to the HeroDevs private registry:
@neverendingsupport:registry=https://registry.nes.herodevs.com/npm/pkg/
//registry.nes.herodevs.com/npm/pkg/:_authToken=<YOUR_NES_ACCESS_TOKEN>3. Install and run
npm installThat's it. Run your test suite. The patched jQuery is API-compatible with the version you were already using, it just doesn't have the security holes.
For teams that don't use npm, direct download URLs are also available through the HeroDevs registry, and NES packages support both script tag inclusion and module bundlers.
What NES Covers Beyond Core jQuery
jQuery rarely lives alone. If your application uses jQuery UI, jQuery Validation, jQuery Mobile, or jQuery Cookie, those carry their own CVEs (and NES covers them too):
- jQuery UI (1.8.x, 1.13.x, 1.14.x): includes fixes for CVE-2024-30875 and earlier XSS flaws
- jQuery Validation (1.19.x): patches for ReDoS vulnerabilities (CVE-2021-43306 and related)
- jQuery Mobile (1.4.x)
- jQuery Cookie (1.4.x)
Each follows the same three-step setup pattern. Same registry, same auth token, same npm aliasing approach.
Which Option Should You Choose?
It depends on where you are and where you're going.
Choose mitigation (Option 1) if you have a migration already underway and just need to reduce risk for the next 30–60 days. DOMPurify + CSP gives you the best short-term coverage. But know that this approach doesn't clear compliance audits, the vulnerable version is still in your dependency tree and will still appear in SBOM scans.
Choose a jQuery 3.5+ upgrade (Option 2) if you're already on jQuery 3.x with a small plugin footprint and manageable test coverage. The breaking changes between 3.4.x and 3.5.x are minimal. But if you're on 1.x or 2.x, this is likely a multi-month project that competes with your product roadmap.
Choose NES (Option 3) if you need to resolve CVEs now while preserving the stability of your current application. This is particularly relevant if you're facing an audit deadline, a CISA KEV remediation window, or a customer security questionnaire that asks about known vulnerabilities in your dependency chain. NES gives you a clean scan result and ongoing patch coverage without the regression risk of a major version upgrade.
Most of our customers use NES as either a permanent solution for applications that are in maintenance mode, or as a bridge while they plan a larger migration on their own timeline. Either way, the point is that patching doesn't have to wait for a rewrite.
The Compliance Angle
If you're tracking regulatory requirements, here's why jQuery CVEs matter beyond the technical risk:
CISA KEV / BOD 22-01: Federal agencies must remediate KEV-listed vulnerabilities within a defined timeline. CVE-2020-11023 was added January 23, 2025, with a February 13 deadline.
PCI DSS 4.0 (Requirement 6.3.3): Organizations must address known vulnerabilities in third-party software components. A jQuery CVE in your SBOM is a finding.
SOC 2 (CC7.1): Known vulnerabilities must be identified and remediated in a timely manner. Running jQuery 1.12.4 with CVE-2020-11023 unpatched is a gap.
EU Cyber Resilience Act: Products with digital elements must demonstrate active vulnerability management. Using unmaintained jQuery versions undermines CRA compliance.
In each case, what auditors and assessors want to see is evidence that you've addressed the vulnerability either by upgrading, patching, or applying a documented mitigation with a compensating control. NES provides all three: the patched package, the SBOM update, and the VEX documentation to show the vulnerability has been resolved.
Get Started
You can try NES for jQuery with a free trial, no sales call required. The trial packages use the same registry and setup process described above.
If you want to see what's in your jQuery dependency tree before making any changes, run npm ls jquery and check the versions you may be using. If they are below 3.5.0, you're exposed. The fix with HeroDevs takes five minutes.
.png)
.png)
.png)