ESC

Type to search the knowledge base.

iframe Sandbox and Security

Embed third-party content safely — sandbox tokens, allow attributes, CSP frame-src, and postMessage boundaries.

advanced3 min read
  • html
  • iframe
  • security
  • sandbox

<iframe> embeds another browsing context. That is power and risk: the framed page can be a trusted payment widget or a hostile script host. sandbox, allow, and CSP frame-src are how you shrink the blast radius.

Docs: MDN <iframe>, sandbox, CSP frame-src.

Default risks

Without restrictions, a framed document may:

  • Run scripts
  • Submit forms
  • Navigate top-level page (depending on conditions)
  • Access storage for its origin
  • Open popups

Same-origin iframes can be scripted by the parent; cross-origin ones cannot access the parent DOM (SOP), but still participate in clickjacking and UI redress unless mitigated.

sandbox attribute

<iframe
  title="Calendar embed"
  src="https://calendar.example.com/embed/abc"
  sandbox="allow-scripts allow-same-origin allow-popups"
></iframe>

Empty sandbox applies maximum restrictions (no scripts, no forms, unique opaque origin, etc.).

Token Allows
allow-scripts JavaScript
allow-same-origin Treat as real origin (storage, etc.)
allow-forms Form submission
allow-popups window.open
allow-popups-to-escape-sandbox Opened windows not sandboxed
allow-top-navigation Navigate top browsing context
allow-top-navigation-by-user-activation Safer top nav
allow-downloads Downloads
allow-modals alert/confirm

Dangerous combo: allow-scripts + allow-same-origin on untrusted content can let the frame remove sandboxing via script in some historical scenarios — treat untrusted + both flags as high risk. Prefer minimal tokens.

Permissions policy via allow

<iframe
  title="YouTube video"
  src="https://www.youtube-nocookie.com/embed/VIDEO_ID"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen
  loading="lazy"
  referrerpolicy="strict-origin-when-cross-origin"
></iframe>

allow gates features (camera, mic, payment, etc.) even when scripts run.

Always title iframes

<iframe title="Payment form" src="…"></iframe>

Screen readers announce iframes; empty titles fail a11y checks.

postMessage boundary

// parent
iframe.contentWindow.postMessage({ type: "INIT" }, "https://widget.example.com");

window.addEventListener("message", (event) => {
  if (event.origin !== "https://widget.example.com") return;
  // handle event.data
});

Validate origin and message shape. Never trust event.data blindly.

CSP and cookies

Content-Security-Policy: frame-src https://widget.example.com; frame-ancestors 'self'
  • frame-src — who you may embed
  • frame-ancestors — who may embed you (clickjacking defense; also X-Frame-Options)

Interview out-loud

“Iframes embed separate documents. I set a descriptive title, use sandbox with least privilege, gate features with allow, restrict sources via CSP frame-src, and only accept postMessage from expected origins. allow-scripts combined with allow-same-origin on untrusted content is a red flag.”

Footguns

  1. Sandbox-free third-party embeds.
  2. Missing iframe titles.
  3. Trusting postMessage without origin checks.
  4. Using iframes for seamless same-app routing when components would do.
  5. Clickjacking your own authenticated UI without frame-ancestors.

Least-privilege embeds

<!-- Static map preview: no scripts needed -->
<iframe
  title="Office location map"
  src="https://maps.example.com/static-embed/…"
  sandbox=""
  loading="lazy"
  referrerpolicy="no-referrer"
></iframe>

Start from empty sandbox and add tokens only when the embed breaks for a documented reason. Log those reasons in code comments so future you does not “fix” it by removing sandbox entirely.

Clickjacking your own app

If your authenticated UI can be framed by an attacker origin, users may be tricked into clicking “Delete” under a fake overlay. Set Content-Security-Policy: frame-ancestors 'self' (or a strict allowlist) and consider X-Frame-Options for legacy. Combine with cookie SameSite practices. Sandbox protects embeds you host; frame-ancestors protects you from being embedded.

Further reading

Related guides