Skip to Content

No clickjacking protection header

What Is This Issue

This issue checks whether your website has protection against clickjacking attacks by declaring either the X-Frame-Options HTTP header or the frame-ancestors directive in the Content-Security-Policy header.

What this issue checks

  • The X-Frame-Options header is present with a valid value (DENY or SAMEORIGIN), OR
  • The Content-Security-Policy header includes a frame-ancestors directive
  • The header value is not misspelled or invalid (e.g., denied instead of DENY)

What is considered a passing implementation

A passing implementation means:

  • The X-Frame-Options header is present with DENY or SAMEORIGIN value, OR
  • The Content-Security-Policy header includes a frame-ancestors directive
  • The header value is correctly spelled and cased

Real-world example

A properly configured X-Frame-Options header looks like:

X-Frame-Options: DENY

Or using the modern CSP approach:

Content-Security-Policy: frame-ancestors 'none';

These tell browsers that your page cannot be embedded in an iframe on other websites, preventing clickjacking attacks.

Why Is This Important

Clickjacking protection is important for security and SEO:

Crawlability

If your site is vulnerable to clickjacking, attackers could potentially use it to manipulate your pages or redirect users to malicious sites, which could affect your SEO if search engines detect such manipulation.

Indexability

Similar to crawlability, security vulnerabilities can lead to indexing issues if attackers manipulate your content or redirect crawlers.

Rankings

While not a direct ranking factor, sites vulnerable to clickjacking can be exploited to manipulate user behavior, potentially leading to security incidents that harm your site’s reputation and search rankings.

User Experience

Clickjacking attacks trick users into performing unintended actions (like confirming payments, granting permissions, or deleting accounts) by embedding your page in a transparent iframe on a malicious site. Without protection, users can be manipulated without their knowledge.

AI Search / AEO

AI-powered search engines prioritize secure, trustworthy sites that protect users from attacks.

SEO Health Score Impact

Resolving this issue improves your overall SEO health score by protecting users from clickjacking attacks and demonstrating your commitment to security best practices.

How XeoPix Detects This

XeoPix checks whether your website has protection against clickjacking attacks by declaring either the X-Frame-Options HTTP header or the frame-ancestors directive in the Content-Security-Policy header.

Detection process

XeoPix follows these logical steps to identify clickjacking protection issues:

  1. Check for X-Frame-Options header - XeoPix looks for the X-Frame-Options header in the HTTP response.

  2. Validate X-Frame-Options value - If the header is present, XeoPix checks if the value is a recognized directive:

    • DENY (page cannot be embedded in any iframe)
    • SAMEORIGIN (page can only be embedded by same-origin pages)
  3. Check for CSP frame-ancestors - XeoPix also checks if the Content-Security-Policy header includes a frame-ancestors directive, which is the modern replacement for X-Frame-Options.

  4. Verify protection - XeoPix considers the page protected if either:

    • X-Frame-Options header is present with a valid value, OR
    • Content-Security-Policy header includes frame-ancestors directive

When the issue is flagged

The issue is flagged when any of these conditions are met:

  • Neither X-Frame-Options nor CSP frame-ancestors is present
  • X-Frame-Options is present but has an invalid or unrecognized value (e.g., misspelled or using deprecated ALLOW-FROM)

When the issue passes

The issue passes when:

  • The X-Frame-Options header is present with DENY or SAMEORIGIN value, OR
  • The Content-Security-Policy header includes a frame-ancestors directive
  • The header value is correctly spelled and cased

How To Fix

Follow these steps to implement clickjacking protection:

Step 1: Choose your protection method

  • Option A (Traditional): Use X-Frame-Options header (simpler, widely supported)
  • Option B (Modern): Use frame-ancestors directive in CSP header (more flexible, recommended)

Step 2: Set X-Frame-Options header (if using Option A)

Set X-Frame-Options header on your web server, CDN, or load balancer:

X-Frame-Options: DENY

Or if you need to allow embedding from same-origin only:

X-Frame-Options: SAMEORIGIN

Step 3: Set CSP frame-ancestors directive (if using Option B)

Set CSP frame-ancestors directive:

Content-Security-Policy: frame-ancestors 'none';

Or to allow same-origin embedding:

Content-Security-Policy: frame-ancestors 'self';

Or to allow specific trusted domains:

