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.
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.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.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
- Stop being framed: send
Content-Security-Policy: frame-ancestors 'none'(or list allowed parents).X-Frame-Options: DENYcovers older browsers. - Contain what you embed: start from
sandboxwith no values and add the minimum. - Cut capabilities with
allow="camera 'none'; microphone 'none'"β that'sPermissions-Policyapplied per frame (3.12). - Talk safely across frames:
postMessagewith an explicittargetOrigin, and validateevent.originon receive β never'*'.
window.addEventListener('message', (e) => {
if (e.origin !== 'https://trusted-widget.com') return; // mandatory
handle(e.data);
});Trade-offs
| Control | Use when |
|---|---|
frame-ancestors 'none' | Default for any authenticated page |
frame-ancestors https://partner.com | Deliberate 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, plusSameSite=Laxcookies 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-ancestorscontrols who frames you;sandboxandallowcontrol what you frame.- Never combine
allow-scriptswithallow-same-originon untrusted content. - Always validate
event.origininpostMessagehandlers.