Join our Newsletter — 33% off our NHI Course
Home› Guides› Iframe Sandboxing and srcdoc Security Guide: Isolate untrusted…
Guide Web & API Security

Iframe Sandboxing and srcdoc Security Guide: Isolate untrusted and AI-generated content safely

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 28 October 2026 13 min read
On this page

An iframe is only an isolation boundary if its origin and its sandbox flags make it one, and a srcdoc frame without a sandbox runs with the full privileges of the page that embeds it. Developers reach for srcdoc to render HTML they did not write: user-submitted markup, email bodies, rich previews, third-party widgets and, increasingly, HTML, SVG and scripts produced by large language models. If you have seen about:srcdoc in a browser address bar, error report or analytics feed, that is the URL every srcdoc document carries. This guide explains what the sandbox attribute restricts, how srcdoc documents get their origin, which token combinations quietly undo the protection, how to choose between a sandboxed srcdoc frame, a separate sandbox domain and a CSP sandbox header, and how to render AI output without opening an exfiltration channel. It is written for front-end engineers, application security teams and anyone shipping a product that displays generated content. Cross-window messaging is covered in the postMessage Security Guide; this page covers the frame itself.

Key takeaways

  • An empty sandbox attribute applies every restriction. Each allow- token lifts one; start empty and add only what the content demonstrably needs.
  • Never combine allow-scripts and allow-same-origin for same-origin content. The WHATWG HTML standard and MDN both warn that the embedded document can then remove its own sandbox attribute, leaving no protection at all.
  • srcdoc content is same-origin unless sandboxed. Without the sandbox attribute (or with allow-same-origin), script in a srcdoc frame can read the parent's DOM, cookies and storage.
  • Sandboxing does not stop data leaving. A sandboxed frame can still load images and make requests unless a Content Security Policy restricts it, which is exactly how rendered AI output becomes an exfiltration path.
  • The strongest pattern is a separate origin. For hostile content, the standard advises serving it from a dedicated domain, so that even a user opening it directly cannot reach your application's origin.

What the sandbox attribute restricts

MDN describes the sandbox value as either empty, to apply all restrictions, or a space-separated list of tokens that lift particular restrictions. A sandboxed frame without allow-same-origin is treated as coming from an opaque origin: MDN states that such a resource always fails same-origin checks and its Origin is null, so it cannot read document.cookie or localStorage. Without allow-scripts, no script runs; without allow-forms, forms render but do not submit; without allow-popups, window.open and target="_blank" fail silently.

TokenWhat it liftsRisk when granted to untrusted content
allow-scriptsScript execution (not popups)Moderate on its own; the frame can still make network requests and post messages
allow-same-originKeeps the real origin instead of an opaque oneHigh: gives access to that origin's cookies and storage; with allow-scripts on same-origin content, a full escape
allow-formsForm submissionPhishing forms that post credentials to an attacker
allow-popupswindow.open and target="_blank"Opening attacker pages; popups inherit the sandbox unless the next token is set
allow-popups-to-escape-sandboxPopups open without the sandbox flagsIntended for ads that link out; never for untrusted script
allow-top-navigationNavigating the top-level pageHigh: redirect the whole tab to a phishing page
allow-top-navigation-by-user-activationTop navigation only after a user gestureLower, but still a click-to-phish path
allow-top-navigation-to-custom-protocolsNavigation to non-http protocolsLaunching registered protocol handlers
allow-modalsalert, confirm, print and promptSpoofed dialogs; denial of service
allow-downloadsDownloads through download links or navigationDrive-by delivery of files that look like they came from you
allow-storage-access-by-user-activationStorage Access API request for unpartitioned cookiesCross-site cookie access after a gesture
allow-pointer-lock, allow-orientation-lock, allow-presentationThe named APIsLow; grant only when needed

Two other iframe attributes complete the picture. The allow attribute sets a Permissions Policy for the frame (camera, microphone, geolocation and others); MDN notes it further restricts the Permissions-Policy header and does not replace it. The referrerpolicy attribute controls what URL the frame's requests reveal; use no-referrer for untrusted content so the parent's path and query string are not leaked. The credentialless attribute loads the frame in a new, ephemeral context without the cookies and storage of its origin, which is useful for third-party embeds under Cross-Origin-Embedder-Policy.

