nexu-io/open-design · error · Error
iframe elements are not supported in live artifact previews
Error message
iframe elements are not supported in live artifact previews
What it means
Thrown by validateHtmlTemplateV1Security when the template matches /<\s*iframe\b/i. iframes are blocked because live artifact previews are rendered into a controlled host document; embedded frames could break out of the intended content boundary, load untrusted origins, or be used for clickjacking/SSRF via src URLs. The preview surface stays frame-free.
Source
Thrown at apps/daemon/src/live-artifacts/render.ts:34
const TEMPLATE_INTERPOLATION = /{{\s*([^{}]+?)\s*}}/g;
const RAW_TEMPLATE_INTERPOLATION = /{{{[^{}]*}}}|{{\s*&[^{}]*}}/;
const TEMPLATE_PATH = /^(?:data|[A-Za-z_][A-Za-z0-9_]*)(?:\.(?:[A-Za-z_][A-Za-z0-9_-]*|\d+))*$/;
// `data-od-repeat="item in data.items"` — one loop variable over one `data.*` array.
const REPEAT_DIRECTIVE = /\s*\bdata-od-repeat\s*=\s*"([^"]*)"/i;
const REPEAT_DIRECTIVE_SPEC = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s+in\s+(data(?:\.(?:[A-Za-z_][A-Za-z0-9_-]*|\d+))*)\s*$/;
const EXECUTABLE_TEMPLATE_PATTERNS: Array<{ pattern: RegExp; message: string }> = [
{ pattern: /<\s*script\b/i, message: 'script elements are not supported in live artifact previews' },
{ pattern: /<\s*iframe\b/i, message: 'iframe elements are not supported in live artifact previews' },
{ pattern: /\bsrcdoc\s*=/i, message: 'srcdoc attributes are not supported in live artifact previews' },
{ pattern: /\son[a-z][a-z0-9_-]*\s*=/i, message: 'event handler attributes are not supported in live artifact previews' },
{ pattern: /(?:href|src|action|formaction)\s*=\s*['"]?\s*javascript\s*:/i, message: 'javascript: URLs are not supported in live artifact previews' },
{ pattern: /\bdata-od-(?:html|raw|bind-html)\b/i, message: 'raw HTML insertion directives are not supported' },
];
export function validateHtmlTemplateV1Security(templateHtml: string): void {
for (const { pattern, message } of EXECUTABLE_TEMPLATE_PATTERNS) {
if (pattern.test(templateHtml)) throw new Error(message);
}
}
export function escapeHtmlTemplateValue(value: unknown): string {
return String(value)
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", ''');
}
/**
* A binding resolver for one scope. Given a trimmed binding path (e.g.
* `data.title` or a loop variable path like `item.label`) it returns the
* already-escaped scalar string to substitute, or throws for an unsupported
* path. Loop scopes delegate non-matching heads (including `data.*`) to their
* parent so global bindings keep working inside a repeat.View on GitHub (pinned to 5be4028344)
Solutions
- Replace the iframe with native HTML rendering of the data (e.g. show a thumbnail image linked to the external URL, do not embed it).
- If the goal is to display external content, surface it as data (a link, an image) rather than a nested browsing context.
- Request a first-party embed directive if you genuinely need framed content; do not bypass.
Example fix
// before
<template><iframe src='{{data.url}}'></iframe></template>
// after
<template><a href='{{data.url}}'>Open</a></template> Defensive patterns
Strategy: validation
Validate before calling
function assertNoIframe(html: string): void {
if (/<\s*iframe\b/i.test(html)) throw new Error('iframe tags not allowed');
} Type guard
function isIframeFree(html: string): boolean {
return !/<\s*iframe\b/i.test(html);
} Try / catch
try { validateHtmlTemplateV1Security(tpl); } catch (e) { /* reject template */ throw e; } Prevention
- Render external content as data (links/images), not as nested frames.
- Run the validator in CI on committed templates.
- Educate template authors that live artifacts are frame-free.
When it happens
Trigger: Template contains <iframe src='https://...'></iframe>, <iframe srcdoc=...>, <IFRAME>, or any opening iframe tag with leading whitespace.
Common situations: Model embeds a YouTube/CodePen iframe for rich preview; developer pastes an embed snippet; intent to show another live artifact inside this one; misunderstanding the sandbox model.
Related errors
- script elements are not supported in live artifact previews
- raw template interpolation is not supported
- srcdoc attributes are not supported in live artifact preview
- event handler attributes are not supported in live artifact
- javascript: URLs are not supported in live artifact previews
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/fed2138e89697de6.
Report an issue: GitHub.