Aug 26, 2026·6 min read·1 visit
SunEditor versions prior to 3.1.4 are vulnerable to DOM-based XSS because the Embed plugin unsafely parses raw iframe/blockquote blocks and programmatically re-creates sibling script elements, causing immediate execution of attacker-controlled JavaScript.
A DOM-based Cross-Site Scripting (XSS) vulnerability was identified in SunEditor before version 3.1.4. The Embed plugin programmatically recreated and mounted script elements from raw HTML embed code, permitting remote attackers to execute arbitrary JavaScript within a user's browser session.
SunEditor is a lightweight, dependency-free WYSIWYG rich text editor implemented in vanilla JavaScript. It is widely integrated into content management systems, blogging platforms, and administrative dashboards to enable rich text composition. One key feature of SunEditor is its modal-based Embed plugin, located within src/plugins/modal/embed.js, which allows users to directly insert third-party media widgets such as social media posts, videos, or external interactive content.
The Embed plugin exposes an input interface where users can supply raw HTML code, typically consisting of <iframe> or <blockquote> elements. To maintain the layout and interactivity of embedded elements, the editor must parse and integrate this untrusted input into the active editor document. This process introduces an attack surface where maliciously configured input is parsed and manipulated on the client side.
A vulnerability exists within this parsing mechanism. Because the client-side parser fails to restrict and sanitize incoming sibling elements, an attacker can construct input that leads to DOM-based Cross-Site Scripting (DOM XSS), cataloged as CWE-79. Under this vulnerability class, the browser parses the payload and executes arbitrary JavaScript immediately upon mounting the parsed elements to the active DOM.
The root cause of CVE-2026-54606 resides in how the Embed plugin processes and renders raw HTML input strings within src/plugins/modal/embed.js. When a user submits an embed payload, the editor checks if the input begins with an <iframe or <blockquote tag. Upon matching, it parses the input string into a detached DOM fragment using the native browser API DOMParser().parseFromString(src, 'text/html').
Parsing raw HTML into a detached DOM fragment is generally considered a safe browser operation because scripts do not execute within a detached document context. However, security boundaries are broken during the subsequent rendering loop. The original plugin code iterates through the collection of parsed child nodes inside the detached fragment and actively processes each node before appending it to the active editor container.
If the loop identifies a node named script, it does not discard it. Instead, the application programmatically recreates the script node by calling the internal utility dom.utils.createElement('script', ...). It extracts the src attribute from the parsed untrusted node and copies it to the newly created element. This manual recreation and subsequent insertion into the live document causes the browser to evaluate, fetch, and execute the resource pointed to by the script's src attribute.
Reviewing the implementation of src/plugins/modal/embed.js before the patch reveals the precise logic that enabled the programmatic recreation of script elements. The vulnerable iteration block processed nodes sequentially without validating the host domain of the script resource.
// Vulnerable Code Path (Pre-patch)
const childNodes = Array.from(children);
for (const chd of childNodes) {
if (/^script$/i.test(chd.nodeName)) {
// Programmatically recreate the script element
scriptTag = dom.utils.createElement('script', {
src: /** @type {Element} */ (chd).getAttribute('src'),
async: 'true'
}, null);
continue;
}
cover.appendChild(chd);
}The patch introduced in version 3.1.4 mitigates this vulnerability by establishing a strict default-deny whitelist posture. It defines scriptSrcWhitelist inside the plugin's configuration options and introduces a validation method #isAllowedScriptSrc to verify script sources before creation. Additionally, it recursively validates all nested and top-level <iframe> sources using Embed.#checkContentType.
// Patched Code Path (Post-patch)
// A validation function validates the source URL against the configured whitelist
static #isAllowedScriptSrc(src, whitelist) {
if (!src) return false;
return whitelist.some((p) => (p instanceof RegExp ? p.test(src) : src.startsWith(p)));
}
// Inside the rendering loop, validation is performed before element creation
const scriptWhitelist = this.pluginOptions.scriptSrcWhitelist;
for (const chd of childNodes) {
if (/^script$/i.test(chd.nodeName)) {
const scriptSrc = /** @type {Element} */ (chd).getAttribute('src') || '';
// Reject script tag generation if the source is not explicitly whitelisted
if (!Embed.#isAllowedScriptSrc(scriptSrc, scriptWhitelist)) continue;
scriptTag = dom.utils.createElement('script', { src: scriptSrc, async: 'true' }, null);
continue;
}
cover.appendChild(chd);
}> [!WARNING]
> Developers must configure the scriptSrcWhitelist property using highly restrictive, anchored regular expressions. If unanchored regular expressions or loose string matches are used, attackers can register domain names that mimic trusted sources to bypass validation checks. Furthermore, if a whitelisted domain hosts a JSONP endpoint or suffers from open redirect vulnerabilities, attackers can leverage those endpoints to run malicious payloads.
To exploit the vulnerability, an attacker must have network access to the target web application where SunEditor is deployed. The attacker requires the permission level needed to use the rich text editor's Embed feature, which typically requires standard user privileges.
The exploit sequence relies on crafting a multi-part payload. The payload must begin with an approved wrapper tag (such as <iframe) to trigger the parsing path in the editor, followed immediately by a <script> tag referencing an attacker-controlled external script file.
An attacker can craft the following payload to trigger the vulnerability. When inputted into the Embed plugin modal, this payload uses a data URI to display an alert dialog containing the executing domain context:
<iframe src="https://www.facebook.com/plugins/post.php?href=test"></iframe><script src="data:text/javascript,alert(document.domain)"></script>The impact of this DOM-based Cross-Site Scripting vulnerability is high. If an attacker successfully embeds a malicious payload, the injected JavaScript executes under the security context of the victim's browser session. If the victim has administrative privileges, the execution scope expands to full control of the web application.
In a typical attack scenario, the arbitrary JavaScript can access the document.cookie property (unless protected by the HttpOnly flag), extract local storage or session storage tokens, and hijack active sessions. The payload can also perform unauthorized state-changing operations by making programmatic API requests on behalf of the victim. This includes modifying user account details, creating new administrative accounts, or deleting application resources.
The CVSS v4.0 base score for this vulnerability is assessed at 8.5 (High). The vector string CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N indicates that the vulnerability is exploitable over the network with low complexity, low privileges required, and results in high confidentiality and integrity impact on the client-side system.
To address CVE-2026-54606, organizations must upgrade the suneditor npm package to version 3.1.4 or later. This release enforces a default-deny posture for script elements parsed inside the Embed plugin.
# Upgrade package to patched version
npm install suneditor@3.1.4If widgets require external scripts, developers must explicitly configure the scriptSrcWhitelist parameter when initializing the SunEditor instance. The whitelist should contain strict regular expressions with anchor markers to prevent domain-squatting bypasses.
import suneditor from 'suneditor';
suneditor.create('editor_id', {
embed: {
scriptSrcWhitelist: [
/^https:\/\/platform\.x\.com\/widgets\.js$/,
/^https:\/\/www\.instagram\.com\/embed\.js$/
]
}
});To detect exploitation attempts at the network layer, security teams can implement Web Application Firewall (WAF) rules designed to identify the combined presence of iframe or blockquote elements and adjacent script tags within the body of HTTP POST requests:
(?i)(<iframe\b[^>]*>.*?<\/iframe>|<blockquote\b[^>]*>.*?<\/blockquote>)\s*<script\b[^>]*src\s*=\s*['"]?
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
suneditor JiHong88 | < 3.1.4 | 3.1.4 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 (DOM-based Cross-Site Scripting) |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | Low |
| User Interaction | Passive |
| CVSS v4.0 Score | 8.5 (High) |
| Exploit Status | Proof-of-Concept Available |
| CISA KEV Status | Not Listed |
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
A high-severity path traversal vulnerability in Cloudreve's WebDAV component allows authenticated users with scoped WebDAV credentials to bypass directory containment limits and access unauthorized filesystem areas.
SENAITE LIMS core framework (senaite.core) versions 2.0.0 through 2.6.0 contain a critical vulnerability chain that permits unauthenticated remote code execution. By combining a Missing Authorization flaw (CWE-862) in multiple JSON API endpoints with an Unsafe Evaluation flaw (CWE-95) during custom field deserialization, an attacker can execute arbitrary Python commands. This execution occurs under the privileges of the hosting Zope process, creating severe risk to laboratory systems, physical instrumentation databases, and host system integrity.
A Stored Cross-Site Scripting (XSS) vulnerability exists within the legacy presentation templates of the LibreNMS network monitoring system. Due to inadequate context-aware output encoding of operational data ingested via Simple Network Management Protocol (SNMP) polling, Border Gateway Protocol (BGP) notifications, and incoming Syslog messages, an administrative user viewing device dashboards can be targeted with arbitrary JavaScript execution.
CVE-2026-54614 is an unsafe reflection vulnerability in the MailPreview component of cakephp/debug_kit prior to versions 4.10.3 and 5.2.4. Unauthenticated or low-privileged remote attackers can exploit this vulnerability to dynamically resolve and instantiate arbitrary PHP classes within the Composer autoloader environment, leading to constructor and destructor execution.
An incomplete input sanitization fix in AsyncSSH version 2.23.0 allows unauthenticated remote attackers to bypass directory restriction controls and perform path-traversal attacks. When the system is configured to perform username token substitution inside its AuthorizedKeysFile directive, attackers can manipulate downstream path resolution mechanisms via tilde expansion and environment variable references. This flaw permits authentication bypasses by forcing the server to read public keys from unauthorized file locations outside the restricted environment.
CVE-2026-54591 is a high-severity path traversal vulnerability in AsyncSSH's SCP implementation prior to version 2.23.1. When an AsyncSSH-based SCP client connects to a malicious or compromised SSH server and performs a file transfer, the server can send crafted filenames containing relative path sequences. Because the client failed to validate these filenames before resolving the final storage path, a malicious server could write or overwrite arbitrary files on the client machine within the security context of the executing application. This vulnerability is mapped to GitHub Security Advisory GHSA-2wxc-x7rj-hg8f.