srcdoc and about:srcdoc explained

  • What it is: the srcdoc attribute holds the full HTML of the frame's document inline. The HTML standard defines about:srcdoc as a reserved, unresolvable URL used as the URL of every srcdoc document, which is why it appears in address bars, console messages, CSP reports and error trackers.
  • Precedence: if both src and srcdoc are present, srcdoc wins. Leaving a src fallback does not make an unsafe srcdoc safe.
  • Base URL: MDN states that about:srcdoc uses the embedding document's URL as its base URL when resolving relative links, so relative URLs in generated HTML point at your own site.
  • Origin: an unsandboxed srcdoc document runs with the embedding page's origin. Add sandbox without allow-same-origin and it gets an opaque, null origin instead. This single attribute decides whether the frame is isolated.
  • Escaping: srcdoc is an attribute, so the content must be attribute-escaped. The standard says to escape every ampersand and quotation mark, ampersands first, so that a quotation mark becomes " and not ". Setting the property from script (frame.srcdoc = html) avoids hand-escaping, but the HTML itself is still untrusted.
  • CSP inheritance: a srcdoc document inherits the embedding page's Content Security Policy in current browsers, and you can tighten it further with a CSP meta element inside the srcdoc. A policy can only add restrictions, never remove inherited ones.
  • Trusted Types: where Trusted Types are enforced, assignments to srcdoc are an injection sink and must go through a policy. See the Trusted Types and DOM XSS Prevention Guide.

Choosing an isolation pattern

PatternHow it isolatesBest forTrade-offs
srcdoc with empty sandboxOpaque origin, no scripts, no formsDisplaying static HTML such as emails or sanitised rich textNo interactivity; auto-height needs a parent-side approach
srcdoc with sandbox="allow-scripts"Opaque origin, scripts runLive previews, generated mini-apps, code playgroundsFrame can still make network requests and post messages; needs a strict CSP
Separate sandbox domain (for example a registrable domain used only for user content) plus sandbox attributeDifferent site and opaque originHostile or user-uploaded content, AI artifacts that run codeInfrastructure and a second domain; the standard's recommendation for potentially hostile files
CSP sandbox response headerSandboxes the document even when opened directly in a tabUser-uploaded HTML or SVG served from your own serversMDN states it is ignored in meta and in report-only mode; header only
Content-Disposition: attachmentBrowser downloads rather than rendersFiles users upload but should not view inlineNo in-page preview
Sanitise and render in the main DOMNo isolation; relies on the sanitiserSimple formatted textAny sanitiser bypass is XSS in your origin

Decision guidance: if the content never needs script, use an empty sandbox and sanitise anyway. If it needs script and comes from users or a model, isolate it on a separate domain and sandbox it, because a sandboxed frame on your own origin is one misconfigured token away from an escape. Small teams without the capacity to run a second domain should use srcdoc with sandbox="allow-scripts" only, a strict inherited CSP and no allow-same-origin under any circumstance. Large platforms that render content from many tenants should use per-tenant or per-render subdomains so one tenant's content cannot share an origin with another's.

Rendering AI-generated content in iframes

Chat interfaces, coding assistants and agent consoles now render model output as HTML, SVG, Markdown with images, and runnable mini-applications. OWASP's Top 10 for LLM Applications 2025 lists this as LLM05 Improper Output Handling: model output must be treated like any other untrusted input. Prompt injection means the content may have been written by whoever controlled a document, email or web page the model read. See the OWASP LLM Top 10 LLM05 Improper Output Handling Guide.

  • Isolate execution: run generated code only in a frame with sandbox="allow-scripts" and without allow-same-origin, preferably on a separate domain.
  • Close the network: the sandbox does not stop requests. Give the frame a CSP with default-src 'none' and only the script and style sources it needs, and keep img-src and connect-src as narrow as possible. In the EchoLeak Microsoft 365 Copilot vulnerability, an image reference in a rendered answer carried sensitive data out, routed through Microsoft domains that the page's CSP trusted, with no user action needed.
  • Do not trust allow-listed domains blindly: any domain that can redirect, proxy or preview URLs can carry data onwards. Prefer no external loads at all for generated content.
  • Keep the bridge narrow: if the parent and frame must talk, define a small message schema, check event.source against the frame's contentWindow (the origin will be null) and never pass tokens or session data into the frame. The postMessage Security Guide covers the listener rules.
  • Block navigation and forms: omit allow-top-navigation, allow-popups and allow-forms so generated content cannot redirect the user or harvest credentials.
  • Keep secrets out: never inject API keys, OAuth tokens or agent credentials into generated HTML for convenience. A frame that can run script can read anything placed in it.

Headers that work with the frame

ControlSet onPurpose
Content-Security-Policy: frame-ancestorsYour pagesDecides who may embed you; does not fall back to default-src, and MDN states it is not supported in meta. OWASP ASVS 5.0 V3.4.6 requires it on every response
Content-Security-Policy: frame-src (or child-src)The embedding pageDecides which origins your page may frame
Content-Security-Policy: sandboxUntrusted documents you serveSandboxes the document even when opened directly; ASVS 5.0 V3.2.1 lists it as a control against rendering content in the wrong context
Permissions-Policy and the allow attributeEmbedding page and iframeDenies powerful features to the frame
Referrer-Policy and referrerpolicyEmbedding page and iframeStops URLs with tokens or identifiers leaking to the frame
Cross-Origin-Opener-PolicyYour pagesSeparates your window from popups the frame might open

Framing your own pages by attackers is a separate threat (clickjacking, CAPEC-103). See the Clickjacking Guide and the Content Security Policy Guide.

