Skip to main content

Open WebUI CVE-2026-54017

HIGH
Path Traversal (CWE-22)
2026-06-17 https://github.com/open-webui/open-webui GHSA-r2wg-2mcr-66rv
7.7
CVSS 3.1 · Vendor: https://github.com/open-webui/open-webui
Share

Severity by source

Vendor (https://github.com/open-webui/open-webui) PRIMARY
7.7 HIGH
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
vuln.today AI
8.5 HIGH

Network-reachable proxy, low complexity, authenticated low-privilege grant required (PR:L), scope change to upstream terminal server, high confidentiality and low integrity since traversal can also reach write-capable upstream endpoints.

3.1 AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
4.0 AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:N/SC:H/SI:L/SA:N

Primary rating from Vendor (https://github.com/open-webui/open-webui).

CVSS VectorVendor: https://github.com/open-webui/open-webui

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 18, 2026 - 01:33 vuln.today
Analysis Generated
Jun 18, 2026 - 01:33 vuln.today

DescriptionCVE.org

Summary

The terminal-server reverse proxy in backend/open_webui/routers/terminals.py does not fully confine the user-controlled path segment before forwarding it to an admin-configured terminal server. An authenticated user who has been granted access to a terminal server can craft path values containing encoded ../ traversal sequences that escape the intended path (or policy) scope on that server, reaching unintended endpoints and files on the terminal-server host. Where the terminal server fans requests out to internal services, this also gives SSRF-style reach into those services.

This is a separate code path from the /api/v1/retrieval/process/web SSRF (GHSA-c6xv-rcvw-v685), with its own input. Two distinct vectors are consolidated here:

  1. Raw path forwarding / single-encoded traversal (original report).
  2. A bypass of the subsequently-added _sanitize_proxy_path mitigation using double-encoded dots (%252e%252e).

The attacker-controlled input is the request path, supplied by the non-admin user, not anything an administrator configures, so this is not an admin-trust / Rule-9 situation.

Affected code

The proxy route forwards an arbitrary trailing path to the configured terminal server:

python
# routers/terminals.py
@router.api_route('/{server_id}/{path:path}', methods=PROXY_METHODS)
async def proxy_terminal(server_id, path, request, user=Depends(get_verified_user)):
    ...
    safe_path = _sanitize_proxy_path(path)
    if safe_path is None:
        return JSONResponse({'error': 'Invalid path'}, status_code=400)
    target_url = f'{base_url}/{safe_path}'
    policy_id = connection.get('policy_id')
    if policy_id:
        target_url = f'{base_url}/p/{policy_id}/{safe_path}'

Access requires has_connection_access(user, connection, ...), i.e. a non-admin user the administrator has granted to that terminal server.

Vector 1 - single-encoded traversal (original)

The path was originally concatenated to the base URL with no sanitization (target_url = f"{base_url}/{path}"), so single-encoded traversal escaped the intended scope:

GET /api/v1/terminals/server1/..%2F..%2F..%2Finternal-api/secrets
# proxied to: {base_url}/../../../internal-api/secrets

This vector is closed at HEAD: _sanitize_proxy_path now URL-decodes once, runs posixpath.normpath, strips leading slashes, and rejects results beginning with .. (unquote('..%2F..%2F') -> '../../' -> normpath -> '../..' -> rejected).

Vector 2 - double-encoded bypass of _sanitize_proxy_path

_sanitize_proxy_path decodes the path only once before the .. check, so a double-encoded payload survives:

python
def _sanitize_proxy_path(path: str) -> str | None:
    decoded = unquote(path)
# single decode pass only
    normalized = posixpath.normpath(decoded)
    cleaned = normalized.lstrip('/')
    if cleaned.startswith('..') or cleaned == '.':
        return None
    ...

unquote('%252e%252e/secret') yields %2e%2e/secret (not ..), which normpath leaves unchanged and which does not start with .., so it passes the check. The proxy then forwards {base_url}/%2e%2e/secret, and the upstream terminal server decodes %2e%2e into .. and resolves the traversal the check was meant to prevent.

GET /api/v1/terminals/server1/%252e%252e/%252e%252e/sensitive-file
# passes _sanitize_proxy_path as %2e%2e/%2e%2e/sensitive-file
# upstream decodes -> ../../sensitive-file

The policy_id form ({base_url}/p/{policy_id}/{safe_path}) is the higher-impact target: traversal escapes the policy namespace and reaches other policies or the terminal-server root.

Impact

An authenticated user with access to a terminal server can escape the intended path/policy scope on that server, reaching unintended endpoints and files, and, where the terminal server routes onward to internal services, reach those services. CWE-22 (Path Traversal) and CWE-918 (SSRF).

Fix

Decode the proxy path until it is stable before normalising and checking, so no depth of encoding can smuggle a traversal sequence past the check to be re-decoded upstream:

python
decoded = path
for _ in range(8):
    once = unquote(decoded)
    if once == decoded:
        break
    decoded = once
normalized = posixpath.normpath(decoded)
cleaned = normalized.lstrip('/')
if cleaned.startswith('..') or cleaned == '.':
    return None

This rejects %2e%2e, %252e%252e, %25252e%25252e, ..%2f..%2f, etc., while leaving legitimate paths (including singly-encoded characters such as %20) intact.

Credits

  • Tulgaaaaaaaa - original report (terminal-proxy path SSRF / single-encoded traversal).
  • sermikr0 - double-encoded (%252e%252e) bypass of the _sanitize_proxy_path mitigation.

AnalysisAI

Authenticated path traversal and SSRF in Open WebUI's terminal-server reverse proxy (versions <= 0.9.5) allows non-admin users with granted terminal access to escape the intended path or policy scope using double-encoded traversal sequences (%252e%252e). The flaw bypasses the project's own _sanitize_proxy_path mitigation, which performs only a single URL-decode pass before the '..' check, letting attackers reach unintended endpoints, files, and internal services routed by the terminal server. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
Authenticate to Open WebUI
Delivery
Identify granted terminal server connection
Exploit
Send request with %252e%252e double-encoded traversal
Execution
Bypass _sanitize_proxy_path single-decode check
Persist
Upstream decodes to ../ and resolves traversal
Impact
Read files or pivot SSRF into internal services

Vulnerability AssessmentAI

Exploitation Attacker must hold a valid Open WebUI user account (get_verified_user) AND be explicitly granted access by an administrator to at least one configured terminal-server connection (has_connection_access must pass); no admin role is required. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment CVSS 3.1 score of 7.7 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N) reflects network-reachable, low-complexity exploitation by an authenticated low-privilege user, with a scope change because the impacted component (the upstream terminal server and internal services) is distinct from the vulnerable Open WebUI instance. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario An authenticated Open WebUI user who has been granted access to any configured terminal server issues a request such as GET /api/v1/terminals/server1/%252e%252e/%252e%252e/sensitive-file; _sanitize_proxy_path single-decodes this to %2e%2e/%2e%2e/sensitive-file, which passes the '..' prefix check, and the upstream terminal server then decodes it again and resolves ../../sensitive-file. Where a policy_id is configured (base_url/p/{policy_id}/{safe_path}), the same trick lets the attacker escape their assigned policy namespace and read other policies or files at the terminal-server root, or pivot SSRF-style into internal services the terminal server can reach. …
Remediation Vendor-released patch: upgrade Open WebUI to 0.9.6 or later, where _sanitize_proxy_path now loops unquote up to eight times until the string stabilizes before normpath and the '..' check, neutralizing %2e%2e, %252e%252e, %25252e%25252e, and mixed forms like ..%2f..%2f. … Detailed patch versions, workarounds, and compensating controls in full report.

Recommended ActionAI

Within 24 hours: enumerate all systems running Open WebUI versions 0.9.5 or earlier with terminal-server functionality; audit which users hold terminal access privileges. …

Sign in for detailed remediation steps and compensating controls.

Threat intelligence, references, and detailed analysis are available after sign-in.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2026-55255 HIGH POC
8.4 Jun 19

Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing

Share

CVE-2026-54017 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy