Security | WordPress

WordPress Security Headers: What They Are, Why They Matter for SEO, and How to Set Them Up

cute bots protecting your reputation with a shield
To Top

If you have ever run a technical SEO audit and noticed a section about security headers and quietly skipped past it, you are not alone. Security headers sit at the intersection of web development and SEO, and they are easy to overlook. But ignoring them can leave your site open to attacks that tank your rankings, damage user trust, and get your site flagged by Google.

This guide covers every HTTP security header graded by SecurityHeaders.com, what each one does, how it relates to SEO, and how to implement it on the three most common WordPress hosting environments: WP Engine, GoDaddy, and AWS.

What Are HTTP Security Headers?

HTTP security headers are response headers your web server sends to a visitor’s browser with instructions on how to behave when loading your site. They are invisible to users but play a critical role in controlling how your content is handled, embedded, and executed.

Think of them as house rules your server sets for every browser that loads your pages: what scripts it can run, which origins it can load resources from, whether your pages can appear inside an iframe on another domain, and whether connections must be encrypted.

Without security headers, browsers fall back to permissive defaults. They will execute inline scripts from any origin, allow your pages to be framed by any site, and trust whatever MIME type a server claims a file to be. That openness is exactly what attackers exploit.

Common attack vectors that security headers directly mitigate include:

  • Cross-Site Scripting (XSS): malicious scripts injected into your pages and executed in visitors’ browsers
  • Clickjacking: your site loaded in an invisible iframe on another domain to trick users into unintended actions
  • Man-in-the-Middle attacks: traffic intercepted between browser and server over unencrypted HTTP
  • MIME confusion attacks: malicious files disguised as harmless ones (JavaScript served as an image, for example)
  • Cross-Site Script Inclusion (XSSI): sensitive data from your site leaked to a third-party page through embedded resources
  • Spectre-style side-channel attacks: timing exploits that leak cross-origin data through shared browser memory

Do Security Headers Affect SEO?

Yes, though the relationship is mostly indirect. Google’s John Mueller addressed this directly in a Reddit thread on r/TechSEO when asked which security headers belong in an SEO audit:

“The only security headers that I could imagine has an effect on SEO is blocking iframing by other sites, either with the old x-frame-options header, or the CSP frame-ancestors. Otherwise, from my understanding, the security headers are more about, well, security.”

— John Mueller, Google

The direct SEO impact: X-Frame-Options (and its modern replacement, the CSP frame-ancestors directive) prevents other sites from embedding your content in an iframe. Without it, a competitor or bad actor could display your pages inside their domain and potentially capture ranking signals, user attention, or clicks that belong to you.

The indirect SEO impact: A compromised WordPress site can be de-indexed, served with malware warnings in search results, or have its rankings wiped entirely. Injected scripts slow down page speed and damage Core Web Vitals scores. Clickjacking attacks erode user trust signals. Security headers are infrastructure-level protection for the rankings you have already earned.

If your technical SEO checklist does not include a security header audit, it is incomplete.

Every Security Header Graded by SecurityHeaders.com

SecurityHeaders.com is the standard tool for grading HTTP response headers, scoring sites from A+ to F. It evaluates seven core headers that directly affect your grade, plus additional headers it reports on for completeness. Here is a full breakdown of every one of them.

The Seven Headers That Affect Your SecurityHeaders.com Grade

1. Content-Security-Policy (CSP)

Content-Security-Policy is the most powerful security header available. It defines a whitelist of approved sources for every type of resource your page loads: scripts, stylesheets, images, fonts, iframes, and more. Any resource from a source not on your list is blocked before it reaches the browser. CSP is your primary defense against XSS and data injection attacks.

Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';

Important implementation notes for WordPress sites:

  • Always test with Content-Security-Policy-Report-Only before enforcing. A strict CSP applied without testing will break Google Tag Manager, analytics scripts, embedded fonts, ad pixels, and third-party widgets.
  • Not all CSP directives fall back to default-src. The form-action and frame-ancestors directives must be specified explicitly; omitting them creates bypass vectors even when default-src is set.
  • The frame-ancestors directive is the modern replacement for X-Frame-Options. Set both for maximum browser compatibility.

2. Strict-Transport-Security (HSTS)

HSTS tells browsers to connect to your domain over HTTPS only, even if a user types http:// in the address bar. Once a browser receives this header, it refuses to make an unencrypted HTTP connection to your domain for the duration of the max-age value. This prevents protocol downgrade attacks and cookie hijacking on unsecured networks.

Strict-Transport-Security: max-age=31536000; includeSubDomains

When you are fully committed to HTTPS across every subdomain, add the preload directive and submit to hstspreload.org to have your domain hardcoded into browsers permanently. Start with a short max-age like 300 seconds during testing and ramp up gradually. A misconfigured HSTS with a long max-age and a lapsed SSL certificate will lock users out of your site with no bypass option.

