---
id: 2026-11-prefab-ui-generative-ui-sandbox-deno-permissions-host-file-write-cve-2026-120338-fixed-0-21-0
title: "Prefab UI 0.14.0 to 0.20.2: Generative UI sandbox ran Deno with full permissions, LLM code reads and writes server files (CVE-2026-120338, 10.0); fixed 0.21.0"
date_disclosed: 2026-11-01
last_updated: 2026-11-02
severity: critical
status: patched
ecosystems: [pypi, python, mcp, agent-framework, fastmcp]
tools_affected: ["prefab-ui (PyPI) 0.14.0 through 0.20.2", "FastMCP servers that use the GenerativeUI provider (fastmcp[apps], FastMCP 3.2.0 and later; FastMCP installs Deno on first use)", "any service that passes LLM-written or caller-supplied Python into Prefab's Generative UI sandbox"]
tags: [cve, prefab-ui, prefect, fastmcp, generative-ui, pyodide, deno, sandbox-escape, mcp-server, code-execution, silent-fix, jfrog, patched]
---

## TL;DR
Prefab UI 0.14.0 through 0.20.2 ran its Generative UI sandbox, a Deno subprocess hosting Pyodide, with unrestricted file and network permissions and left the Deno API reachable from the sandboxed Python, so any caller who could supply code read and wrote files as the server user and could persist code execution by writing a `.pth` file into the server's site-packages. CVE-2026-120338 (JFrog CNA) scores it 10.0 on an unauthenticated server and 9.9 on an authenticated one. The usual remote path is FastMCP's GenerativeUI provider, whose `generate_prefab_ui` tool forwards the LLM-written code into this sandbox, so an unauthenticated FastMCP server exposes it to anyone who can reach it. Upgrade `prefab-ui` to 0.21.0 or later (0.21.1 is newest on PyPI) and check site-packages for `.pth` files you did not create.

## What happened

Prefab is Prefect's Python UI framework for MCP apps. Its Generative UI feature runs caller-supplied Python inside Pyodide (Python compiled to WebAssembly) in a Deno subprocess, and the feature is documented as isolation for untrusted code, including UI code an LLM writes at runtime. JFrog Security Research (credit Yuval Moravchick) found that from 0.14.0 the launcher started Deno with `--allow-read`, `--allow-write` and `--allow-net` and the runner left the Deno API on the JavaScript global object. Pyodide's `js` module proxies that global, so the sandboxed Python could call `Deno.readTextFileSync` and `Deno.writeTextFileSync` directly. The CNA record says 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", and that the finding was confirmed on 0.20.2.

**The reachable path.** FastMCP's docs say "Generative UI needs `fastmcp[apps]`, which pulls in `prefab-ui`", that the server-side Pyodide sandbox "requires Deno — it installs automatically on first use", and that the feature is new in FastMCP 3.2.0. The provider registers the MCP tool `generate_prefab_ui`, and the CNA record says the tool's `code` argument is forwarded into this sandbox. Per the record: "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." The feature is opt-in and the host must have Deno installed, which the FastMCP provider does for you.

**Timeline, from the CNA record.** Sandbox added with the three `--allow-*` flags on 2026-03-24 (commit fc4362f3, pull request 334); `prefab-ui` 0.14.0 published 2026-03-27 as the first release with the sandbox; 0.20.2 published 2026-06-03; reported to PrefectHQ on 2026-08-05 as GHSA-595q-jv4r-q7j9; fix merged 2026-10-25 in pull request 538 (commit 030f074); 0.21.0 published 2026-10-26 "with the fix. No vendor advisory text was published with the release." The record was published at CVE Services on 2026-11-01 and the database row the same day.