Content-Security-Policy: frame-ancestors 'self' https://trusted-partner.com;

Step 4: Avoid deprecated ALLOW-FROM

Avoid deprecated ALLOW-FROM directive, which is not supported in modern browsers (Chrome, Firefox, Safari).

Step 5: Use correct syntax

Ensure values are uppercase and correctly spelled (DENY, not denied or Deny).

Step 6: Test your configuration

Test your configuration using browser developer tools to verify the header is present and correctly configured.

What We Store

Storage Level

Page Level — This issue is evaluated for each individual URL.


Database Table / Prisma Model

PageSecurityHeader


Stored Fields

FieldTypeDescription
xFrameOptionsString?X-Frame-Options header value
cspFrameAncestorsString?frame-ancestors directive from CSP header

Detection Dependencies

  • The following data sources are required to evaluate this issue:
  • HTTP Response Headers — The crawler checks for the presence and value of the X-Frame-Options header
  • Content-Security-Policy Header — The frame-ancestors directive in the CSP header is also checked as a modern alternative to X-Frame-Options

Examples

Example 1: Missing X-Frame-Options Header

Problem: The X-Frame-Options header is not present.

What fails:

HTTP response does not include X-Frame-Options header

What passes:

X-Frame-Options: DENY

Example 2: Invalid X-Frame-Options Value

Problem: The X-Frame-Options header has a misspelled or invalid value.

What fails:

X-Frame-Options: denied

What passes:

X-Frame-Options: DENY

Example 3: Using Modern CSP Approach

Scenario: Using the modern CSP frame-ancestors directive instead of X-Frame-Options.

What passes:

Content-Security-Policy: frame-ancestors 'none';

This is the modern approach and provides more flexibility than X-Frame-Options.

Unit Test

Test File

__tests__/seo-audit-checks/httpSecurityHeaders/issue-140-x-frame-options.test.js

Purpose

This unit test validates that the X-Frame-Options header check correctly identifies when neither the X-Frame-Options header nor the CSP frame-ancestors directive is configured to prevent clickjacking.

Tested Function

runHttpSecurityHeaders() from toggleGroups/httpSecurityHeaders.js

Issue Information

  • Issue Number: 140
  • Issue Code: x_frame_options
  • Toggle Group: httpSecurityHeaders

Test Scenarios

Positive Test Cases

Scenarios where the issue should be reported:

  • Neither X-Frame-Options header nor CSP frame-ancestors directive is present
  • X-Frame-Options header is present but its value is an empty string

Negative Test Cases

Scenarios where the issue should not be reported:

  • X-Frame-Options header is present with value DENY
  • X-Frame-Options header is present with value SAMEORIGIN
  • CSP content-security-policy header has a frame-ancestors directive (e.g., frame-ancestors 'none')
  • Both X-Frame-Options (DENY) and CSP frame-ancestors are present

Boundary Cases

  • X-Frame-Options with empty string '' — treated as missing and flagged

Edge Cases

  • CSP frame-ancestors directive satisfies the requirement even without X-Frame-Options header
  • Both headers present simultaneously — no duplicate issue

Expected Outcome

Pass

The issue is reported when neither the x-frame-options header nor the CSP frame-ancestors directive is present, or when x-frame-options is present but empty.

Fail

The issue is not reported when X-Frame-Options is present with a valid value (DENY or SAMEORIGIN), or when CSP includes a frame-ancestors directive.

Validation

The unit test verifies:

  • Correct detection when both clickjacking protections are absent
  • No detection when X-Frame-Options is DENY or SAMEORIGIN
  • No detection when CSP has frame-ancestors directive
  • No detection when both protections are present
  • Correct detection when X-Frame-Options value is empty
  • The issue details message is populated correctly
  • toggleGroups/httpSecurityHeaders.js — contains the runHttpSecurityHeaders() function and extract() logic
  • issueCodes.js — defines IssueCode.X_FRAME_OPTIONS
  • utils/ssl.js — provides extractCspFrameAncestors() used to parse CSP frame-ancestors

Coverage Summary

  • Covers the full X-Frame-Options and CSP frame-ancestors detection logic
  • Tests both individual and combined protection scenarios
  • Tests valid values (DENY, SAMEORIGIN) and edge case (empty string)
  • Validates the issue detection message string

References

Last updated on