3. X-Frame-Options

X-Frame-Options controls whether your pages can be loaded inside an <iframe>, <frame>, or <embed> on another domain. It is your primary clickjacking defense and the one header Google has explicitly tied to SEO, as it prevents your content from being displayed on a competitor’s domain inside a frame.

X-Frame-Options: SAMEORIGIN

Values: DENY blocks all framing; SAMEORIGIN allows only your own domain to frame your pages. The ALLOW-FROM value is deprecated and no longer supported in modern browsers. The CSP frame-ancestors directive is the modern successor and offers more granular control, but X-Frame-Options is still worth setting for backward compatibility with older browsers.

One WordPress-specific note: if you use oEmbed or WordPress’s built-in URL embed previews in the block editor, setting X-Frame-Options: DENY will break them. Use SAMEORIGIN instead.

4. X-Content-Type-Options

This header prevents browsers from MIME-sniffing a response (guessing a file’s type when it differs from what the server declared). Without it, a browser might decide a file served as an image is actually a script and execute it. This is exactly the kind of confusion MIME confusion attacks exploit. The only valid value is nosniff.

X-Content-Type-Options: nosniff

5. Referrer-Policy

Referrer-Policy controls how much URL information is included in the Referer header when a user clicks a link away from your site. Without it, sensitive data in URLs, such as password reset tokens, session IDs, and internal path structures, can be exposed to third-party domains. It also has privacy implications relevant to GDPR compliance.

Referrer-Policy: strict-origin-when-cross-origin

This value sends the full URL for same-origin requests, sends only the origin (no path or query string) for cross-origin requests, and sends nothing when navigating from HTTPS to HTTP. It is the recommended default for most sites.

6. Permissions-Policy

Permissions-Policy (formerly Feature-Policy) restricts which browser APIs and hardware features your pages can access or request, including camera, microphone, geolocation, payment APIs, and autoplay. Disabling features your site does not use reduces your attack surface and supports privacy compliance requirements.

Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=()

An empty parenthesis value disables the feature entirely. You can also grant access to specific trusted origins: geolocation=(self "https://trusted-partner.com").

7. X-Permitted-Cross-Domain-Policies

This header tells legacy Adobe clients (Flash, Acrobat) whether they are permitted to load content across domains from your server. Flash is gone, but this header is still evaluated by SecurityHeaders.com and should be set to prevent any residual legacy plugin exploits.

X-Permitted-Cross-Domain-Policies: none

For virtually every WordPress site, none is the correct and only value you will ever need.

Additional Headers SecurityHeaders.com Reports On

These headers do not directly affect your SecurityHeaders.com letter grade, but the tool reports on their presence. They are either situational (primarily relevant to advanced web applications) or deprecated.

Cross-Origin-Opener-Policy (COOP)

COOP controls whether your top-level page can share a browsing context group with cross-origin documents opened in popups. Setting it to same-origin isolates your page from cross-origin windows, protecting against Spectre-style side-channel attacks that exploit shared browser process memory.

Cross-Origin-Opener-Policy: same-origin

Available values:

  • unsafe-none: the default, with no isolation applied
  • same-origin-allow-popups: isolates from cross-origin documents but preserves popup window references, making it compatible with OAuth and payment flows that communicate back through a popup
  • same-origin: full isolation, required for cross-origin isolation, but severs all cross-origin window references including OAuth and payment popups

For most WordPress sites, COOP is optional. It becomes relevant when you need access to advanced browser APIs like SharedArrayBuffer, which require cross-origin isolation achieved by pairing COOP with COEP.

Cross-Origin-Embedder-Policy (COEP)

COEP controls which cross-origin resources your page is allowed to load. When set to require-corp, the browser blocks any cross-origin resource that has not explicitly opted in to being loaded via CORS headers or a Cross-Origin-Resource-Policy header.

Cross-Origin-Embedder-Policy: require-corp

Pairing COEP with COOP set to same-origin achieves full cross-origin isolation, which is required to unlock SharedArrayBuffer, performance.measureUserAgentSpecificMemory(), and high-precision timers. A looser alternative value, credentialless, allows no-cors cross-origin requests without requiring CORP headers on embedded resources, which is useful when you do not control the third-party resources your page loads.

Like COOP, COEP is primarily relevant to advanced web applications, not standard WordPress sites. Always test in report-only mode first: Cross-Origin-Embedder-Policy-Report-Only: require-corp.

Cross-Origin-Resource-Policy (CORP)

CORP tells the browser which origins are allowed to load a specific resource from your server. Unlike CORS, which controls JavaScript-level access, CORP blocks the request entirely before the response body is delivered. This protects against Cross-Site Script Inclusion (XSSI) attacks and Spectre-style memory timing exploits where a malicious page embeds one of your resources to leak its contents through timing analysis.