**A silent fix.** The vendor advisory URL the record references, `github.com/PrefectHQ/prefab/security/advisories/GHSA-595q-jv4r-q7j9`, returned 404 when read on 2026-11-02, the shape of an unpublished draft. Pull request 538 is titled "Refresh dependencies and fix renderer and sandbox regressions"; its description talks about dependency refreshes and sandbox output corrupting later responses and does not mention permissions or security. The v0.21.0 release notes (26 Oct) list 35 pull requests, name 538 under dependencies and tooling, and carry no security wording beyond "Refresh vulnerable dependencies" (#510). A reader of the release page would not learn that 0.21.0 closes a sandbox escape. The CNA record is the only document that does.

**What 0.21.0 does, per the record.** 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 the jsDelivr CDN. The fix is on by default, which is why this file is `patched`.

**Scores.** The CNA record carries two CVSS 3.1 vectors: 10.0 `AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H` for the unauthenticated server and 9.9 with `PR:L` for the authenticated one. The GitHub Advisory Database page (GHSA-3g72-rrqc-f76c, unreviewed, "No package listed") prints 10.0. `severity: critical` follows the CNA.

**Registry facts (2026-11-02).** `pip index versions prefab-ui` lists 0.21.1 as newest; 0.14.0 (2026-03-27) through 0.20.2 (2026-06-03) are the affected releases on PyPI, and 0.21.0 and 0.21.1 both published on 2026-10-26. `fastmcp-slim` 4.0.0 (2026-08-31) and 4.1.5 (2026-11-01) declare `prefab-ui>=0.18.0; extra == "apps"`, so a fresh `pip install "fastmcp[apps]"` today resolves 0.21.1, while an environment installed before 2026-10-26 or pinned to a lower version keeps the affected sandbox.

## Am I affected?

```bash
pip show prefab-ui 2>/dev/null | grep -i ^version          # 0.14.0 through 0.20.2 is affected; 0.21.0 and later fixed
pip show fastmcp fastmcp-slim 2>/dev/null | grep -i ^version
grep -rn 'GenerativeUI\|fastmcp.apps.generative\|generate_prefab_ui' --include='*.py' . 2>/dev/null | head   # the provider in your server code
which deno 2>/dev/null                                      # the sandbox only runs where Deno is present
```

- Affected if `prefab-ui` is below 0.21.0 and the Generative UI sandbox was reachable, through FastMCP's GenerativeUI provider or your own call into it.
- An unauthenticated FastMCP server with the provider enabled was reachable by anyone who could connect to it; an authenticated one by any client allowed to call tools.
- Look for persistence the record describes: list `.pth` files in the server's site-packages and compare against what your packages install.

```bash
python -c 'import site,glob; [print(p) for d in site.getsitepackages() for p in glob.glob(d+"/*.pth")]'
```

## If you are affected

1. Upgrade: `pip install --upgrade "prefab-ui>=0.21.0"`, and redeploy; confirm with `pip show prefab-ui`.
2. Review every `.pth` file in site-packages and any file the server user could write; remove anything your dependencies did not install, or rebuild the environment from a lockfile.
3. If the sandbox was reachable without authentication, treat the host as compromised: rotate every credential the server process could read (environment variables, mounted secrets, cloud instance roles) with [rotating cloud credentials](../playbooks/rotating-cloud-credentials.md) and follow [if an MCP server was malicious](../playbooks/if-an-mcp-server-was-malicious.md) for the client side.

## Prevention

- Put authentication in front of every MCP server, and treat a tool that executes model-written code as a code-execution endpoint whatever its sandbox claims: [MCP hygiene](../prevention/mcp-hygiene.md), [agent sandboxing](../prevention/agent-sandboxing.md).
- A sandbox a framework installs for you is a dependency to read: check what permissions the runtime is started with before relying on it.

## Sources
- [CVE Services — CVE-2026-120338](https://cveawg.mitre.org/api/cve/CVE-2026-120338) — fetched 2026-11-02: CNA JFrog, published 2026-11-01 15:24 UTC, title "Prefab UI Pyodide sandbox escape to host RCE", affected `prefab-ui` 0.14.0 before 0.21.0 (semver), the two vectors (10.0 `PR:N`, 9.9 `PR:L`), CWE-693, CWE-94 and CWE-269, the full description and the six-entry timeline quoted above, credits Yuval Moravchick and JFrog Security Research.
- [GitHub Advisory Database — GHSA-3g72-rrqc-f76c](https://github.com/advisories/GHSA-3g72-rrqc-f76c) — fetched 2026-11-02: published 2026-11-01, unreviewed, "No package listed", CVSS 10.0, the same description and references. Surfaced as the top row of the [`mcp` recency listing](https://github.com/advisories?query=mcp+sort%3Apublished-desc) and the [`llm` listing](https://github.com/advisories?query=llm+sort%3Apublished-desc) on 2026-11-02; the [`prefab` package query](https://github.com/advisories?query=prefab+sort%3Apublished-desc) returns this row and one unrelated 2021 advisory.
- `github.com/PrefectHQ/prefab/security/advisories/GHSA-595q-jv4r-q7j9` — requested 2026-11-02: HTTP 404; the vendor advisory the record names is not published.
- [PrefectHQ/prefab — release v0.21.0](https://github.com/PrefectHQ/prefab/releases/tag/v0.21.0) — fetched 2026-11-02: dated 26 Oct, 35 pull requests, #538 listed under dependencies and tooling, "Refresh vulnerable dependencies" (#510) the only security-labelled line, no mention of the sandbox permissions.
- [PrefectHQ/prefab — pull request 538](https://github.com/PrefectHQ/prefab/pull/538) — fetched 2026-11-02: "Refresh dependencies and fix renderer and sandbox regressions", by jlowin, opened and merged 2026-10-25 as commit 030f074; description does not mention security or permissions.
- [FastMCP docs — Generative UI provider](https://gofastmcp.com/apps/providers/generative.md) — fetched 2026-11-02: "Generative UI needs `fastmcp[apps]`, which pulls in `prefab-ui`"; "The server-side Pyodide sandbox (for final validation) requires Deno — it installs automatically on first use"; "New in version 3.2.0"; `generate_prefab_ui` and `search_prefab_components` tools; no security note.
- PyPI `prefab-ui` release metadata and `pip index versions prefab-ui`, queried 2026-11-02: 0.14.0 2026-03-27, 0.20.2 2026-06-03, 0.21.0 2026-10-26 19:00 UTC, 0.21.1 2026-10-26 19:18 UTC, newest 0.21.1; author Jeremiah Lowin, repository PrefectHQ/prefab.
- PyPI `fastmcp-slim` 4.0.0 and 4.1.5 metadata, queried 2026-11-02: `prefab-ui>=0.18.0; extra == "apps"`; `fastmcp` 4.1.5 (2026-11-01) delegates every extra to `fastmcp-slim[...]==4.1.5`.
- Related in this corpus: [FastMCP October advisory batch (client RCE via server-supplied output schema)](2026-10-fastmcp-october-advisory-batch-client-rce-server-supplied-output-schema-ghsa-gpgx-58w2-xwwf.md), [Pyodide sandbox escape cluster (August 2026)](2026-08-pyodide-sandbox-escape-cluster.md).
