The iframe sandbox attribute.
Isolate untrusted content.
An iframe without sandbox is as trusted as the page that hosts it. A malicious ad, a compromised widget, or an untrusted user's embedded HTML can run scripts, read cookies, redirect the parent page. The sandbox attribute blocks all of that by default — scripts, forms, popups, top navigation, same-origin access. You then re-enable only what the embed actually needs. This page covers the tokens, the danger of allow-scripts + allow-same-origin, and the patterns that scale.
Short answer: Add sandbox to every untrusted iframe. Start with no tokens (maximum restriction). Add only what the embed needs: allow-scripts for interactive widgets, allow-forms for form submissions, allow-popups for new tabs. Never combine allow-scripts with allow-same-origin for untrusted content — that defeats the sandbox entirely. Add title for accessibility. For user-submitted HTML, use srcdoc with sandbox — never set src to user-controlled URLs.
✅ What sandbox blocks by default
Everything. Then you re-enable.
Scripts
No <script>, no onclick, no JavaScript at all. Re-enable with allow-scripts.
Forms
Submissions blocked. Re-enable with allow-forms.
Top navigation
Iframe can't redirect the parent page. Re-enable with allow-top-navigation (dangerous).
Same-origin access
No cookies, no localStorage, no parent DOM access. Re-enable with allow-same-origin (dangerous with allow-scripts).
Popups
window.open, <a target="_blank"> blocked. Re-enable with allow-popups.
Modals
alert, confirm, prompt blocked. Re-enable with allow-modals.
Downloads
File downloads blocked. Re-enable with allow-downloads.
Presentation
Screen sharing, presentations blocked. Re-enable with allow-presentation.
✅ Before and after
The same embed, with and without sandbox.
<!-- Untrusted iframe — no sandbox --> <iframe src="https://untrusted-widget.com/embed"> </iframe>
❌ Iframe runs JavaScript freely. ❌ Iframe can submit forms → CSRF. ❌ Iframe can navigate the parent page (window.top.location = "..."). ❌ Iframe can open popups. ❌ If the iframe is same-origin (or attacker tricks you into it), it can read your cookies, localStorage, and DOM. This is the most common iframe security bug. An ad network or a compromised third-party widget can take over the whole page.
<!-- Sandboxed — script-only widget --> <iframe src="https://untrusted-widget.com/embed" sandbox="allow-scripts" title="Interactive chart"> </iframe> <!-- Fully locked — static embed --> <iframe src="https://untrusted-widget.com/embed" sandbox title="Embedded content"> </iframe> <!-- Interactive + forms (still no top nav) --> <iframe src="https://untrusted-widget.com/embed" sandbox="allow-scripts allow-forms" title="Feedback form"> </iframe>
✅ sandbox="allow-scripts"
→ JavaScript runs, but no forms, no popups,
no top nav, no same-origin access.
✅ sandbox (no tokens)
→ Maximum restriction. Static content only.
✅ sandbox="allow-scripts allow-forms"
→ JS runs, forms submit. Still no top nav,
still no same-origin.
⚠️ title is required for accessibility.
Screen readers announce "frame, {title}".
Without it: "frame" with no name.
✅ The dangerous combination
allow-scripts + allow-same-origin = no sandbox.
<!-- ❌ Dangerous: defeats the sandbox --> <iframe src="https://untrusted-widget.com/embed" sandbox="allow-scripts allow-same-origin"> </iframe> <!-- ✅ Safe: JS runs, but iframe is opaque-origin --> <iframe src="https://untrusted-widget.com/embed" sandbox="allow-scripts"> </iframe>
allow-same-origin tells the browser: "treat this iframe as if it were same-origin (or its real origin), not as an opaque sandbox." allow-scripts then lets that same-origin iframe run JavaScript. Result: ❌ Iframe can read parent cookies (if same origin). ❌ Iframe can read parent localStorage. ❌ Iframe can access parent DOM if same origin. ❌ Iframe can remove the sandbox attribute from itself. ❌ The sandbox is gone. Rule: for untrusted content, pick ONE: allow-scripts (run JS, no domain access) OR allow-same-origin (access domain, no JS) Never both, unless the content is fully trusted.
Don't combine allow-scripts with allow-same-origin for untrusted content. MDN warns about this explicitly. Together they give the iframe both script execution and same-origin access — which is exactly what the sandbox is meant to prevent. The iframe can read your cookies, script against your DOM, and remove its own sandbox attribute. For content from a third party (ads, widgets, user-submitted embeds), pick one: scripts without origin access, or origin access without scripts. Never both. For first-party content you fully control, the combination is fine — but the content isn't untrusted anymore.
⚠️ Common mistakes
The iframe-sandbox mistakes that cost real time.
The iframe runs scripts freely, can redirect parent, read data. Fix: add sandbox.
allow-scripts + allow-same-origin for untrusted contentDefeats the sandbox. Fix: pick one. allow-scripts alone is usually right.
Same as no sandbox. Fix: add tokens as needed, one at a time.
title on iframeScreen readers say "frame" with no name. Fix: title="Description of the content".
srcdoc with allow-same-originsrcdoc content inherits the parent origin — dangerous. Fix: omit allow-same-origin.
A trusted vendor can be compromised. Fix: sandbox anyway. Defense-in-depth.
allow-forms for form embedsForms don't submit — the embed appears broken. Fix: add the token.
allow-popups for payment widgetsPayment flows that open new windows fail. Fix: add allow-popups.
❓ Frequently asked
What does the iframe sandbox attribute do?
The sandbox attribute on an iframe puts the embedded content in a restricted context. By default, sandbox blocks: script execution, form submission, top-level navigation, popups, plugins, pointer lock, downloads, and access to same-origin resources (cookies, localStorage, parent DOM). It's the most powerful security tool for embedding untrusted content. Without sandbox, an iframe can run scripts, redirect the user, and read data from the parent page. With sandbox, the iframe is isolated.
Is an iframe without sandbox dangerous?
Yes, for untrusted content. A same-origin iframe can read cookies, access localStorage, modify the parent DOM, and redirect the top-level page. It's as trusted as the page that hosts it. Even cross-origin iframes (which can't read parent data due to same-origin policy) can still navigate the top-level page, open popups, and play audio. That's why a malicious ad or a compromised third-party widget can take over a page. Always add sandbox to untrusted iframes.
What are the sandbox allow tokens?
The most common tokens: allow-scripts (run JavaScript), allow-forms (submit forms), allow-same-origin (access cookies and same-origin storage — dangerous when combined with allow-scripts), allow-popups (open popups and new tabs), allow-top-navigation (navigate the parent page — dangerous), allow-modals (alert, confirm, prompt), allow-downloads (download files), allow-presentation (start screen sharing), allow-pointer-lock (control the mouse pointer). Add tokens as needed — never add all of them.
Why is allow-scripts plus allow-same-origin dangerous?
Because it defeats the sandbox. allow-same-origin gives the iframe access to cookies, localStorage, and the parent's DOM (if same origin). allow-scripts lets it run JavaScript. Together, the iframe can script against the parent — remove elements, read form values, exfiltrate cookies. It's no longer sandboxed. The MDN docs warn explicitly: combining these two removes the security boundary. If you need both, the content must be fully trusted — treat it like your own code.
Does sandbox affect performance?
No meaningful impact. Sandbox is a browser security boundary, not a rendering layer. The iframe loads the same way — same network requests, same JavaScript engine, same DOM. The cost is small: the browser skips some optimizations that rely on same-origin trust (like shared memory between the iframe and parent), but the difference is measured in microseconds. Never omit sandbox for performance reasons.
Can I sandbox my own content?
Yes, and you should. Even first-party content benefits from sandbox as defense-in-depth. If your own iframe is compromised via XSS, sandbox limits the damage — the attacker can't read cookies, can't access the parent DOM, can't redirect the user. The cost is trivial; the benefit is real. Use sandbox with the tokens your content needs: usually allow-scripts, allow-forms, allow-same-origin for trusted first-party widgets.