Problem Solved

HTML · iframe sandbox

Home › Courses › HTML › Problems › iframe sandbox
📄 Concept · 4 min read

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.

unsafe-iframe.html
<!-- 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.
safe-iframe.html
<!-- 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-combo.html
<!-- ❌ 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.

1. No sandbox on third-party iframes

The iframe runs scripts freely, can redirect parent, read data. Fix: add sandbox.

2. allow-scripts + allow-same-origin for untrusted content

Defeats the sandbox. Fix: pick one. allow-scripts alone is usually right.

3. Adding all tokens "just in case"

Same as no sandbox. Fix: add tokens as needed, one at a time.

4. Missing title on iframe

Screen readers say "frame" with no name. Fix: title="Description of the content".

5. Using srcdoc with allow-same-origin

srcdoc content inherits the parent origin — dangerous. Fix: omit allow-same-origin.

6. Trusting the domain name

A trusted vendor can be compromised. Fix: sandbox anyway. Defense-in-depth.

7. Forgetting allow-forms for form embeds

Forms don't submit — the embed appears broken. Fix: add the token.

8. Forgetting allow-popups for payment widgets

Payment 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.

🔗 Related

← All HTML problems
Problem solved · HTML