# Iframes use sandbox attribute

- **Pattern:** `ab-002444` (`security-headers-ii.cross-origin-isolation.iframe-sandbox`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002444
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002444)

## Why it matters

An iframe without a `sandbox` attribute inherits the full capabilities of the embedding page: it can run scripts, submit forms, navigate the top frame, and access storage. A compromised or malicious embedded resource (ads, widgets, user-generated embeds) can exploit unrestricted iframes to navigate your page to a phishing URL, submit forms on the user's behalf, or read cross-origin storage if the embed is same-site. CWE-1021 (Improper Restriction of Rendered UI Layers) applies directly. OWASP A05 identifies unsandboxed iframes as a configuration gap that gives embedded third-party content unwarranted trust.

## Severity rationale

Low because exploitation requires a compromised or malicious embed, but the `sandbox` attribute is a zero-cost capability restriction that eliminates the entire attack surface for misbehaving embeds.

## Remediation

Add the `sandbox` attribute to every `<iframe>` element. Start with no permissions and add only those the embed actually requires.

```tsx
{/* Video embed — needs scripts only */}
<iframe src="https://player.example.com/embed/123" sandbox="allow-scripts" />

{/* Interactive widget needing forms */}
<iframe src="https://widget.example.com" sandbox="allow-scripts allow-forms" />

{/* Same-origin embed needing full interaction */}
<iframe src="/embed/preview" sandbox="allow-scripts allow-same-origin allow-forms" />
```

Avoid `allow-same-origin` combined with `allow-scripts` for cross-origin iframes — that combination effectively defeats sandboxing by letting the embed escape via same-origin DOM access.

## Detection

- **ID:** `iframe-sandbox`
- **Severity:** `low`
- **What to look for:** Search all components and page files for `<iframe>` elements. For each, check whether the `sandbox` attribute is present with appropriate restrictions. The `sandbox` attribute restricts what the iframe can do — forms, scripts, popups, navigation, etc. Count all iframes found.
- **Pass criteria:** 100% of iframes have the `sandbox` attribute. Report: "X of Y iframes have sandbox attribute." Acceptable sandbox values allow only the minimum required permissions (e.g., `sandbox="allow-scripts allow-same-origin"` for interactive embeds).
- **Fail criteria:** Any iframe element lacks the `sandbox` attribute.
- **Skip (N/A) when:** No iframes found in any component.
- **Detail on fail:** `"X of Y iframes lack sandbox attribute — embedded content has full page capabilities"` or `"Iframe in EmbedPlayer component has no sandbox restrictions"`
- **Remediation:** The `sandbox` attribute restricts what embedded content can do. Start with no permissions and add only what is needed:

  ```tsx
  {/* Restrictive: only allow scripts */}
  <iframe src="..." sandbox="allow-scripts" />

  {/* For interactive embeds that need forms */}
  <iframe src="..." sandbox="allow-scripts allow-forms" />

  {/* For same-origin embeds needing full interaction */}
  <iframe src="..." sandbox="allow-scripts allow-same-origin allow-forms" />
  ```

  Never use an empty `sandbox=""` if the embed needs any functionality — it blocks everything including scripts.

---

## External references

- cwe CWE-1021
- owasp A05

Taxons: access-control

HTML version: https://auditbuffet.com/patterns/ab-002444