How to implement

  1. Inventory frames. Search the codebase for iframe, srcdoc, sandbox and frame.srcdoc assignments, and list where each frame's content comes from (static, user, third party, model).
  2. Classify content trust. Anything from users, tenants, third parties or models is untrusted. Static first-party content can be framed without a sandbox.
  3. Set the strictest sandbox that works. Start every untrusted frame with an empty sandbox attribute, then add tokens one at a time with a written reason. Reject allow-same-origin with allow-scripts in code review.
  4. Add CSP for the frame. Rely on the inherited policy for srcdoc, add a stricter meta policy inside it, or serve the frame from a sandbox domain with its own header policy.
  5. Test in report-only first. Deploy the parent's CSP changes as Content-Security-Policy-Report-Only and collect violation reports (about:srcdoc in a report tells you which frame) before enforcing. Remember the CSP sandbox directive itself has no report-only mode.
  6. Pilot and roll back. Ship to an internal ring, watch errors and support tickets, then expand. Roll back by reverting the sandbox token change, not by removing the sandbox.
  7. Add tests. Write automated checks that assert sandbox values on every iframe and that the frame cannot read the parent's cookies.

Detection and measurement

  • CSP violation reports: collect them centrally; blocked img-src or connect-src from a frame rendering generated content may indicate an exfiltration attempt.
  • Static analysis: lint rules for iframe elements missing sandbox, and for the allow-scripts plus allow-same-origin pair.
  • Egress monitoring: watch for long encoded query strings on image and fetch requests initiated from sandbox domains.

Metrics: percentage of untrusted-content frames with a sandbox attribute; number of frames granted allow-same-origin; number granted allow-top-navigation or allow-popups-to-escape-sandbox; share of generated-content frames served from a separate domain; CSP violations per thousand renders from content frames; time to remediate a lint finding.

Common failure patterns

  • The self-removing sandbox: sandbox="allow-scripts allow-same-origin" on same-origin or srcdoc content, added to make a library work. The frame removes its own sandbox and runs as your origin.
  • srcdoc without sandbox: developers assume srcdoc isolates content because it is "in a frame". It does not; it runs as the parent's origin.
  • Sandbox without CSP: script is blocked, but images and links still reach external servers, so generated content can leak data in URLs, as the EchoLeak case showed.
  • Escaping by hand: building srcdoc strings in server templates with incomplete attribute escaping, which lets content break out of the attribute into the parent page.
  • Hostile files on the main domain: user-uploaded HTML or SVG is sandboxed when framed but served from your origin, so a direct link opens it unsandboxed. Serve it from a separate domain or with a CSP sandbox header.
  • Wildcard messaging: a parent that accepts any message because the frame's origin is null, without checking event.source and the message schema.

Lessons from incidents

The EchoLeak case is the clearest public example of rendered AI output acting as a data channel. Link filtering removed ordinary Markdown links, but reference-style images got through, and the browser fetched them automatically through domains the CSP trusted. The lessons carry directly to iframe-rendered content: filter at the rendering layer, not only in the model's output; treat any allow-listed domain that redirects or previews URLs as an exit; and make the default for generated content no external loads at all.

Framework mapping

FrameworkReferenceRelevance
OWASP ASVS 5.0V3.2.1, V3.4.3, V3.4.6, V3.5.5, V15.2.5Content rendered in the wrong context, CSP, frame-ancestors, postMessage validation, sandboxing dangerous functionality
OWASP Top 10 for LLM Applications 2025LLM05 Improper Output HandlingTreat model output as untrusted before rendering
NIST SP 800-53 Rev. 5SC-18, SC-39, SI-10Mobile code, process isolation, input validation
NIST CSF 2.0PR.PS-06Secure development practices
MITRE CAPECCAPEC-103 ClickjackingThe framing threat in the other direction

Where identity fits

Frames often sit next to sessions and tokens. A srcdoc frame with your origin can read session cookies that are not HttpOnly, tokens in localStorage and anything in the parent DOM. Keep access tokens and agent credentials out of any page area that renders untrusted content, and do not pass them through postMessage to content frames. See the OAuth for Browser-Based Applications and the BFF Pattern Guide for keeping tokens out of the browser.

Practitioner checklist

  • Inventory every iframe and srcdoc use and classify its content source.
  • Give every untrusted frame a sandbox attribute, starting empty.
  • Block allow-scripts with allow-same-origin in code review and lint rules.
  • Serve hostile or user-uploaded content from a separate domain or with a CSP sandbox header.
  • Restrict network access from content frames with CSP, especially img-src and connect-src.
  • Use no-referrer and a restrictive allow attribute on content frames.
  • Validate event.source and schema on every message from a sandboxed frame.
  • Route srcdoc assignments through Trusted Types where enforced.
  • Collect CSP reports and track sandbox coverage metrics.

Standards and references

Related NHI Mgmt Group resources: postMessage Security Guide · Content Security Policy Guide · Cross-Site Scripting (XSS) Prevention Guide · OWASP LLM Top 10 LLM05 Improper Output Handling Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 28 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.