Cross-Origin-Resource-Policy: same-origin

Values: same-origin (only your domain), same-site (same-site subdomains allowed), and cross-origin (any origin; appropriate for public CDN assets). CORP works alongside COEP: if COEP is set to require-corp, embedded resources also need CORP headers or they will be blocked.

Deprecated Headers SecurityHeaders.com Flags

X-XSS-Protection

This older header enabled the built-in XSS filter in Internet Explorer, early Chrome, and Safari. It is now fully deprecated. Current guidance from both OWASP and MDN is to explicitly set it to 0 and rely on a properly configured Content-Security-Policy instead. Leaving it at 1; mode=block can actually introduce XSS vulnerabilities in some modern browsers.

X-XSS-Protection: 0

Expect-CT (Remove It)

Expect-CT previously allowed sites to opt into Certificate Transparency reporting. Modern browsers now enforce CT requirements automatically, making this header obsolete. Mozilla actively recommends removing it from existing codebases if it is present.

How to Implement Security Headers by Hosting Platform

WP Engine

WP Engine runs on Nginx and does not provide root-level .htaccess access. You have three reliable implementation paths.

Option 1: WordPress send_headers hook (works on any host)

Add this to a custom plugin or your child theme’s functions.php. This is the most portable approach and requires no server access.

add_action( 'send_headers', function() {
    header( 'X-Frame-Options: SAMEORIGIN' );
    header( 'X-Content-Type-Options: nosniff' );
    header( 'Strict-Transport-Security: max-age=31536000; includeSubDomains' );
    header( 'Referrer-Policy: strict-origin-when-cross-origin' );
    header( 'Permissions-Policy: geolocation=(), camera=(), microphone=()' );
    header( 'X-Permitted-Cross-Domain-Policies: none' );
    header( 'X-XSS-Protection: 0' );
    header( "Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';" );
} );

Option 2: Nginx rules in the WP Engine User Portal

In your WP Engine portal, go to your environment, then Nginx, then Nginx Rules. Add the following block. These rules apply at the server level and are slightly more performant than PHP-level headers.

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-XSS-Protection "0" always;
add_header Content-Security-Policy "default-src 'self';" always;

Option 3: Security plugin

Really Simple Security, W3 Total Cache, and All in One SEO (AIOSEO) all offer security header configuration through a UI. Good option if you prefer to avoid code changes, but server-level configuration is always preferable when accessible.

GoDaddy (cPanel / Apache)

On GoDaddy shared or managed WordPress hosting, add headers directly to your .htaccess file in the WordPress root. Back up the file first. Place this block above the # BEGIN WordPress comment.

# Security Headers
<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()"
    Header always set X-Permitted-Cross-Domain-Policies "none"
    Header always set X-XSS-Protection "0"
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-src 'none'; object-src 'none'; form-action 'self';"
</IfModule>

If GoDaddy’s managed WordPress environment restricts .htaccess modifications, fall back to the WordPress send_headers hook shown above.

AWS (CloudFront, Apache on EC2, Nginx on EC2)

Option 1: CloudFront Response Headers Policy (recommended)

For WordPress sites on EC2 behind CloudFront, or static sites on S3, configure headers at the CDN layer so they apply universally regardless of origin server configuration.

  1. Go to CloudFront, then Policies, then Response headers.
  2. Create a new custom policy and add your headers under the Security headers section.
  3. Attach the policy to your distribution’s cache behavior.

AWS includes a managed policy called SecurityHeadersPolicy that covers HSTS, X-Content-Type-Options, X-Frame-Options, and Referrer-Policy. For CSP, Permissions-Policy, and cross-origin headers, create a custom policy.

Option 2: Apache VirtualHost on EC2

<VirtualHost *:443>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()"
    Header always set X-Permitted-Cross-Domain-Policies "none"
    Header always set X-XSS-Protection "0"
    Header always set Content-Security-Policy "default-src 'self';"
</VirtualHost>

Option 3: Nginx on EC2

Add to your server block in /etc/nginx/sites-available/your-site.conf and reload Nginx after saving.

server {
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
    add_header X-Permitted-Cross-Domain-Policies "none" always;
    add_header X-XSS-Protection "0" always;
    add_header Content-Security-Policy "default-src 'self';" always;
}

How to Verify Your Security Headers

After implementing, confirm your headers are being served correctly before moving on.

  • SecurityHeaders.com: grades your site A+ through F, flags missing headers, and analyzes whether present header values are actually configured correctly, not just present. A CSP that allows unsafe-inline or a bypassable host allowlist will be called out even if the header exists.
  • Chrome DevTools: Network tab, click your domain, inspect Response Headers to see exactly what your server is sending.
  • Mozilla Observatory: detailed security scoring including header analysis and additional checks.

Recommended Implementation Order

