---
id: CVE-2026-120338
title: Prefab UI Pyodide sandbox escape to host RCE
summary: >-
  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.…
severity: critical
cvss: 10
cvssVector: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H'
cvssSource: cna
cwe:
  - CWE-693
  - CWE-94
  - CWE-269
vendor: PrefectHQ
product: prefab-ui
affected:
  - prefab-ui >= 0.14.0 < 0.21.0
ssvc:
  exploitation: none
  automatable: 'no'
  technicalImpact: total
  timestamp: '2026-11-02T19:42:39.981153Z'
published: '2026-11-01'
updated: '2026-11-02'
sourceUpdated: '2026-11-02T19:42:56.540Z'
source: CVEORG
sourceUrl: 'https://www.cve.org/CVERecord?id=CVE-2026-120338'
references:
  - url: 'https://github.com/PrefectHQ/prefab'
    label: Prefab repository
  - url: 'https://pypi.org/project/prefab-ui/'
    label: prefab-ui on PyPI
  - url: >-
      https://github.com/PrefectHQ/prefab/security/advisories/GHSA-595q-jv4r-q7j9
    label: GHSA-595q-jv4r-q7j9
  - url: 'https://github.com/PrefectHQ/prefab/pull/538'
    label: >-
      Refresh dependencies and fix renderer and sandbox regressions (fix pull
      request)
  - url: >-
      https://github.com/PrefectHQ/prefab/commit/030f074f85e0b1be0dd44b0283185aecb26337a2
    label: Fix commit 030f074
  - url: 'https://github.com/PrefectHQ/prefab/releases/tag/v0.21.0'
    label: v0.21.0
  - url: 'https://pypi.org/project/prefab-ui/0.21.0/'
    label: prefab-ui 0.21.0
  - url: 'https://github.com/PrefectHQ/prefab/releases/tag/v0.20.2'
    label: v0.20.2 (confirmed affected)
  - url: 'https://github.com/PrefectHQ/prefab/releases/tag/v0.14.0'
    label: v0.14.0 (first release with the sandbox)
tags:
  - cve.org
epss: 0.00771
epssPercentile: 0.55782
ingestedAt: '2026-11-05T19:30:42.807Z'
---

## Overview

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).

## Affected

- `prefab-ui >= 0.14.0 < 0.21.0`

## Remediation

Refer to the linked advisories for vendor-supplied fixes and affected version ranges.
