Jul 7, 2026·6 min read·18 visits
A stored XSS vulnerability in Open WebUI allows low-privileged users to achieve remote code execution (RCE) by tricking an administrator into opening an uploaded HTML file, bypassing logical checks to register unauthorized backend functions.
Open WebUI versions prior to 0.6.6 contain a stored cross-site scripting (XSS) vulnerability that allows low-privileged users to upload malicious HTML files containing arbitrary JavaScript. When viewed by an administrator, the executed script can abuse administrative APIs to register malicious functions, leading to remote code execution on the underlying server host.
Open WebUI is a self-hosted artificial intelligence platform designed to operate entirely offline. The system exposes an API endpoint at /api/v1/files/ to handle user-uploaded documents and static assets. This backend endpoint serves as the primary mechanism for low-privileged users to ingest documents into the platform's knowledge base.
The vulnerability, tracked as CVE-2025-46571, resides in the handling of HTML file uploads. The backend exposes a dedicated router designed to render HTML content within the browser context. This endpoint serves files with the text/html MIME type directly under the application origin, exposing a stored cross-site scripting attack surface.
While default permissions restrict low-privileged users to viewing only their own files, administrative users are allowed to access any uploaded resource. An attacker can leverage this logical permission model to target administrators. By sending a malicious link, the attacker can execute arbitrary script code within the administrative session context.
The root cause of CVE-2025-46571 lies in the incorrect neutralization of user-supplied HTML content and a subsequent flawed logical access control check. When a file is requested via /api/v1/files/{id}/content/html, the backend uses FastAPI's FileResponse to serve the document. The server returns the content with a Content-Type: text/html response header.
Because the file is served from the same domain as the main web interface, the browser executes any embedded <script> tags within the parent origin. This execution environment permits the malicious script to access sensitive local storage variables, cookies, and authentication headers. Consequently, the script bypasses standard browser security protections like the Same-Origin Policy.
The initial attempt to fix this issue introduced a flawed logical comparison. The code verified the role of the file owner rather than properly restricting administrative access. The logic checked if the owner of the file was not an administrator, but the subsequent exception-raising block was bypassed when the user object existed, allowing execution to fall through.
The flawed access control verification in commit ef2aeb7c0eb976bac759e59ac359c94a5b8dc7e0 relied on synchronous database checks that failed to raise an HTTP exception when a standard user account was found. The conditional block evaluated the file owner's role but did not stop the request if the owner was a non-admin user.
# Vulnerable implementation in ef2aeb7
file_user = Users.get_user_by_id(file.user_id)
if not file_user.role == "admin":
if not file_user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=ERROR_MESSAGES.NOT_FOUND,
)In this logic, if file_user is a regular user (not an admin), not file_user.role == "admin" evaluates to True. The flow enters the block and checks if not file_user:. Since the user exists, not file_user is False. The code skips the raise HTTPException statement and continues execution, serving the file.
# Corrected implementation in v0.6.6
file_user = await Users.get_user_by_id(file.user_id, db=db)
if not file_user or file_user.role != 'admin':
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=ERROR_MESSAGES.NOT_FOUND,
)In the corrected version, the logic checks if the user is missing or if the role is not 'admin'. If either condition is true, it immediately raises an HTTP 404 error. This correctly blocks any HTML content uploaded by a low-privileged user from being served.
To exploit this vulnerability, an attacker must first obtain low-privileged credentials to authenticate to the Open WebUI instance. The attacker uploads a custom HTML document containing a malicious payload to /api/v1/files/. The backend returns a JSON payload containing the assigned id of the uploaded file.
The attacker then targets an administrator by sending a direct link to /api/v1/files/{id}/content/html. Because administrators can bypass the standard file-sharing restrictions, the application permits the rendering of the HTML file. The browser then executes the embedded JavaScript within the administrator's authenticated session.
The malicious script executes administrative API calls in the background. It can target Open WebUI's custom Functions API to register a malicious Filter or Pipeline containing python code. Since Open WebUI evaluates these python-based functions on the server, the administrative API call results in full remote code execution.
The impact of CVE-2025-46571 is classified as high because it allows a low-privileged user to achieve administrative access and execute arbitrary commands on the host system. Although classified as Stored XSS, the chain of trust in Open WebUI means that administrative compromise is equivalent to remote code execution.
The CVSS v3.1 base score is 5.4, indicating medium severity due to the requirement of user interaction. However, under CVSS v4.0, the impact metrics yield a base score of 5.3, emphasizing the potential for complete compromise of integrity and availability on subsequent systems if administrators are targeted.
Because Open WebUI operates in self-hosted, often high-privilege environments to manage private AI workloads, achieving remote code execution compromises all connected databases, private model weights, and local system environments. This highlights the severity of the flaw despite the user-interaction requirement.
The primary mitigation for this vulnerability is upgrading Open WebUI to version 0.6.6 or newer. The update implements correct asynchronous database checks that safely restrict HTML document retrieval to resources owned by administrators, preventing standard users from rendering arbitrary scripts.
If immediate upgrades are not possible, administrators should restrict file uploads containing HTML MIME types at the reverse proxy or web application firewall level. Blocking requests ending with .html, .htm, or .xhtml targeted at the files router will mitigate the initial upload phase of the attack.
Additionally, implementing a strict Content Security Policy (CSP) can limit the impact of unexpected XSS. Serving user-uploaded content from a distinct, sandboxed origin ensures that any script execution does not share cookies or local storage with the primary application, neutralizing the session hijacking vector.
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
open-webui open-webui | < 0.6.6 | 0.6.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Attack Vector | Network |
| CVSS Score | 5.4 (Medium) |
| EPSS Score | 0.003 (0.30%) |
| Exploit Status | poc |
| CISA KEV Status | Not Listed |
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
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.
A critical security bypass vulnerability in Argo Workflows allows authenticated attackers with workflow submission privileges to bypass 'Strict' or 'Secure' template referencing restrictions. By injecting unvalidated fields into the nested ArtifactGC configuration, attackers can execute arbitrary pod patches, leading to host namespace escape and cluster-wide privilege escalation.
A Server-Side Request Forgery (SSRF) / Confused Deputy vulnerability has been identified in Pydantic AI UI Adapters (such as VercelAIAdapter). Under certain conditions, a malicious client can supply manipulated message history with provider metadata that forces the server to resolve files within privileged cloud environments (AWS S3, Google Cloud Storage) or model providers. This occurs because the adapters deserialize client-provided metadata structures directly into UploadedFile instances without validation, which are subsequently fetched using high-privilege server credentials.
A path traversal vulnerability in the optional dashboard server of atomic-agents-stack before version 1.1.0 allows unauthenticated remote attackers to read arbitrary files from the host filesystem.