Sep 10, 2026·7 min read·3 visits
Authenticated users can trigger a persistent infinite loop in the Open WebUI backend, completely freezing the server and exhausting host memory by saving a cyclic chat history.
An infinite loop vulnerability (CWE-835) in Open WebUI versions 0.5.0 through 0.11.0 allows authenticated attackers to cause a complete and persistent Denial of Service (DoS) of the backend. By submitting a specially crafted chat history containing cyclic message references that omit internal message identifiers, the cycle detection mechanism is bypassed. This triggers an infinite synchronous traversal that blocks the single-threaded asyncio event loop and exhausts system memory, causing the application to crash.
Open WebUI is an extensible, feature-rich, self-hosted interface for artificial intelligence models. The backend server manages user chat sessions, conversation states, and message histories. A vulnerability exists in the chat message-chain reconstruction utility within the backend component. This flaw allows authenticated users to trigger a persistent Denial of Service (DoS) condition on the server.
The issue lies specifically in the get_message_list function located in the backend/open_webui/utils/misc.py module. This helper function is responsible for parsing a stored map of chat messages and rebuilding a linear representation of a conversation thread. When a client requests or updates a chat session, the server traverses this structure to establish the message hierarchy.
Under normal operation, the traversal logic expects a directed acyclic graph representing the conversation history. However, the system fails to robustly detect loops in the graph when messages omit specific internal identity attributes. Because the backend relies on a single-threaded asynchronous architecture, any CPU-bound infinite iteration in this component completely blocks the execution flow.
The root cause of this vulnerability is an infinite loop (CWE-835) arising from a desynchronization between database-level lookup keys and internal message-body attributes during cycle detection. The reconstruction utility, get_message_list, parses the history by walking backward from a terminal message node. It iteratively resolves parent references using the parentId field of each message.
To prevent circular references from causing an infinite loop, the function implements a cycle detector that maintains a set of visited message identifiers. However, instead of tracking the dictionary lookup keys used to query the message map, the code queries the message body for an optional 'id' attribute. If an attacker crafts a message node where this internal 'id' property is absent or set to None, the cycle detector resolves the ID as None.
Because the tracking logic evaluates whether the parsed ID is not None before adding it to the visited set, a value of None prevents the ID from being recorded. The loop continues to traverse the next node based on the parentId reference. When these nodes refer back to one another in a cyclic structure, the loop iterates indefinitely. The exit condition is never satisfied because the cycle detector cannot register the traversal of the unidentifiable nodes.
The vulnerable implementation of get_message_list demonstrates the precise logical gap. Below is the vulnerable segment of code in backend/open_webui/utils/misc.py before the patch:
def get_message_list(messages_map, message_id):
current_message = messages_map.get(message_id)
message_list = []
visited_message_ids = set()
while current_message:
# Resolves ID from the mutable payload body
message_id = current_message.get('id')
if message_id in visited_message_ids:
# This block is bypassed if message_id is None
break
if message_id is not None:
visited_message_ids.add(message_id)
message_list.append(current_message)
parent_id = current_message.get('parentId')
# Resolves the next node key but does not bind it to cycle verification
current_message = messages_map.get(parent_id) if parent_id else None
message_list.reverse()
return message_listThe critical flaw is the reliance on current_message.get('id') for the membership check in visited_message_ids. If the JSON payload lacks the 'id' attribute, the function assigns None to message_id. The condition if message_id is not None: evaluates to false, and the set remains empty. When the loop advances to the next node, it executes the same logic. If two or more nodes are linked in a cycle and lack internal IDs, the loop runs endlessly.
The patch resolved this vulnerability by realigning the cycle tracking with the structural database keys rather than payload attributes. In the corrected code, the tracking is bound directly to the dictionary key message_id which must exist to query messages_map:
def get_message_list(messages_map, message_id):
current_message = messages_map.get(message_id)
message_list = []
visited_message_ids = set()
# Track the map keys, not the messages' own 'id' field: a message may omit it
while current_message and message_id not in visited_message_ids:
visited_message_ids.add(message_id)
message_list.append(current_message)
message_id = current_message.get('parentId')
current_message = messages_map.get(message_id) if message_id else None
message_list.reverse()
return message_listThis structural modification ensures that traversal logic is deterministic and bound by the number of unique message keys in the map, preventing cyclic bypass.
Exploitation of CVE-2026-88002 requires authenticated access to the target Open WebUI instance. An attacker must have the privileges necessary to create or modify chat sessions. The threat actor constructs a conversation history containing at least two message nodes that reference each other cyclicly.
The attacker prepares a JSON payload representing a chat history where the nested message maps are defined without internal 'id' fields. For instance, "node_1" contains "parentId": "node_2", and "node_2" contains "parentId": "node_1". The attacker then transmits this malformed structure via an API call, such as a POST or PUT request to /api/v1/chats/.
Once the database stores this payload, the vulnerability triggers when the server attempts to read or serialize the corresponding chat history. Because the API backend automatically loads this data to display the conversation, any subsequent attempt by any user or administrator to access the chat list or the specific chat thread will invoke the get_message_list utility, triggering the infinite loop.
The impact of this vulnerability is a complete Denial of Service (DoS) affecting the entire application instance. Open WebUI is built on Python's asyncio framework, which utilizes a single-threaded event loop to handle concurrent network requests. When the synchronous while loop in get_message_list enters an infinite cycle, it blocks the entire event loop, preventing the server from processing any other incoming connections.
In addition to the immediate thread block, the continuous execution of message_list.append(current_message) causes rapid, uncontrolled memory allocation. The memory usage of the backend server process will increase linearly until the host operating system or the container runtime terminates the process via an Out-of-Memory (OOM) killer.
Because the malicious cyclic payload is stored persistently in the backend database, the Denial of Service persists across application restarts. When the application service recovers and re-indexes or retrieves the active chat data, it encounters the malformed record and enters the infinite loop again. This persistent vulnerability holds a CVSS v3.1 score of 6.5, reflecting high availability impact with low complexity and low privilege requirements.
The primary remediation strategy is to upgrade the Open WebUI deployment to version 0.11.1 or later. This release incorporates the official patch that correctly binds cycle detection to lookup keys. For Docker-based environments, operators should pull the latest official container image from the GitHub Container Registry.
In legacy environments where an immediate system-wide upgrade is not feasible, operators can apply a hotpatch to the backend. This involves editing the backend/open_webui/utils/misc.py file manually and replacing the loop structure in get_message_list with the corrected implementation. The server process must be restarted after applying the file modification to load the updated module.
Administrators should also audit the database for stored malformed payloads. If an exploitation attempt has occurred, the affected database records must be manually purged or repaired to resolve the persistent infinite loop condition. Querying the chat tables for records containing cyclic parent-child links without defined internal IDs will identify the malicious entries.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
open-webui open-webui | >= 0.5.0, < 0.11.1 | 0.11.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-835 |
| Attack Vector | Network (AV:N) |
| Privileges Required | Low (PR:L) |
| User Interaction | None (UI:N) |
| Availability Impact | High (A:H) |
| Exploit Status | Proof of Concept |
| CISA KEV Status | Not Listed |
The program contains an iteration loop with an exit condition that cannot be reached or is never met, causing the loop to run indefinitely, consuming system resources.
Server-Side Request Forgery (SSRF) vulnerability in Open WebUI (v0.9.5 to v0.11.1) allows authenticated users to bypass private IP and host filter lists by abusing HTTP redirect handling or using IP literals with the aiohttp client.
An authenticated denial-of-service vulnerability exists in Open WebUI versions 0.10.0 up to 0.11.0. By uploading a malformed chat history containing cyclical child message references and requesting a message deletion, an attacker can trigger an infinite loop. Since Open WebUI relies on Python's single-threaded asyncio event loop, the CPU-bound loop blocks all incoming connections, freezing the service for all users.
A heap-based buffer overflow vulnerability (CVE-2026-71328) exists within the parser component of Microsoft Visual Studio and Microsoft .NET runtimes. This vulnerability permits an unauthenticated remote attacker to execute arbitrary code with the privileges of the running application, provided they can convince a user to load a maliciously crafted project file, solution, or stream.
CVE-2026-69439 is a high-severity elevation of privilege vulnerability in Microsoft .NET and Visual Studio, originating from a heap-based buffer overflow (CWE-122) within native parsing libraries. An unauthenticated attacker can achieve code execution under the privileges of the active process by convincing a user to open a specially crafted project, metadata stream, or dependency.
Prior to version 1.7.1, smol-toml is vulnerable to an infinite loop Denial of Service when parsing a malformed TOML payload containing an unclosed comment inside an array or inline table.
CVE-2026-69522 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET runtimes, .NET Framework, and Visual Studio caused by a heap-based buffer overflow (CWE-122). An unauthenticated attacker can exploit this flaw by inducing a user to open a malicious project file or by transmitting crafted payloads over the network, leading to arbitrary code execution within the context of the running application.