For a WordPress site starting from zero, implement in this sequence to minimize risk and maximize impact at each step.

  1. X-Frame-Options, X-Content-Type-Options, X-Permitted-Cross-Domain-Policies, X-XSS-Protection: 0. Implement these together. All four are single-value headers with no configuration complexity, and they immediately move your SecurityHeaders.com grade.
  2. Referrer-Policy and Permissions-Policy. These carry low configuration overhead, deliver strong privacy benefit, and are safe for virtually all WordPress configurations.
  3. HSTS. Confirm HTTPS is working correctly across your domain and all subdomains before enabling. Start with max-age=300, verify, then ramp to max-age=31536000. Add preload only when you are certain every subdomain will always support HTTPS.
  4. Content-Security-Policy. Implement last. Start in report-only mode (Content-Security-Policy-Report-Only), review violations in your browser console or a reporting endpoint, build your allowlist from real traffic, then switch to enforcement mode. CSP is the most impactful header and the most likely to break things if rushed.
  5. COOP, COEP, CORP. Implement only if your application specifically requires cross-origin isolation, for example to access SharedArrayBuffer. For standard WordPress sites, these are optional. Always test in report-only mode first.

Security Headers Quick Reference

Header Affects Grade Priority Protects Against
Content-Security-Policy Yes High; implement last, test first XSS, data injection, clickjacking
Strict-Transport-Security Yes High; verify HTTPS first Protocol downgrade, cookie hijacking
X-Frame-Options Yes High; direct SEO relevance Clickjacking, iframe content theft
X-Content-Type-Options Yes High; easy win MIME confusion attacks
Referrer-Policy Yes High; easy win URL data leakage to third parties
Permissions-Policy Yes High; easy win Browser API and hardware abuse
X-Permitted-Cross-Domain-Policies Yes Easy win; set to none Legacy plugin cross-domain exploits
Cross-Origin-Opener-Policy Reported Situational; advanced apps Spectre, cross-origin window attacks
Cross-Origin-Embedder-Policy Reported Situational; advanced apps XSSI, cross-origin resource loading
Cross-Origin-Resource-Policy Reported Situational; advanced apps Unauthorized resource embedding
X-XSS-Protection Noted Set to 0; deprecated N/A; use CSP instead
Expect-CT Noted Remove if present; deprecated N/A; enforced natively by browsers
FAQs

Frequently Asked Questions About WordPress Security Headers

Do security headers improve SEO rankings?

Not directly. Google has confirmed that X-Frame-Options is the only security header with a clear SEO implication, as it prevents content theft via iframes. The SEO value of other headers is indirect: they protect your site from attacks that can cause de-indexing, malware flags, page speed degradation, and ranking loss.

What is the difference between X-Frame-Options and CSP frame-ancestors?

Both prevent your site from being loaded in an iframe on another domain. CSPframe-ancestorsis the modern standard and gives you more granular control (you can whitelist specific domains). X-Frame-Options provides broader browser support. Set both for maximum coverage.

Will a Content-Security-Policy break my WordPress site?

It can if implemented without testing. CSP is the most complex security header to configure correctly on a WordPress site because plugins, themes, Google Tag Manager, analytics, and ad networks all load third-party resources. Always deploy inContent-Security-Policy-Report-Onlymode first and build your allowlist from actual traffic before enforcing.

How do I check if my security headers are set correctly?

Run your site through SecurityHeaders.com. It will grade your headers A+ through F and flag not just missing headers but misconfigured values within headers that are present.

Are security headers relevant for AI search and LLM crawlers?

Yes. AI crawlers and LLM agents assess page trustworthiness and technical quality as signals for inclusion in responses. A site that is compromised or serving injected content risks being excluded from AI-generated answers. Security headers are part of the foundational technical health that both traditional search engines and AI retrieval systems evaluate when determining whether a source is reliable.

What is the HSTS preload list?

The HSTS preload list is a browser-maintained list of domains hardcoded to always use HTTPS, enforced before the browser ever makes a first connection. Inclusion is permanent and difficult to reverse. Only submit your domain after you are fully committed to HTTPS across every subdomain, including staging environments.

Ready to Get an A on SecurityHeaders.com?

Security headers are one of the fastest technical wins available on any WordPress site, and one of the most commonly missed. Most sites can implement the core seven headers in under an hour. Getting to an A or A+ on SecurityHeaders.com is a straightforward, measurable improvement that protects your rankings, your users, and your reputation.

At City of Oaks Marketing, technical SEO and WordPress security go hand in hand. We audit security headers as part of every technical SEO engagement, alongside page speed, Core Web Vitals, structured data, and crawlability. If your site is missing headers, or has headers that are present but misconfigured, we will find them and fix them.

Request a Technical SEO Audit and find out exactly where your site stands.

or call 919-200-0201