CVE-2026-56104 Overview
Chainlit versions prior to 2.10.1 contain a session hijacking vulnerability in the WebSocket session restoration path. The flaw allows unauthenticated attackers to inherit authenticated user sessions by presenting a valid sessionId during reconnection, without any ownership verification. By exploiting the restore_existing_session function, an attacker assumes the victim's permissions and roles. This enables unauthorized invocation of tools and access to data restricted to the authenticated victim. The issue is classified under [CWE-862] Missing Authorization and has been patched in Chainlit release 2.10.1.
Critical Impact
Attackers who obtain or guess a valid session identifier can fully impersonate authenticated users, executing privileged tools and accessing sensitive data within the Chainlit application.
Affected Products
- Chainlit versions prior to 2.10.1
- Chainlit Python framework for conversational AI applications
- Deployments exposing the Chainlit WebSocket session restoration endpoint
Discovery Timeline
- 2026-06-22 - CVE-2026-56104 published to NVD
- 2026-06-23 - Last updated in NVD database
Technical Details for CVE-2026-56104
Vulnerability Analysis
The vulnerability resides in Chainlit's WebSocket session handling logic within backend/chainlit/socket.py. When a client reconnects, the server calls restore_existing_session(sid, session_id, ...) to rebind the WebSocket to an existing WebsocketSession. The pre-patch implementation looked up the session by ID and restored it without checking whether the requesting client owned that session. Any actor presenting a valid sessionId could attach to that session and inherit the authenticated identity bound to it.
Once attached, the attacker operates with the victim's user context across the Chainlit runtime. This includes invoking server-side tools, sending messages on behalf of the user, and retrieving persisted thread data. In LLM-driven workflows where tools wrap sensitive APIs, this becomes a direct path to data exfiltration and privileged action execution.
Root Cause
The root cause is missing authorization [CWE-862] on the session restoration path. The server trusted the client-supplied session_id as sufficient proof of session ownership and did not compare the authenticated user against the user attached to the stored WebsocketSession.
Attack Vector
An attacker needs network reachability to the Chainlit WebSocket endpoint and a valid sessionId belonging to an authenticated user. Session identifiers can be obtained through log exposure, referrer leakage, shared environments, or other side channels. The attacker initiates a WebSocket connection and supplies the captured sessionId to trigger the restore_existing_session path.
threadId: str | None
-def restore_existing_session(sid, session_id, emit_fn, emit_call_fn, environ):
+def _session_owner_matches_user(
+ session: WebsocketSession, user: User | PersistedUser | None
+) -> bool:
+ if session.user is None and user is None:
+ return True
+
+ if session.user is None or user is None:
+ return False
+
+ return session.user.identifier == user.identifier
+
+
+def restore_existing_session(
+ sid,
+ session_id,
+ emit_fn,
+ emit_call_fn,
+ environ,
+ user: User | PersistedUser | None = None,
+):
"""Restore a session from the sessionId provided by the client."""
if session := WebsocketSession.get_by_id(session_id):
+ if not _session_owner_matches_user(session, user):
+ logger.error("Authorization for the session failed.")
+ raise ConnectionRefusedError("authorization failed")
+
# Source: https://github.com/Chainlit/chainlit/commit/5effb664f1e0af4a4f0a42fe63ea979676039a7f
The patch introduces _session_owner_matches_user, which compares the stored session's user identifier against the user resolved from the current connection. Mismatches now raise ConnectionRefusedError("authorization failed").
Detection Methods for CVE-2026-56104
Indicators of Compromise
- WebSocket connections from unexpected source IP addresses reusing a sessionId previously bound to a different IP or user agent
- Application logs showing successful restore_existing_session events without corresponding authentication events from the same client
- Sudden geolocation or device fingerprint changes for an active Chainlit session
- Anomalous tool invocations or thread access occurring outside normal user activity windows
Detection Strategies
- Correlate Chainlit access logs with authentication events to identify session restorations that lack a fresh login from the same client identity
- Monitor for repeated restore_existing_session calls referencing the same sessionId from differing client identifiers
- Flag post-patch occurrences of the "Authorization for the session failed." log line, which indicates blocked hijack attempts
- Inspect reverse proxy logs for WebSocket upgrade requests carrying session identifiers across distinct user contexts
Monitoring Recommendations
- Centralize Chainlit application and WebSocket logs in your SIEM with user, session, and source IP fields normalized
- Alert on tool execution events that occur from a session whose source IP changed within the session lifetime
- Track session lifetimes and invalidate or rotate sessions that exceed expected duration thresholds
How to Mitigate CVE-2026-56104
Immediate Actions Required
- Upgrade Chainlit to version 2.10.1 or later, which enforces session ownership validation on WebSocket restoration
- Invalidate all active Chainlit sessions after upgrading to ensure no pre-existing hijacked sessions persist
- Audit recent Chainlit activity logs for unauthorized tool invocations or thread access
- Restrict network exposure of Chainlit deployments to authenticated reverse proxies or VPN-only access where feasible
Patch Information
The fix is delivered in the Chainlit 2.10.1 release via pull request #2857 and commit 5effb664. The patch adds the _session_owner_matches_user check to restore_existing_session, refusing the connection when the resolved user does not match the session owner. Additional details are available in the VulnCheck advisory.
Workarounds
- Place Chainlit behind a reverse proxy that enforces per-connection authentication and rejects WebSocket upgrades lacking valid credentials
- Shorten session lifetimes and rotate session identifiers frequently to reduce the window for hijack reuse
- Restrict access to the Chainlit instance using network controls such as IP allowlists, mTLS, or zero-trust gateways until the upgrade is applied
# Upgrade Chainlit to the patched release
pip install --upgrade "chainlit>=2.10.1"
# Verify installed version
python -c "import chainlit; print(chainlit.__version__)"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

