🛡️ CVE-2026-58263 — jodit

🟠 CVSS 8.0 — High ✅ No Known Exploit CWE-79 NVD
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Jodit Editor: Mutation XSS in jodit clean-html via a MathML/style rawtext carrier ### Summary jodit's built-in `clean-html` sanitizer can be bypassed by a MathML/`` carrier that hides a dangerous element from the sanitizer's element walk, so a no-interaction event handler survives into the editor value. When an application supplies attacker-influenced HTML to the editor's value-set or insertion paths, the sanitized output still contains a live `` (or another non-`onerror` handler such as `onfocus`). A consumer that renders that output (`element.innerHTML = editor.value`) executes the handler with no user interaction. This is a stored cross-site scripting vulnerability, confirmed live on the shipped `es2021/jodit.min.js` for 4.12.25 and the latest 4.12.27 (in Chromium via a client-side `innerHTML` consumer, and in Firefox via server-rendered / document-context output; see the cross-browser note under Proof of concept). ### Details The bypass exploits the order in which `clean-html` parses, walks, and re-serializes the value. 1. On the value-set path, the `clean-html` plugin handles `:beforeSetNativeEditorValue` (`src/plugins/clean-html/clean-html.ts:116`), parsing the value into an inert document: `sandBox.innerHTML = data.value`. 2. In that parse, the source nesting `math > mtext > table > mglyph > style` triggers MathML text-integration-point and foster-parenting rules: the `` is parsed as text inside `` (rawtext), not as an element. The `` is foster-parented out, and the `` MathML text-integration point governs the namespace, so the `` never becomes an element node in this parse. 3. That value-set sanitizer is `safeHTML` (`src/core/helpers/html/safe-html.ts:24`); it walks the tree but acts on elements only (the `Dom.isElement` gate at `:39`) and runs against the parse-1 `sandBox`, in which the `` is rawtext, not an element. So `removeAllEventAttributes` (the full `on*` strip at `safe-html.ts:76`) has no element to clean and the handler passes through. The `onBeforeSetNativeEditorValue` handler runs `safeHTML` on that parse-1 tree both before and after it captures the value, so neither pass ever sees the `` as an element. 4. The captured value (`data.value = sandBox.innerHTML`) is then assigned to the editable, a second parse, which hoists the `` out of `` and into the HTML namespace as a live element with its handler intact. The serialize-reparse moves the element across the tree and across namespaces: ``` BEFORE - parse 1 (sandBox): the is text [MathML] [MathML] [HTML] integration point: content parses as HTML [HTML] text "" <-- is RAWTEXT, not an element
[HTML] AFTER - editor.value (re-parsed): the is hoisted OUT of , live

[HTML] [MathML] [MathML] [MathML] [MathML] (now empty) [HTML] its handler fires

[HTML] ``` 5. `editor.value` now carries that live element. The value-set pass (Steps 1-4) only walked the parse-1 `sandBox` and never sees it; the other sanitizer, the on-change visitor (`visitNodeWalker` via a `LazyWalker`, `clean-html.ts:56`/`:70`), does reach the hoisted element, but its `sanitizeAttributes` filter calls `sanitizeHTMLElement` (`safe-html.ts:139`), which strips `onerror` only - it never reads the `removeEventAttributes` flag `sanitizeAttributes` passes it (`sanitize-attributes.ts:30`), so it never runs the full `on*` strip. So `onload`, `onfocus`, and every other non-`onerror` handler is never removed and persists in `editor.value` permanently. (`onerror` is the one handler the cleaner removes, but only after a ~300ms window in which it too fires.) The two code points (jodit 4.12.27): ```js // 1. clean-html.ts onBeforeSetNativeEditorValue - the SYNCHRONOUS value-set pass runs on the parse-1 sandBox: sandBox.innerHTML = data.value; // :128 parse 1: the carrier hides the element as rawtext this.j.e.fire('safeHTML', sandBox); // :129 safeHTML element-walk misses the rawtext element data.value = sandBox.innerHTML; // :130 value captured; re-parsing it into the editable hoists the element live safeHTML(sandBox, { safeJavaScriptLink: true, removeOnError: true }); // :131 re-runs on the SAME parse-1 sandBox, never on the captured value // 2. the ASYNC on-change filter (LazyWalker) reaches the hoisted element, but only strips onerror: sanitizeHTMLElement(nodeElm, { /* ... */ removeEventAttributes: opts.removeEventAttributes }); // sanitize-attributes.ts:30 - passes the full-strip flag export function sanitizeHTMLElement(elm, { safeJavaScriptLink, removeOnError

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality low, integrity low, availability none.

Weakness class

CVE-2026-58263 is classified as CWE-79: Cross-site Scripting (XSS). User-supplied data is written into a page without escaping, so attacker script runs in the browser of anyone who views it.

Affected software

CVE-2026-58263 is recorded against 2 packages.

  • jodit
  • unknown

Timeline and source

Published on 31 July 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
nvd.nist.gov (Advisory)
github.com (Web)
github.com (Package)
github.com (Web)

Details

Severity HIGH
CVSS Score 8.0
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
CWE CWE-79
Public Exploit ✅ No
Source NVD
Published 2026-07-31
Updated 2026-08-12
Modified 2026-07-31
Fix URL N/A

Affected Packages

Software From version Fixed in
jodit
unknown

Similar Threats

Site Security Check

Is jodit part of your stack?

CVE-2026-58263 is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.