Mar 27, 2026·6 min read·2 visits
A flaw in Open WebUI's filename parsing allows authenticated users to leak absolute server paths by triggering verbose file-write errors in the transcription API.
Open WebUI versions prior to 0.8.6 are vulnerable to path traversal and information disclosure via the audio transcription endpoint. An authenticated attacker can manipulate the multipart form filename to disclose the absolute filesystem path of the internal application directory.
Open WebUI is a self-hosted artificial intelligence platform that includes features for processing various media types. The vulnerability resides specifically within the /api/v1/audio/transcriptions endpoint, which is responsible for receiving and processing audio files uploaded by users.
The endpoint expects multipart form data containing an audio payload but fails to properly sanitize the filename parameter supplied in the Content-Disposition header. This failure introduces two distinct but chained vulnerability classes: Path Traversal (CWE-22) and the Generation of Error Messages Containing Sensitive Information (CWE-209).
Exploitation requires the attacker to hold an authenticated session on the Open WebUI instance. Administrative privileges are not required; any standard user account possesses sufficient authorization to interact with the vulnerable transcription API and submit crafted payloads.
Upon successful exploitation, the application inadvertently reflects the absolute path of the backend application's DATA_DIR within an HTTP 400 Bad Request response. This exposes internal filesystem structures that aid in reconnaissance for subsequent targeted attacks.
The core defect exists in backend/open_webui/routers/audio.py. The application attempts to parse the file extension directly from the user-controlled filename attribute using manual string manipulation without prior structural sanitization.
The parsing mechanism splits the filename string on the period character (.) and extracts the final array element. If an attacker submits a payload containing a directory path prefixed by a period, the application incorrectly assigns the entire path string as the file extension. The application subsequently attempts to sanitize this extracted extension using a weak blocklist approach that replaces / and \ characters, but this logic executes too late or is bypassed entirely by the preceding structural extraction.
The application then attempts to open a file handle at a concatenated path utilizing this crafted extension. Because the intermediate directories generated by the application (incorporating unique UUIDs) do not exist on the underlying filesystem, the operating system kernel rejects the file creation request.
The rejected request raises a standard Python FileNotFoundError. The application catches this exception using a global error handler and reflects the raw exception string back to the client via ERROR_MESSAGES.DEFAULT(e), exposing the complete absolute path evaluated by the operating system.
The vulnerable implementation relies on an insecure manual string split operation. The code extracts the extension using ext = file.filename.split(".")[-1] if file.filename else "" and attempts to sanitize it. The sanitization logic fails because it operates under the assumption that the split operation yielded a valid, concise file extension, rather than a full system path.
If an attacker submits the filename audio./etc/passwd, the resulting extracted string is /etc/passwd. The application concatenates this to the target storage path, resulting in a variable such as f"{CACHE_DIR}/audio/transcriptions/{uuid}./etc/passwd".
The patched version, introduced in commit 387225eb8b3906909436004f84fff1b012e067d4, implements mandatory use of os.path.basename(file.filename). This standard library function correctly strips all preceding directory components from the input string before any extension parsing occurs.
Additionally, the patch modifies the exception handling block. The verbose exception reflection is replaced with a static string response. When an error occurs, the application now returns HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Transcription failed."), effectively eliminating the CWE-209 information disclosure vector entirely.
# Patched implementation in audio.py
safe_name = os.path.basename(file.filename) if file.filename else ""
ext = safe_name.rsplit(".", 1)[-1] if "." in safe_name else ""
try:
# File write operations
pass
except Exception as e:
log.exception(e) # Exception details are kept server-side
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Transcription failed.",
)Exploitation requires the attacker to possess a valid authentication token for the Open WebUI instance. The attacker initializes a standard HTTP client configured to send POST requests containing multipart form data.
The attacker constructs a POST request directed to /api/v1/audio/transcriptions. Within the Content-Disposition header for the file part, the attacker specifies a manipulated filename directive utilizing the payload pattern filename="payload./etc/passwd".
Upon receiving the request, the application parses the payload and attempts the file write operation based on the crafted extension. The application fails to write to the nonexistent intermediate path and returns an HTTP 400 Bad Request response.
The response body contains the raw Python stack trace or exception string. The attacker inspects this JSON response to locate the [Errno 2] No such file or directory: string, which is immediately followed by the server's absolute target path, successfully disclosing the internal directory structure.
The immediate security impact is isolated to information disclosure. An attacker executing this technique gains precise knowledge of the absolute filesystem path where the Open WebUI application stores its data directory.
The vulnerability does not permit arbitrary file reading, writing, or remote code execution. The file write operation inherently fails due to the application's internal reliance on generated UUID directory structures that do not exist at the root level of the provided path traversal payload.
Despite the limited direct impact, the disclosed path information provides valuable reconnaissance data. Attackers frequently utilize internal filesystem paths to craft secondary exploits, such as localized payload staging or configuring targeted arbitrary file reads in adjacent vulnerable components.
The CVSS v3.1 base score is calculated as 4.3 (Medium), reflecting the network attack vector, low complexity, low privilege requirement, and isolated impact to confidentiality.
The vendor addressed the vulnerability in Open WebUI version 0.8.6. System administrators must upgrade all deployed instances to this version or a newer release to fully remediate the flaw.
The official patch comprehensively resolves the issue by securely parsing the basename of the uploaded file and masking underlying exception details. This dual-layered fix eliminates both the path traversal vector and the side-channel information leak.
In environments where immediate patching is prohibited by operational constraints, administrators can deploy external mitigation controls. Web Application Firewalls (WAF) or reverse proxies can be configured to inspect and sanitize the filename attribute within multipart/form-data requests, dropping requests containing path traversal sequences.
Development teams maintaining similar Python web applications should systematically review all file upload endpoints. The use of robust path handling libraries, such as Python's pathlib or os.path.basename, is required for securely processing user-supplied filenames before performing any string manipulation operations.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Open WebUI Open WebUI | < 0.8.6 | 0.8.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 / CWE-209 |
| Attack Vector | Network |
| CVSS Score | 4.3 (Medium) |
| EPSS Score | 0.00020 (5.29%) |
| Impact | Information Disclosure (Absolute Path Leak) |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
Generation of Error Message Containing Sensitive Information