A logic flaw in open-webui's terminal WebSocket route lets it authenticate a user's JWT without re-checking the account's approval role, unlike every equivalent HTTP terminal endpoint. The practical effect is that an account still stuck in 'pending' status, whether freshly registered or deactivated after the fact, can open a live interactive shell in a connected terminal server as long as its four-week token hasn't expired and the server's access grants cover it. This only bites deployments that have configured a terminal server at all, which is off by default, and EPSS puts real-world exploitation likelihood low (0.00207, no public PoC, no Nuclei template, CISA SSVC rates it TRACK not KEV) — so this is a fix-on-next-patch-cycle item rather than a fire drill. Deployments running open-webui 0.8.8 through 0.10.x with a terminal server exposed to broad grants (public read or a shared group) should upgrade to v0.11.0, which consolidates token validation, revocation checking, and the role check into a single get_verified_user_by_token helper shared by both the WebSocket and Socket.IO handshake paths.
What is the risk?
Medium severity (CVSS 6.3) is well-calibrated: the vector requires a valid authenticated JWT (PR:L) and no user interaction, but confidentiality/integrity/availability impact is capped at Low each because the terminal access grants themselves are enforced correctly — an account with zero grants is still refused. Exploitability is low in practice: it requires a non-default configuration (a terminal server must be set up), a specific account state (pending or deactivated-to-pending), and knowledge of the terminal server id. EPSS (0.00207) and the absence of a public exploit or scanner template both support a low near-term exploitation probability. The real risk is process drift rather than raw severity: an admin who deactivates a compromised or offboarded user reasonably believes access is revoked, but the WebSocket plane silently disagrees with the HTTP plane for up to four weeks.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Open WebUI | pip | >= 0.8.8, < 0.11.0 | 0.11.0 |
Do you use Open WebUI? You're affected.
How severe is it?
What is the attack surface?
What should I do?
1 step-
Upgrade to open-webui v0.11.0 or later, which is a drop-in fix with no configuration change required. If immediate upgrade isn't possible: (1) audit whether any terminal server is configured and, if so, restrict its access grants to admin-only rather than public/group-wide as an interim compensating control; (2) reduce JWT lifetime from the four-week default so deactivated accounts lose access faster; (3) for detection, review WebSocket connection logs to
/{server_id}/api/terminals/{session_id}for connections from accounts whose role is or recently was 'pending', and cross-reference against HTTP terminal endpoint 403s from the same account — a WebSocket connection succeeding where the HTTP route would reject is the signature of this bug being exploited.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-70490?
A logic flaw in open-webui's terminal WebSocket route lets it authenticate a user's JWT without re-checking the account's approval role, unlike every equivalent HTTP terminal endpoint. The practical effect is that an account still stuck in 'pending' status, whether freshly registered or deactivated after the fact, can open a live interactive shell in a connected terminal server as long as its four-week token hasn't expired and the server's access grants cover it. This only bites deployments that have configured a terminal server at all, which is off by default, and EPSS puts real-world exploitation likelihood low (0.00207, no public PoC, no Nuclei template, CISA SSVC rates it TRACK not KEV) — so this is a fix-on-next-patch-cycle item rather than a fire drill. Deployments running open-webui 0.8.8 through 0.10.x with a terminal server exposed to broad grants (public read or a shared group) should upgrade to v0.11.0, which consolidates token validation, revocation checking, and the role check into a single get_verified_user_by_token helper shared by both the WebSocket and Socket.IO handshake paths.
Is CVE-2026-70490 actively exploited?
No confirmed active exploitation of CVE-2026-70490 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-70490?
Upgrade to open-webui v0.11.0 or later, which is a drop-in fix with no configuration change required. If immediate upgrade isn't possible: (1) audit whether any terminal server is configured and, if so, restrict its access grants to admin-only rather than public/group-wide as an interim compensating control; (2) reduce JWT lifetime from the four-week default so deactivated accounts lose access faster; (3) for detection, review WebSocket connection logs to `/{server_id}/api/terminals/{session_id}` for connections from accounts whose role is or recently was 'pending', and cross-reference against HTTP terminal endpoint 403s from the same account — a WebSocket connection succeeding where the HTTP route would reject is the signature of this bug being exploited.
What systems are affected by CVE-2026-70490?
This vulnerability affects the following AI/ML architecture patterns: model serving, agent frameworks.
What is the CVSS score for CVE-2026-70490?
CVE-2026-70490 has a CVSS v3.1 base score of 6.3 (MEDIUM). The EPSS exploitation probability is 0.28%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0012 Valid Accounts AML.T0050 Command and Scripting Interpreter AML.T0091.000 Application Access Token Compliance Controls Affected
What are the technical details?
Original Advisory
## Summary The terminal WebSocket route authenticates its own first-message JWT instead of going through the HTTP dependency chain, and never applies the role check that `get_verified_user` enforces on every HTTP terminal route. An account whose role is `pending`, meaning registered but not approved, or approved and later deactivated back to `pending`, can therefore open an interactive terminal session that the HTTP terminal endpoints would refuse. The missing control is the verified-user role gate, not the terminal access grants, which are evaluated correctly. ## Preconditions At least one terminal server must be configured, which is off by default, and its access grants must cover the account: either public read (`principal_id: "*"`) or a group the account still belongs to. The attacker needs a valid, unexpired JWT for a `pending` account and the terminal server id. Both are obtainable by an account that registered while approvals are pending, or by one that held access and was deactivated, since deactivation sets the role to `pending` without revoking the token, which lasts four weeks by default. Deployments with no terminal server configured, or whose terminal grants are admin-only, are not affected. ## Impact A deployment loses the account-approval boundary for terminal access. An unapproved or deactivated account gets interactive shell access, file browsing and terminal-backed tooling in the terminal environment, for as long as its token remains valid. Because the HTTP terminal routes correctly reject the same account, the two planes disagree, so an administrator who deactivates a user sees access revoked over HTTP while the WebSocket keeps working. The terminal access grants themselves are not bypassed: an account with no grant is still refused, so this only widens access to terminals already shared broadly or with a group the account remains in. ## Fix Fixed in v0.11.0 by https://github.com/open-webui/open-webui/pull/27537. Token decoding, revocation checking, user lookup and the role check are consolidated into a single `get_verified_user_by_token` helper, and both the terminal WebSocket route and the Socket.IO handshake now go through it. The role set lives in one constant shared with the HTTP gate so the two cannot drift apart again. Upgrading fully resolves the issue; no configuration change is required. ## Root cause Affected component: `backend/open_webui/routers/terminals.py`, the `_resolve_authenticated_connection` helper backing the `/{server_id}/api/terminals/{session_id}` WebSocket route. Affected setup: every build from v0.8.8 onward, since the route was introduced there. WebSocket handshakes cannot use FastAPI dependencies, so this route reimplemented authentication inline. The reimplementation reproduced the parts that are visible in the token, that it decodes and that the user row exists, and silently dropped the part that lives in the database row, the role check. Authorization then ran on two independent code paths with no shared definition of what an authenticated user is, and only one of them was updated when the role gate was introduced. ## Credits Reported by @rexpository.
Exploitation Scenario
An employee registers a self-service open-webui account that requires admin approval; before approval lands, they notice their JWT already works for chat. They discover (or are told) that a terminal server is configured with a group grant they belong to, and connect directly to the WebSocket terminal endpoint using their still-valid, still-pending-role token. The HTTP terminal UI would reject them with a 403, but the WebSocket path only checks that the token decodes and the user row exists — not the role — so they land an interactive shell in the terminal environment. From there they browse files and run commands via terminal-backed tooling for as long as the token remains valid (up to four weeks), even if an admin later deactivates the account under the belief that HTTP-side revocation is sufficient.
Weaknesses (CWE)
CWE-863 — Incorrect Authorization: The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
- [Architecture and Design] Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries. Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
- [Architecture and Design] Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L References
Timeline
Related Vulnerabilities
CVE-2026-44551 9.1 open-webui: LDAP auth bypass — full account takeover
Same package: open-webui CVE-2026-45672 8.8 open-webui: code exec gate bypass via API endpoint
Same package: open-webui CVE-2026-44552 8.7 open-webui: Redis cache poisoning enables cross-instance tool hijack
Same package: open-webui CVE-2025-64495 8.7 Open WebUI: XSS-to-RCE via malicious prompt injection
Same package: open-webui CVE-2026-45315 8.7 open-webui: stored XSS → JWT theft and admin takeover
Same package: open-webui