Safeguard
Vulnerability Analysis

CVE-2020-11022: XSS in jQuery via htmlPrefilter

CVE-2020-11022 lets attacker-controlled HTML bypass sanitization via jQuery's htmlPrefilter, enabling XSS in versions before 3.5.0. Impact, timeline, and fixes.

Aman Khan
AppSec Engineer
7 min read

Lede

CVE-2020-11022 is a cross-site scripting (XSS) vulnerability in jQuery, one of the most widely deployed JavaScript libraries on the web. The flaw lives in jQuery's htmlPrefilter mechanism — the internal routine that normalizes HTML strings before they're inserted into the DOM by methods like .html(), .append(), .prepend(), and .replaceWith(). Under specific conditions, HTML passed to these methods — even HTML that an application believed it had sanitized — could be re-interpreted by the browser in a way that let an attacker smuggle in executable markup. The practical impact is textbook stored or DOM-based XSS: an attacker who controls a fragment of HTML that eventually flows into one of jQuery's manipulation methods can execute arbitrary JavaScript in the context of the victim's session, enabling session hijacking, credential theft, or further pivoting inside a web application.

What makes this CVE notable isn't sophistication — it's reach. jQuery ships in an enormous share of production web applications, either directly, bundled inside CMS themes and plugins, or pulled transitively through other front-end dependencies. A defect in a shared, deeply-nested dependency like this is a supply chain problem as much as it is a browser-security problem: teams that never wrote a line of the vulnerable code still inherited the exposure the moment they added jQuery to a package.json, a script tag, or a vendored asset folder.

Affected Versions and Components

The vulnerability affects jQuery versions from 1.2 up to (but not including) 3.5.0. That range covers well over a decade of releases, including the 1.x, 2.x, and 3.x branches that many long-lived enterprise applications, WordPress themes/plugins, and internal admin tools still run today. The vulnerable code path is jQuery's HTML manipulation logic — specifically the regex-driven htmlPrefilter used by DOM-insertion APIs such as .html(), .append(), .prepend(), .before(), .after(), .replaceWith(), and the jQuery() constructor itself when passed an HTML string. Any application, theme, or plugin that passes user-influenced or third-party HTML content through these methods — regardless of whether that content was run through an upstream sanitizer — is a candidate for exposure, since the bug lies in how jQuery itself rewrites certain tag patterns before insertion, not in the absence of sanitization on the caller's side.

It's worth noting jQuery 3.5.0 also fixed a closely related sibling issue, CVE-2020-11023 (XSS via <option> element handling in the same family of DOM manipulation methods). The two are frequently patched and discussed together because they share a root cause area and a fix release, though they are tracked as distinct CVEs.

CVSS, EPSS, and KEV Context

NVD scores CVE-2020-11022 as a Medium-severity issue under CVSS v3.1, reflecting that exploitation requires an attacker to get attacker-influenced HTML into a vulnerable jQuery call and typically requires some form of user interaction to trigger the resulting script execution — it is not a remotely exploitable, unauthenticated network flaw in the traditional sense. That "Medium" label is a common source of under-prioritization: teams triaging by raw CVSS number alone can deprioritize a bug that, in the context of their specific application (e.g., a comment field, a WYSIWYG editor preview, or an admin panel that renders user-submitted HTML), is trivially exploitable and high-impact.

This CVE is not currently listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, and it has not attracted the kind of mass-exploitation campaigns associated with KEV-listed network-facing bugs. That absence should not be read as "safe to ignore." Client-side XSS in a library as ubiquitous as jQuery tends to be exploited opportunistically and quietly — through malicious ads, compromised third-party scripts, or crafted user content — rather than through the kind of internet-wide scanning that produces KEV additions. EPSS-style exploitation-probability scoring for this CVE has generally sat on the lower end precisely because exploitation is application-specific rather than generic, but "lower probability of mass exploitation" is a very different statement from "not exploitable in your codebase," and it should not substitute for checking whether your own code passes untrusted HTML through the affected APIs.

