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-Optionsheader is present with a valid value (DENYorSAMEORIGIN), OR - The
Content-Security-Policyheader includes aframe-ancestorsdirective - The header value is not misspelled or invalid (e.g.,
deniedinstead ofDENY)
What is considered a passing implementation
A passing implementation means:
- The
X-Frame-Optionsheader is present withDENYorSAMEORIGINvalue, OR - The
Content-Security-Policyheader includes aframe-ancestorsdirective - The header value is correctly spelled and cased
Real-world example
A properly configured X-Frame-Options header looks like:
X-Frame-Options: DENYOr 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:
-
Check for X-Frame-Options header - XeoPix looks for the
X-Frame-Optionsheader in the HTTP response. -
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)
-
Check for CSP frame-ancestors - XeoPix also checks if the
Content-Security-Policyheader includes aframe-ancestorsdirective, which is the modern replacement forX-Frame-Options. -
Verify protection - XeoPix considers the page protected if either:
X-Frame-Optionsheader is present with a valid value, ORContent-Security-Policyheader includesframe-ancestorsdirective
When the issue is flagged
The issue is flagged when any of these conditions are met:
- Neither
X-Frame-Optionsnor CSPframe-ancestorsis present X-Frame-Optionsis present but has an invalid or unrecognized value (e.g., misspelled or using deprecatedALLOW-FROM)
When the issue passes
The issue passes when:
- The
X-Frame-Optionsheader is present withDENYorSAMEORIGINvalue, OR - The
Content-Security-Policyheader includes aframe-ancestorsdirective - 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-Optionsheader (simpler, widely supported) - Option B (Modern): Use
frame-ancestorsdirective 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: DENYOr if you need to allow embedding from same-origin only:
X-Frame-Options: SAMEORIGINStep 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
| Field | Type | Description |
|---|---|---|
| xFrameOptions | String? | X-Frame-Options header value |
| cspFrameAncestors | String? | 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-Optionsheader - Content-Security-Policy Header — The
frame-ancestorsdirective 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 headerWhat passes:
X-Frame-Options: DENYExample 2: Invalid X-Frame-Options Value
Problem: The X-Frame-Options header has a misspelled or invalid value.
What fails:
X-Frame-Options: deniedWhat passes:
X-Frame-Options: DENYExample 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-Optionsheader nor CSPframe-ancestorsdirective is present X-Frame-Optionsheader is present but its value is an empty string
Negative Test Cases
Scenarios where the issue should not be reported:
X-Frame-Optionsheader is present with valueDENYX-Frame-Optionsheader is present with valueSAMEORIGIN- CSP
content-security-policyheader has aframe-ancestorsdirective (e.g.,frame-ancestors 'none') - Both
X-Frame-Options(DENY) and CSPframe-ancestorsare present
Boundary Cases
X-Frame-Optionswith empty string''— treated as missing and flagged
Edge Cases
- CSP
frame-ancestorsdirective satisfies the requirement even withoutX-Frame-Optionsheader - 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-OptionsisDENYorSAMEORIGIN - No detection when CSP has
frame-ancestorsdirective - No detection when both protections are present
- Correct detection when
X-Frame-Optionsvalue is empty - The issue details message is populated correctly
Related Production Files
toggleGroups/httpSecurityHeaders.js— contains therunHttpSecurityHeaders()function andextract()logicissueCodes.js— definesIssueCode.X_FRAME_OPTIONSutils/ssl.js— providesextractCspFrameAncestors()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