Files
wehub-resource-sync e30e75b5d4
Code Quality / Oxlint + Oxfmt (push) Waiting to run
Code Quality / Template Sync (push) Waiting to run
Code Quality / Build Changed Packages (push) Waiting to run
Code Quality / Test Changed Packages (push) Waiting to run
Deploy Expo Example / Deploy Production (push) Waiting to run
Deploy Ink Example / Deploy Production (push) Waiting to run
Python Tests / pytest (assistant-stream, 3.10) (push) Waiting to run
Python Tests / pytest (assistant-stream, 3.12) (push) Waiting to run
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Waiting to run
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Waiting to run
Deploy Shadcn Registry / Deploy Production (push) Waiting to run
Template Metrics / LOC + Bundle Size (push) Waiting to run
Changesets / Create Version PR (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00
..

safe-content-frame

npm version npm downloads bundle size GitHub stars

Render untrusted HTML, PDF, or arbitrary Blob content inside a sandboxed iframe whose origin is hashed per-content. The frame is hosted on scf.auiusercontent.com, a separate eTLD+1 from your app, so model-generated scripts cannot reach document.cookie, localStorage, or the parent window even if allow-scripts is set.

safe-content-frame is framework-agnostic vanilla JS. There is no React or DOM-framework dependency.

Installation

npm install safe-content-frame

Usage

import { SafeContentFrame } from "safe-content-frame";

const frame = new SafeContentFrame("my-app");

const container = document.getElementById("preview")!;
const rendered = await frame.renderHtml(modelGeneratedHtml, container);

await rendered.fullyLoadedPromiseWithTimeout(5000);

rendered.sendMessage({ type: "theme", value: "dark" });

// later
rendered.dispose();

The first argument to SafeContentFrame is your product identifier; it scopes the hashed origin so different products on the same domain do not collide.

Methods

Method Purpose
renderHtml(html, container, opts?) Render an HTML string.
renderRaw(content, mimeType, container) Render any MIME type from a string or Uint8Array.
renderPdf(content, container) Render a PDF document.

Each renderer returns a RenderedFrame:

Property/Method Description
iframe The created <iframe> element.
origin The hashed origin the frame was loaded from.
sendMessage(data, transfer?) postMessage to the frame, scoped to its origin.
fullyLoadedPromiseWithTimeout(ms) Resolves once the frame signals it is fully loaded; rejects on timeout.
dispose() Remove the iframe from the DOM.

Options

Option Default Effect
useShadowDom false Mount the iframe inside a closed shadow root.
enableBrowserCaching false Derive the salt from the content hash so repeated renders reuse the same origin and HTTP cache.
sandbox ["allow-same-origin", "allow-scripts"] Extra iframe[sandbox] permissions to grant. The two defaults are always added.
salt random per render Override the salt explicitly (useful for tests or stable-origin embeds).

Sub-paths

  • safe-content-frame: the main SafeContentFrame class above.
  • safe-content-frame/shadow_dom: shadow-DOM rendering variant for embedding inside a custom element.

See the docs page for the threat model and a live demo.