Timeline

  • jQuery 3.5.0 release: The jQuery team shipped version 3.5.0, which rewrote the htmlPrefilter handling and resolved both CVE-2020-11022 and CVE-2020-11023, along with other DOM-manipulation hardening.
  • Public disclosure: The CVE was published to NVD/MITRE around the same window as the 3.5.0 release, documenting the flaw across jQuery 1.2 through 3.4.x.
  • Post-disclosure tail: As with most front-end library CVEs, the practical risk window extended well beyond disclosure. jQuery's popularity means it is frequently vendored, minified, or bundled inside third-party themes and plugins that don't track upstream releases closely — so applications built on outdated bundles remained exposed long after a fix was publicly available, a pattern security teams continue to see in dependency audits years later.

Remediation Steps

  1. Upgrade jQuery to 3.5.0 or later. This is the definitive fix. If you're on the 1.x or 2.x branch and can't jump straight to 3.5.x due to compatibility constraints, treat the upgrade path as a project in its own right rather than deferring it indefinitely.
  2. Inventory every place jQuery is loaded from, not just your direct package.json dependency. Check CDNs referenced in HTML templates, vendored/minified copies checked into vendor/ or static/ directories, and jQuery bundled inside third-party themes, plugins, or widgets (WordPress and other CMS ecosystems are a common source of stale copies).
  3. Audit calls to .html(), .append(), .prepend(), .before(), .after(), .replaceWith(), and the jQuery()/$() constructor for any path where the HTML argument originates from user input, third-party APIs, or CMS-managed content — even content you believe is sanitized upstream. Prefer .text() or DOM APIs like textContent/createElement when you don't actually need to inject markup.
  4. Don't rely on sanitization alone as a compensating control. The root cause here is in how jQuery re-processes HTML before insertion, so a sanitizer that runs before jQuery sees the string doesn't guarantee the string jQuery ultimately inserts is still safe. Pin to a patched jQuery version rather than treating input sanitization as sufficient mitigation.
  5. Regression-test after upgrading. jQuery 3.5.0 made behavioral changes beyond the security fix; run your front-end test suite and manually verify any code that depends on specific HTML string transformation behavior.
  6. Add jQuery (and its transitive/vendored copies) to continuous dependency scanning so future stale copies — reintroduced by a new plugin, theme update, or CDN snippet — get flagged automatically instead of surviving silently for years.

How Safeguard Helps

CVE-2020-11022 is a clean example of why dependency visibility has to extend past the top-level manifest. The riskiest instances of this vulnerability aren't the ones sitting in a clearly declared package.json — they're the vendored copies, CDN references, and third-party plugin bundles that never show up in a routine npm audit because they were never installed through a package manager in the first place.

Safeguard's software supply chain platform is built to close exactly that gap. Continuous SBOM generation and dependency inventory surface every instance of jQuery across your applications — declared, transitive, and vendored — so a stale, pre-3.5.0 copy embedded inside a theme or a static asset folder doesn't stay invisible. Vulnerability correlation maps CVE-2020-11022 and its sibling CVE-2020-11023 against your actual deployed inventory, not just your direct dependency tree, and prioritizes remediation using real-world exploitability signals rather than CVSS score alone — surfacing cases where a "Medium" severity XSS sits directly behind a user-content rendering path that makes it far more urgent than the raw score suggests.

Beyond detection, Safeguard's policy and gating controls let teams enforce minimum-version rules for high-blast-radius libraries like jQuery at the CI/CD stage, so a vulnerable version can't silently re-enter the codebase through a new plugin or a copy-pasted CDN snippet. Combined with provenance tracking for third-party and vendored assets, this gives security and engineering teams a durable way to confirm — not assume — that known XSS issues like CVE-2020-11022 have actually been remediated everywhere the library lives, not just where the package manager happens to be looking.

Never miss an update

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