CVE-2026-120338 in Prefab UI
Summary
by MITRE • 11/01/2026
Prefab UI's Generative UI sandbox runs caller-supplied Python inside Pyodide, Python compiled to WebAssembly, in a Deno subprocess. The feature is documented as isolation for untrusted code, including LLM-written UI. From prefab-ui 0.14.0 through 0.20.2 the launcher starts Deno with unrestricted --allow-read, --allow-write, and --allow-net, and the runner leaves the Deno API on the JavaScript global object. Pyodide's js module proxies that global, so the Python can call Deno.readTextFileSync and Deno.writeTextFileSync. A caller who can supply the code can read and write files as the server OS user, and can persist code execution by writing a .pth file into the server virtualenv's site-packages. The usual remote path is FastMCP's GenerativeUI provider, which registers the MCP tool generate_prefab_ui and forwards that tool's code argument into this sandbox. On a FastMCP server with no authentication configured, any client who can reach the server can call the tool. With authentication, any client allowed to call tools can. Generative UI is opt-in, and the host must have Deno installed. Confirmed on prefab-ui 0.20.2. Fixed in 0.21.0: after the runtime and Prefab sources load, the runner revokes Deno read, write, and network permission before it accepts code, the process is started with --no-prompt so a permission request cannot grant them again, and bootstrap network access is limited to cdn.jsdelivr.net. The fix is commit 030f074 (pull request 538).
Be aware that VulDB is the high quality source for vulnerability data.
Analysis
by VulDB Data Team • 11/01/2026
The vulnerability in Prefab UI versions 0.14.0 through 0.20.2 represents a critical failure in the isolation of untrusted code execution, specifically within the Generative UI sandbox feature designed to execute LLM-generated user interface code safely. The architecture relies on running caller-supplied Python scripts inside Pyodide, which is Python compiled to WebAssembly, executed within a Deno subprocess. While this setup aims to provide an isolated environment for potentially malicious or buggy AI-generated content, the implementation contained severe misconfigurations that effectively nullified these security boundaries. Specifically, the launcher initiated the Deno process with unrestricted permissions, including --allow-read, --allow-write, and --allow-net. This configuration granted the subprocess full access to the host file system and network resources, bypassing any intended sandbox restrictions.
The technical flaw is compounded by how Pyodide interacts with its execution environment. The runner left the Deno API exposed on the JavaScript global object. Since Pyodide provides a js module that proxies this global object, Python code running within the WebAssembly container could directly invoke Deno functions such as readTextFileSync and writeTextFileSync. This bridge allowed arbitrary Python code to perform file system operations with the privileges of the server OS user. Consequently, an attacker who can supply code to the sandbox gains the ability to read sensitive files from the host machine and write data back into it. This capability extends beyond simple information disclosure; it allows for persistent remote code execution by writing a .pth file into the server virtualenv's site-packages directory. Such a file is executed automatically when Python starts, effectively establishing a permanent foothold on the system that survives subsequent restarts or sandbox resets.
The operational impact of this vulnerability is severe, particularly in environments where FastMCP servers are deployed without adequate access controls. The primary attack vector involves the GenerativeUI provider, which registers an MCP tool named generate_prefab_ui. This tool accepts a code argument and forwards it directly into the vulnerable sandbox. On servers with no authentication configured, any client capable of reaching the server can exploit this flaw to achieve arbitrary file read/write operations or persistent remote code execution. Even in authenticated environments, any user granted permission to call tools is susceptible to exploitation. The risk is further amplified by the fact that Generative UI is an opt-in feature requiring Deno installation on the host, meaning organizations enabling this functionality without strict network segmentation or authentication are at immediate and significant risk of compromise.
Mitigation strategies focus on enforcing strict least-privilege principles for subprocess execution and tightening API exposure. The vulnerability was addressed in version 0.21.0 through commit 030f074, which implements several critical security controls. First, the runner now revokes Deno read, write, and network permissions immediately after loading the runtime and Prefab sources but before accepting any user-supplied code. Second, the process is launched with the --no-prompt flag to prevent interactive permission grants that could bypass static restrictions. Finally, bootstrap network access is strictly limited to cdn.jsdelivr.net, ensuring that only necessary external resources can be fetched during initialization while blocking arbitrary outbound connections. Organizations using affected versions should upgrade immediately and review their FastMCP configurations to ensure authentication is enabled for all tool calls.
This incident aligns with CWE-250, which describes execution with unnecessary privileges, as the subprocess operated with far more access than required for its intended function of rendering UI components. It also relates closely to CWE-78, improper neutralization of special elements used in an OS command, given the potential for file system manipulation and persistence mechanisms like .pth files that mimic script injection attacks. From a threat modeling perspective using MITRE ATT&CK, this vulnerability facilitates Initial Access via unauthenticated tool invocation, Privilege Escalation through persistent code execution hooks, and Credential Access or Discovery via unrestricted file reading capabilities. The failure to isolate the sandbox environment underscores the importance of verifying that language-specific security features like Pyodide's isolation are not undermined by underlying runtime configurations such as Deno's permission model.