NewApp Monitoring is liveSign up free
AgentbeamBeta
AI agent vulnerability · Open WebUI

CVE-2026-70490: Open WebUI: Unapproved accounts can open terminal sessions via a WebSocket auth path missing the role check

mediumCVSS 3.1 6.3GHSA-5gpj-vj23-vhhv

Open WebUI 0.8.8 up to 0.10.x lets accounts that are not approved, or were deactivated, open interactive terminal sessions over WebSocket. The WebSocket route skips the role check the HTTP terminal routes enforce. It matters only where a terminal server is configured. Upgrade to 0.11.0.

Published Aug 4, 2026 · Analysis Oct 25, 2026

What an attacker can do

WebSocket handshakes cannot use FastAPI dependencies, so _resolve_authenticated_connection in backend/open_webui/routers/terminals.py re-implemented authentication for the /{server_id}/api/terminals/{session_id} route. It checked the JWT and that the user row exists, but dropped the role check that get_verified_user applies on every HTTP terminal route. An account with role pending therefore gets a shell session that the HTTP endpoints refuse.

The attacker needs a valid, unexpired JWT for a pending account and the terminal server id. Both are available to someone who registered while approval is pending. They are also available to a user an admin deactivated: deactivation sets the role to pending without revoking the token, which lasts four weeks by default. A terminal server must be configured (off by default) and its grants must cover the account, either public read (principal_id: "*") or a group the account still belongs to.

The result is interactive shell, file browsing and terminal-backed tooling for as long as the token lives. Admins see access revoked over HTTP while the WebSocket keeps working. Terminal grants themselves still hold: an account with no grant is refused.

Who is affected

Open WebUI >= 0.8.8, < 0.11.0 with at least one terminal server configured and grants that are public or reach a group the account still belongs to. Deployments with no terminal server, or with admin-only grants, are not affected. Check the version:

pip show open-webui

open-webui

Ecosystem
PyPI
Affected
>= 0.8.8, < 0.11.0
Fixed in
0.11.0
Check
pip show open-webui

How to fix it

Upgrade to 0.11.0:

pip install --upgrade open-webui==0.11.0

Pull request 27537 merges token decoding, revocation checking, user lookup and the role check into one get_verified_user_by_token helper. Both the terminal WebSocket route and the Socket.IO handshake use it, and the role set is shared with the HTTP gate. No configuration change is needed. Until then, narrowing terminal grants to admins removes the exposure, per the stated preconditions.

How to tell if you were hit

List accounts with role pending, especially ones that were deactivated recently, and check terminal server logs and Open WebUI logs for WebSocket sessions on /{server_id}/api/terminals/{session_id} opened by them. Look inside terminal environments for shell history and files created by those users. After upgrading, deactivated users' still-valid tokens lose live access, per the 0.11.0 release notes.

Original advisory

From the GitHub Advisory Database (CC BY 4.0).

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.

Credited to rexpository, Classic298.

Questions

Does CVE-2026-70490 bypass terminal access grants?

No. An account with no grant is still refused. It widens access only to terminals already shared publicly or with a group the unapproved account belongs to.

Why does a deactivated user keep access?

Deactivation sets the role to pending but does not revoke the JWT, which is valid for four weeks by default. The HTTP routes reject it, but the WebSocket route did not check the role.

Am I affected without a terminal server?

No. The advisory says deployments with no terminal server configured are not affected. Terminal servers are off by default.

References

How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology

More Open WebUI vulnerabilities

All Open WebUI entries