Introduction
X-Frame-Options is a simple but effective HTTP header that controls whether your page can be embedded in frames. It's your first line of defense against clickjacking.
Key Concepts
DENY: Never allow framing, by anyone, ever.
SAMEORIGIN: Only allow framing from the same origin (domain + protocol + port).
ALLOW-FROM: Deprecated—use CSP frame-ancestors instead.
Real World Context
Many admin panels and internal tools are served without X-Frame-Options because developers assume they are "internal only." Attackers who compromise any page on the same network can frame these tools to perform administrative actions through the victim's authenticated session.
Deep Dive
Global Configuration
python# settings.py MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ... ] # DENY - most secure, use for most pages X_FRAME_OPTIONS = 'DENY' # SAMEORIGIN - if you need to frame your own pages X_FRAME_OPTIONS = 'SAMEORIGIN'
Per-View Configuration
pythonfrom django.views.decorators.clickjacking import ( xframe_options_deny, xframe_options_sameorigin, xframe_options_exempt ) # Most restrictive for sensitive pages @xframe_options_deny def account_settings(request): pass # Allow embedding your own widgets @xframe_options_sameorigin def embed_widget(request): pass # Public content that can be embedded anywhere @xframe_options_exempt def public_video(request): pass
Common Pitfalls
- Using SAMEORIGIN as default instead of DENY — Unless you actively embed your own pages in iframes, DENY is safer and eliminates an entire class of same-origin clickjacking attacks.
- Forgetting to protect API endpoints — Framing attacks can target any page that performs actions, including non-HTML responses that render in certain browser contexts.
Best Practices
- Default to DENY: Unless you specifically need framing.
- Use SAMEORIGIN sparingly: Only for internal embedding needs.
- Document exemptions: Comment why each exempt view is safe.
Summary
Set X_FRAME_OPTIONS = 'DENY' globally and selectively allow framing for specific views that require it. DENY is the safest default for protecting against clickjacking.