nexu-io/open-design · error · Error
raw HTML insertion directives are not supported
Error message
raw HTML insertion directives are not supported
What it means
Thrown by validateHtmlTemplateV1Security when the template contains a data-od-html, data-od-raw, or data-od-bind-html attribute (regex /\bdata-od-(?:html|raw|bind-html)\b/i). These would be raw-HTML insertion directives that bypass HTML escaping; the render pipeline supports only escaped interpolation ({{...}}) and explicit safe directives, so any raw-insertion directive is rejected up front to keep the model from injecting unescaped markup.
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
- Use plain {{data.field}} interpolation; values are HTML-escaped automatically.
- If the data genuinely contains HTML that must be rendered as markup, that is not supported by html_template_v1 — pre-render or strip tags before feeding the data.
Example fix
// before
<template><div data-od-html="{{data.body}}"></div></template>
// after
<template><div>{{data.body}}</div></template> Defensive patterns
Strategy: validation
Validate before calling
function assertNoRawHtmlDirective(html: string): void {
if (/\bdata-od-(?:html|raw|bind-html)\b/i.test(html)) {
throw new Error('raw-HTML directives are not supported');
}
} Type guard
function isRawDirectiveFree(html: string): boolean {
return !/\bdata-od-(?:html|raw|bind-html)\b/i.test(html);
} Try / catch
try { validateHtmlTemplateV1Security(tpl); } catch (e) { throw e; } Prevention
- Remember there is no opt-out from HTML escaping in html_template_v1.
- If you need to render HTML, pre-process the data before storing in data.json.
- Document the directive vocabulary so authors do not invent v-html-style directives.
When it happens
Trigger: <div data-od-html="{{data.body}}">, <span data-od-raw="{{data.html}}">, <p data-od-bind-html="...">; appears in any case or with extra whitespace before the =.
Common situations: Model assumes a Vue/Angular-style v-html / ng-bind-html directive exists; developer expects to render markdown HTML output; misunderstanding that all {{...}} interpolation is already escaped and there is no opt-out.
Related errors
- script elements are not supported in live artifact previews
- iframe elements are not supported in live artifact previews
- 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/4b82d657f032aadf.
Report an issue: GitHub.