CVE-2026-59219
Open WebUI: Realtime endpoints accept Redis-revoked JWTs after signout/backchannel logout
Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.9.0 before 0.10.0 with Redis configured, Socket.IO connect, user-join, join-channels, join-note, and the terminal websocket first-message authentication used decode_token without the Redis-backed is_valid_token revocation check, allowing revoked JWTs to continue authenticating realtime connections. This issue is fixed in version 0.10.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.1
Open WebUI: Realtime endpoints accept Redis-revoked JWTs after signout/backchannel logout
Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.9.0 before 0.10.0 with Redis configured, Socket.IO connect, user-join, join-channels, join-note, and the terminal websocket first-message authentication used decode_token without the Redis-backed is_valid_token revocation check, allowing revoked JWTs to continue authenticating realtime connections. This issue is fixed in version 0.10.0.
- Record
CVE-2026-59219- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - Weakness
- CWE-613
- Updated
- 2026-11-02
EUVDEUVD-2026-42625
7.1
Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.9.0 before 0.10.0 with Redis configured, Socket.IO connect, user-join, join-channels, join-note, and the terminal websocket first-message authentication used decode_token without the Redis-backed is_valid_token revocation check, allowing revoked JWTs to continue authenticating realtime connections. This issue is fixed in version 0.10.0.
- Record
EUVD-2026-42625- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-855v-hq7w-jmjw
7.1
Open WebUI: Realtime endpoints accept Redis-revoked JWTs after signout/backchannel logout
Summary
With Redis configured, Open WebUI supports JWT revocation: POST /api/v1/auths/signout (per-token jti) and OIDC back-channel logout (per-user revoked_at) record revocations in Redis, and HTTP auth (get_current_user) rejects revoked tokens with 401. The realtime authentication surfaces do not perform this check: Socket.IO connect / user-join / join-channels / join-note and the terminal websocket first-message auth validate tokens with decode_token() only (signature + expiry). A JWT revoked by sign-out or back-channel logout therefore continues to authenticate new realtime connections, even though the same token is rejected on HTTP.
Affected component
backend/open_webui/socket/main.py— Socket.IOconnect,user-join,join-channels,join-notebackend/open_webui/routers/terminals.py— terminal websocket first-message authbackend/open_webui/utils/auth.py— the revocation check was applied to HTTP only
Root cause
HTTP auth enforces revocation:
# utils/auth.py — get_current_user
if data.get('jti') and not await is_valid_token(request, data):
raise HTTPException(status_code=401, detail='Invalid token')
Realtime auth calls decode_token() only, which verifies signature + expiry but never consults the Redis revocation keys ({prefix}:auth:token:{jti}:revoked, {prefix}:auth:user:{id}:revoked_at):
# socket/main.py — connect / user-join / join-channels / join-note
data = decode_token(auth['token'])
# routers/terminals.py — _resolve_authenticated_connection
data = decode_token(token)
Impact
A JWT revoked by user sign-out or OIDC back-channel logout still authenticates new realtime connections. A stolen token therefore retains realtime access after the victim signs out or the IdP performs back-channel logout — the very remediation for a compromised token. The token can populate SESSION_POOL as the victim, join their user/channel/note rooms (receiving realtime channel messages, collaborative-note updates and presence), drive socket-level collaboration as the victim, and pass terminal websocket authentication when terminal servers are configured. HTTP remains correctly protected (401), so REST data and state-changing REST endpoints are not reachable with the revoked token.
Proof of Concept
Reporter PoC on a Redis-backed deployment (v0.9.6 and main): after POST /api/v1/auths/signout, HTTP returns 401 for the token while a Socket.IO user-join with the same token still authenticates, and the terminal WS reaches terminal-server lookup rather than rejecting it as Invalid token.
Fix
Apply the revocation check on the realtime paths. The logic is factored into is_token_revoked(redis, decoded) (covering per-token jti and per-user revoked_at); the Socket.IO handlers and the terminal WS reject tokens that fail it, using the main app Redis where revocations are stored. HTTP is_valid_token delegates to the same helper, so HTTP behaviour is unchanged.
Affected / Patched
- Affected:
>= 0.9.0, < 0.10.0, and only when Redis is configured (without Redis, per-token revocation is not supported and sign-out does not invalidate JWTs by design). - Patched: v0.10.0. The revocation check (
is_valid_token, covering per-tokenjtiand per-userrevoked_at) is applied on Socket.IO connect / user-join / join-channels / join-note and the terminal websocket first-message auth, using the main app Redis where revocations are stored. HTTPis_valid_tokendelegates to the same logic, so HTTP behaviour is unchanged.
- Record
GHSA-855v-hq7w-jmjw- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - Weakness
- CWE-613
- Updated
- 2026-11-02
NVD
7.1
Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.9.0 before 0.10.0 with Redis configured, Socket.IO connect, user-join, join-channels, join-note, and the terminal websocket first-message authentication used decode_token without the Redis-backed is_valid_token revocation check, allowing revoked JWTs to continue authenticating realtime connections. This issue is fixed in version 0.10.0.
- Record
CVE-2026-59219- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - Weakness
- CWE-613
- Updated
- 2026-11-02
OSV
7.1
Open WebUI: Realtime endpoints accept Redis-revoked JWTs after signout/backchannel logout
Open WebUI is an extensible, feature-rich, and user-friendly self-hosted AI platform. From 0.9.0 before 0.10.0 with Redis configured, Socket.IO connect, user-join, join-channels, join-note, and the terminal websocket first-message authentication used decode_token without the Redis-backed is_valid_token revocation check, allowing revoked JWTs to continue authenticating realtime connections. This issue is fixed in version 0.10.0.
- Record
CVE-2026-59219- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - Weakness
- CWE-613
- Updated
- 2026-11-02
OSVGHSA-855v-hq7w-jmjw
7.1
Open WebUI: Realtime endpoints accept Redis-revoked JWTs after signout/backchannel logout
Summary
With Redis configured, Open WebUI supports JWT revocation: POST /api/v1/auths/signout (per-token jti) and OIDC back-channel logout (per-user revoked_at) record revocations in Redis, and HTTP auth (get_current_user) rejects revoked tokens with 401. The realtime authentication surfaces do not perform this check: Socket.IO connect / user-join / join-channels / join-note and the terminal websocket first-message auth validate tokens with decode_token() only (signature + expiry). A JWT revoked by sign-out or back-channel logout therefore continues to authenticate new realtime connections, even though the same token is rejected on HTTP.
Affected component
backend/open_webui/socket/main.py— Socket.IOconnect,user-join,join-channels,join-notebackend/open_webui/routers/terminals.py— terminal websocket first-message authbackend/open_webui/utils/auth.py— the revocation check was applied to HTTP only
Root cause
HTTP auth enforces revocation:
# utils/auth.py — get_current_user
if data.get('jti') and not await is_valid_token(request, data):
raise HTTPException(status_code=401, detail='Invalid token')
Realtime auth calls decode_token() only, which verifies signature + expiry but never consults the Redis revocation keys ({prefix}:auth:token:{jti}:revoked, {prefix}:auth:user:{id}:revoked_at):
# socket/main.py — connect / user-join / join-channels / join-note
data = decode_token(auth['token'])
# routers/terminals.py — _resolve_authenticated_connection
data = decode_token(token)
Impact
A JWT revoked by user sign-out or OIDC back-channel logout still authenticates new realtime connections. A stolen token therefore retains realtime access after the victim signs out or the IdP performs back-channel logout — the very remediation for a compromised token. The token can populate SESSION_POOL as the victim, join their user/channel/note rooms (receiving realtime channel messages, collaborative-note updates and presence), drive socket-level collaboration as the victim, and pass terminal websocket authentication when terminal servers are configured. HTTP remains correctly protected (401), so REST data and state-changing REST endpoints are not reachable with the revoked token.
Proof of Concept
Reporter PoC on a Redis-backed deployment (v0.9.6 and main): after POST /api/v1/auths/signout, HTTP returns 401 for the token while a Socket.IO user-join with the same token still authenticates, and the terminal WS reaches terminal-server lookup rather than rejecting it as Invalid token.
Fix
Apply the revocation check on the realtime paths. The logic is factored into is_token_revoked(redis, decoded) (covering per-token jti and per-user revoked_at); the Socket.IO handlers and the terminal WS reject tokens that fail it, using the main app Redis where revocations are stored. HTTP is_valid_token delegates to the same helper, so HTTP behaviour is unchanged.
Affected / Patched
- Affected:
>= 0.9.0, < 0.10.0, and only when Redis is configured (without Redis, per-token revocation is not supported and sign-out does not invalidate JWTs by design). - Patched: v0.10.0. The revocation check (
is_valid_token, covering per-tokenjtiand per-userrevoked_at) is applied on Socket.IO connect / user-join / join-channels / join-note and the terminal websocket first-message auth, using the main app Redis where revocations are stored. HTTPis_valid_tokendelegates to the same logic, so HTTP behaviour is unchanged.
- Record
GHSA-855v-hq7w-jmjw- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - Weakness
- CWE-613
- Updated
- 2026-11-02
OSVPYSEC-2026-3595
7.1
Open WebUI: Realtime endpoints accept Redis-revoked JWTs after signout/backchannel logout
Summary
With Redis configured, Open WebUI supports JWT revocation: POST /api/v1/auths/signout (per-token jti) and OIDC back-channel logout (per-user revoked_at) record revocations in Redis, and HTTP auth (get_current_user) rejects revoked tokens with 401. The realtime authentication surfaces do not perform this check: Socket.IO connect / user-join / join-channels / join-note and the terminal websocket first-message auth validate tokens with decode_token() only (signature + expiry). A JWT revoked by sign-out or back-channel logout therefore continues to authenticate new realtime connections, even though the same token is rejected on HTTP.
Affected component
backend/open_webui/socket/main.py— Socket.IOconnect,user-join,join-channels,join-notebackend/open_webui/routers/terminals.py— terminal websocket first-message authbackend/open_webui/utils/auth.py— the revocation check was applied to HTTP only
Root cause
HTTP auth enforces revocation:
# utils/auth.py — get_current_user
if data.get('jti') and not await is_valid_token(request, data):
raise HTTPException(status_code=401, detail='Invalid token')
Realtime auth calls decode_token() only, which verifies signature + expiry but never consults the Redis revocation keys ({prefix}:auth:token:{jti}:revoked, {prefix}:auth:user:{id}:revoked_at):
# socket/main.py — connect / user-join / join-channels / join-note
data = decode_token(auth['token'])
# routers/terminals.py — _resolve_authenticated_connection
data = decode_token(token)
Impact
A JWT revoked by user sign-out or OIDC back-channel logout still authenticates new realtime connections. A stolen token therefore retains realtime access after the victim signs out or the IdP performs back-channel logout — the very remediation for a compromised token. The token can populate SESSION_POOL as the victim, join their user/channel/note rooms (receiving realtime channel messages, collaborative-note updates and presence), drive socket-level collaboration as the victim, and pass terminal websocket authentication when terminal servers are configured. HTTP remains correctly protected (401), so REST data and state-changing REST endpoints are not reachable with the revoked token.
Proof of Concept
Reporter PoC on a Redis-backed deployment (v0.9.6 and main): after POST /api/v1/auths/signout, HTTP returns 401 for the token while a Socket.IO user-join with the same token still authenticates, and the terminal WS reaches terminal-server lookup rather than rejecting it as Invalid token.
Fix
Apply the revocation check on the realtime paths. The logic is factored into is_token_revoked(redis, decoded) (covering per-token jti and per-user revoked_at); the Socket.IO handlers and the terminal WS reject tokens that fail it, using the main app Redis where revocations are stored. HTTP is_valid_token delegates to the same helper, so HTTP behaviour is unchanged.
Affected / Patched
- Affected:
>= 0.9.0, < 0.10.0, and only when Redis is configured (without Redis, per-token revocation is not supported and sign-out does not invalidate JWTs by design). - Patched: v0.10.0. The revocation check (
is_valid_token, covering per-tokenjtiand per-userrevoked_at) is applied on Socket.IO connect / user-join / join-channels / join-note and the terminal websocket first-message auth, using the main app Redis where revocations are stored. HTTPis_valid_tokendelegates to the same logic, so HTTP behaviour is unchanged.
- Record
PYSEC-2026-3595- CVSS 3.1
- 7.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
open-webuiPyPI |
0.9.0 up to 0.10.0 | 0.10.0 |
open-webuiPyPI |
0.9.0 up to 0.10.0, plus listed versions 0.9.10.9.20.9.30.9.40.9.50.9.6 |
0.10.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-59219 is a high vulnerability (CVSS 7.1) in Openwebui Open Webui, published July 9, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.55%, the 46th percentile. Fixed in open-webui 0.10.0.
References
github.com/open-webui/open-webui/security/advisories/GHSA-855v-hq7w-jmjw
github.com/open-webui/open-webui/commit/33b91bd8ae8a100a5a306c91441a7d0b422c4cde
github.com/open-webui/open-webui/releases/tag/v0.10.0
nvd.nist.gov/vuln/detail/CVE-2026-59219
github.com/advisories/GHSA-855v-hq7w-jmjw
github.com/CVEProject/cvelistV5/tree/main/cves/2026/59xxx/CVE-2026-59219.json
github.com/open-webui/open-webui
pypi.org/project/open-webui