FSD Frontend System Design

Part II β€” The Shield Β· Lesson 3.3

iFrame Protection

In one lineTwo problems: who may frame you, and what the frames you embed are allowed to do.

Where you've seen itAny "You've won!" page. The visible button is bait; your real, invisible account page sits directly under the cursor.

  • Time14 min
  • DiagramClickjacking overlay, side view
  • Chapter3 Β· Security

Diagram

diagram
CLICKJACKING β€” side view of the same pixel

     user sees          what actually receives the click
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚              β”‚    β”‚  your-bank.com/transfer      β”‚
  β”‚  CLAIM PRIZE β”‚ ◄───  [ Confirm transfer ]        β”‚  opacity: 0
  β”‚              β”‚    β”‚  (real session, real cookies)β”‚  z-index: 10
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    attacker page          your page in an <iframe>

  The click is genuine. The user's intent is not.
diagram
TWO DIRECTIONS, TWO CONTROLS

  YOU GET FRAMED                      YOU EMBED SOMEONE
  ────────────────                    ─────────────────
  CSP: frame-ancestors 'none'         <iframe sandbox="allow-scripts">
  X-Frame-Options: DENY (legacy)      <iframe allow="camera 'none'">
                                      referrerpolicy="no-referrer"
  Default: any site may frame you.    Default: full privileges.
diagram
SANDBOX β€” everything off, then add back only what's needed

  <iframe sandbox>                     nothing allowed
    + allow-scripts                    JS runs
    + allow-forms                      forms submit
    + allow-same-origin                ⚠ keeps its own origin

  allow-scripts + allow-same-origin together
  = the frame can remove its own sandbox. Never pair them
    for content you don't control.

How it works

  1. Stop being framed: send Content-Security-Policy: frame-ancestors 'none' (or list allowed parents). X-Frame-Options: DENY covers older browsers.
  2. Contain what you embed: start from sandbox with no values and add the minimum.
  3. Cut capabilities with allow="camera 'none'; microphone 'none'" β€” that's Permissions-Policy applied per frame (3.12).
  4. Talk safely across frames: postMessage with an explicit targetOrigin, and validate event.origin on receive β€” never '*'.
js
window.addEventListener('message', (e) => {
  if (e.origin !== 'https://trusted-widget.com') return;   // mandatory
  handle(e.data);
});

Trade-offs

ControlUse when
frame-ancestors 'none'Default for any authenticated page
frame-ancestors https://partner.comDeliberate partner embedding
sandbox (empty)Untrusted HTML, previews, user content
sandbox="allow-scripts"Third-party widget you must run

Interview angle

"Your dashboard can be embedded on any site. What's the risk and the fix?"

  • Clickjacking: an invisible overlay turns a real user click into a real destructive action.
  • Fix with frame-ancestors, plus SameSite=Lax cookies so framed requests don't carry the session.
  • If embedding is a product requirement, allowlist specific parents and require confirmation steps for destructive actions.

Recap

  • frame-ancestors controls who frames you; sandbox and allow control what you frame.
  • Never combine allow-scripts with allow-same-origin on untrusted content.
  • Always validate event.origin in postMessage handlers.