X-Frame-Options Header: Setup, Best Practices & Common Issues


The X-Frame-Options header is a security control that tells browsers whether a webpage can be displayed in a frame, iframe, or object. It prevents unauthorized sites from embedding content, reducing the risk of clickjacking attacks that trick users into unintended actions.
Clickjacking and UI redress attacks exploit hidden frames to manipulate user interactions. X-Frame-Options provides clear directives to browsers on which origins can frame content or whether framing should be blocked entirely, protecting sensitive user actions.
This article explains how to set up, test, and follow best practices for X-Frame-Options headers.
What Is the X-Frame-Options Header?
The X-Frame-Options (XFO) header is an HTTP response header used to control whether a webpage can be embedded within frames, iframes, or objects on other sites. It is a key security measure designed to prevent malicious websites from loading your content in a hidden frame to perform clickjacking attacks.
How X-Frame-Options Protects Against Clickjacking and UI Redress Attack
Clickjacking occurs when an attacker overlays a legitimate website in a hidden frame, tricking users into clicking buttons or submitting forms unknowingly. UI redress attacks similarly manipulate a site’s interface to mislead users.
The X-Frame-Options header protects against these threats by specifying which pages can embed content:
- DENY: Completely blocks the page from being framed by any site. This prevents attackers from embedding the page in a hidden frame, eliminating the possibility of clickjacking entirely.
- SAMEORIGIN: Allows the page to be framed only by pages from the same domain. This supports legitimate internal framing (e.g., dashboards or portals) while blocking external malicious sites.
- ALLOW-FROM
: Permits framing by a specific, trusted domain. This is useful for controlled integrations or partner sites, ensuring only authorized domains can embed the content. Note that browser support for this directive is limited.
X-Frame-Options vs. Content Security Policy (CSP): Which to Use?
While X-Frame-Options provides basic protection against framing attacks, modern web security often recommends Content Security Policy (CSP) as a more flexible and comprehensive approach.
CSP allows developers to define multiple security rules, including frame-ancestors, script sources, and media sources, giving finer control over which domains can embed or interact with content.
Here are the key differences between X-Frame-Options and Content Security Policy (CSP)
- Scope of Control: X-Frame-Options only governs framing, while CSP can enforce broader security policies, including framing, scripts, and media.
- Browser Support: X-Frame-Options is widely supported across older browsers, whereas CSP requires modern browser versions.
- Flexibility: CSP’s frame-ancestors directive can specify multiple allowed domains, while X-Frame-Options supports only a single origin with ALLOW-FROM.
- Complementary Use: For maximum protection, it’s common to use both X-Frame-Options and CSP together, ensuring coverage for older browsers while leveraging CSP’s advanced capabilities.
To choose between X-Frame-Options and CSP, consider the site’s audience, required browser support, and overall security needs. X-Frame-Options is sufficient for basic clickjacking protection, while CSP provides a more comprehensive and future-proof solution.
Step-by-Step Guide to Implementing X-Frame-Options
Implementing the X-Frame-Options header involves configuring your web server or application to send the appropriate HTTP response header. The steps differ slightly depending on the server or platform used, but the overall process is straightforward.
Step 1: Choose the appropriate directive
Decide whether to use DENY, SAMEORIGIN, or ALLOW-FROM based on your website’s requirements. DENY is the safest for public-facing pages, SAMEORIGIN is suitable for internal portals, and ALLOW-FROM is for trusted external integrations.
Step 2: Configure the server or application
- Apache: Add the header in your .htaccess file or server configuration:
Header always set X-Frame-Options "SAMEORIGIN" - Nginx: Include the header in your server block configuration:
add_header X-Frame-Options "DENY"; - Express.js (Node.js): Use middleware to set the header:
Step 3: Test the implementation
After configuring the header, check that it is correctly sent with HTTP responses. Use browser developer tools, online header checkers, or automated testing tools to confirm that the desired X-Frame-Options value is applied consistently.
Step 4: Monitor and maintain
Ensure that any new pages or applications added to the site also include the header. Periodically review configurations to maintain protection as the site evolves.
Common Pitfalls When Configuring X-Frame-Options
Misconfigurations of the X-Frame-Options header can leave websites vulnerable or unintentionally block legitimate content. Being aware of common pitfalls helps ensure the header provides effective protection without breaking site functionality.
- Using ALLOW-FROM without considering browser support: Most modern browsers no longer support ALLOW-FROM, so relying on it can leave framing vulnerabilities.
- Inconsistent header application: Applying the header on some pages but not others can allow attackers to target unprotected pages. Ensure all critical pages consistently send the header.
- Conflicts with CSP: If both X-Frame-Options and CSP frame-ancestors are set, ensure they align. Conflicting policies can prevent legitimate framing or weaken protection.
- Overly restrictive directives: Using DENY on pages that require internal framing (e.g., dashboards or embedded widgets) can break functionality. Analyze site requirements before enforcing strict rules.
- Not testing properly: Simply adding the header is insufficient. Failing to test with different browsers, pages, and external embedding scenarios can leave gaps in protection.
X-Frame-Options Best Practices
Implementing X-Frame-Options effectively requires following best practices that balance security with functionality:
- Use DENY for public-facing pages: Completely block framing on pages that do not require any embedded content to eliminate clickjacking risk.
- Apply SAMEORIGIN for internal pages: Allow framing only from the same domain when internal dashboards, portals, or widgets require it.
- Combine with CSP for broader protection: Use CSP’s frame-ancestors directive alongside X-Frame-Options to cover modern browsers and allow more granular control.
- Consistently set headers across all pages: Ensure that every page, including subdomains and new additions, sends the correct header to avoid security gaps.
- Document exceptions carefully: If some pages require different framing rules, clearly document why and how exceptions are implemented to maintain maintainable security policies.
- Regularly test and monitor: Use tools like Requestly, browser developer tools, or monitoring platforms to verify that headers are applied correctly and functioning as intended.
Using Requestly to Monitor and Test X-Frame-Options Headers
Testing and monitoring X-Frame-Options headers in real-world scenarios is crucial to ensure that clickjacking protections are applied correctly. Requestly is a browser extension that allows developers and testers to intercept, modify, and observe HTTP requests and responses in real-time, making it an effective tool for validating X-Frame-Options configurations.
With Requestly, you can simulate different framing scenarios, modify headers on the fly, and verify that your site behaves as expected across various domains and browsers. This helps identify misconfigurations, compatibility issues, and potential security gaps before they affect end users.
Here are the steps to monitor and test X-Frame-Options headers:
- Install Requestly Extension: Download and add the extension to your browser to start intercepting and modifying HTTP traffic.
- Create a Modify Headers Rule: Open the Requestly dashboard, select “Modify Headers,” and create a new rule targeting the desired URL pattern.
- Configure Response Header Settings: Choose “Modify Response” and specify X-Frame-Options as the header to add or change. Set the value to DENY, SAMEORIGIN, or ALLOW-FROM
depending on the scenario you want to test. - Activate and Test the Rule: Save and enable the rule. Test embedding your pages in iframes from the same origin, different origins, or specific URIs to validate that the header behaves as intended.
- Simulate Clickjacking Attempts: Use invisible overlays or external pages to confirm that unauthorized framing is blocked, ensuring clickjacking protections are effective.
- Check Across Browsers: Verify the behavior in multiple browsers to confirm consistent enforcement of X-Frame-Options headers and identify any browser-specific issues.
Conclusion
The X-Frame-Options header is essential for preventing clickjacking and UI redress attacks by controlling which domains can embed your web pages. Proper implementation ensures that sensitive actions, forms, and dashboards cannot be manipulated by hidden frames, while still allowing legitimate internal or partner integrations.
Requestly enables developers and testers to monitor and modify X-Frame-Options headers in real-time, simulate cross-origin framing scenarios, and detect misconfigurations before they become security issues, ensuring robust protection and smooth functionality.


Contents
- What Is the X-Frame-Options Header?
- How X-Frame-Options Protects Against Clickjacking and UI Redress Attack
- X-Frame-Options vs. Content Security Policy (CSP): Which to Use?
- Step-by-Step Guide to Implementing X-Frame-Options
- Common Pitfalls When Configuring X-Frame-Options
- X-Frame-Options Best Practices
- Using Requestly to Monitor and Test X-Frame-Options Headers
- Conclusion
Subscribe for latest updates
Share this article
Related posts











