Open WebUI Stored XSS Vulnerability via OAuth Profile Picture
Open WebUI is vulnerable to stored cross-site scripting (XSS) via OAuth profile picture handling, allowing an attacker to inject malicious SVG code and potentially takeover user accounts by exfiltrating JWT tokens.
Open WebUI versions 0.9.4 and earlier are vulnerable to a stored cross-site scripting (XSS) attack due to improper validation of profile images when users sign in via OAuth. The application fetches a URL provided in the OAuth picture claim, infers the MIME type from the URL extension, and stores it as a data URI without proper sanitization. Specifically, an attacker can host a malicious SVG file and set their profile picture URL to that file. When a victim clicks the link to the attacker's profile image, the browser executes the SVG code, potentially leading to account takeover by exfiltrating the victim's JWT token. This vulnerability is similar to CVE-2025-64496 and CVE-2025-64495, which highlights trust boundary errors in Open WebUI.
Attack Chain
- The attacker crafts a malicious SVG file containing JavaScript code to exfiltrate
localStorage.token. - The attacker hosts the malicious SVG file on a publicly accessible server (e.g.,
https://attacker.example/p.svg). - The attacker configures their OAuth profile picture URL to point to the malicious SVG file.
- The attacker signs in to Open WebUI via OAuth, triggering the application to fetch and store the SVG data URI as their profile image.
- The attacker crafts a URL to their profile image endpoint (e.g.,
https://target.example/api/v1/users/<attacker-user-id>/profile/image) and shares it with a victim. - The authenticated victim clicks on the link.
- The server serves the attacker-controlled SVG with
Content-Type: image/svg+xmlandContent-Disposition: inline. - The victim's browser renders the SVG, executes the embedded JavaScript, and exfiltrates the victim's JWT token to the attacker's server.
Impact
Successful exploitation can lead to account takeover of any authenticated user who clicks the malicious link. The attacker can then access the victim's chats, API keys, and potentially achieve remote code execution (RCE) via installed tools if the victim has the workspace.tools permission. Furthermore, the lack of SSRF protection allows an attacker to potentially read internal resources by pointing the picture claim at internal URLs.
Recommendation
- Implement server-side MIME type validation in
_process_picture_url(utils/oauth.py:1336-1345) to only allowimage/png,image/jpeg,image/gif, andimage/webp. Use theContent-Typeresponse header instead of the URL extension. - Enforce a MIME whitelist in
get_user_profile_image_by_id(routers/users.py:504-528) before building theStreamingResponse. - Apply the
validate_profile_image_urlvalidator at the model layer (Users.update_user_profile_image_url_by_id), not just at the Pydantic form layer, to ensure all profile image updates are validated. - Enable
X-Content-Type-Options: nosniffand set a default Content Security Policy (CSP) to mitigate XSS attacks by setting the appropriate environment variables.
Detection coverage 2
Detect Open WebUI Profile Image XSS via SVG Upload
highDetects attempts to upload SVG files as profile images in Open WebUI, which can lead to stored XSS (CVE-2025-64496, CVE-2025-64495, GHSA-3wgj-c2hg-vm6q).
Detect Open WebUI OAuth Profile Picture with SVG MIME Type
mediumDetects the storage of SVG MIME types in profile images in Open WebUI via the OAuth flow, indicating a potential XSS vulnerability (GHSA-3wgj-c2hg-vm6q).
Detection queries are available on the platform. Get full rules →
Indicators of compromise
3
url
| Type | Value |
|---|---|
| url | https://attacker.example/p.svg |
| url | https://attacker.example/x?c= |
| url | https://target.example/api/v1/users/<attacker-user-id>/profile/image |