security DigitalFixes
Screenshot illustrating Security Headers on WordPress with CSP and X-Frame-Options settings on a security dashboard.

Security Headers on WordPress: Best Settings for CSP, X-Frame-Options, and More

April 9, 2026

Security headers on WordPress are one of the fastest wins you can make after a malware cleanup—and they reduce entire classes of attacks, even when your WordPress core is fully patched. Here’s the direct answer: use a strict Content-Security-Policy (CSP) first, add X-Frame-Options (or its CSP equivalent), and then tighten the rest (HSTS, Referrer-Policy, Permissions-Policy) with testing instead of guessing.

In 2026, hackers still rely on the same weaknesses: clickjacking via iframes, script injection via compromised plugins or supply-chain scripts, and mixed-content tricks during poor TLS setups. I’ve seen clean sites re-compromised because the admin assumed “updates fixed it,” but the browser kept trusting risky behaviors.

This guide gives you best settings you can apply to WordPress, including practical CSP templates, common exceptions for popular plugins, and a safe testing workflow using tools like Google Lighthouse, SecurityHeaders.com, and browser DevTools.

What security headers do (and why WordPress owners underestimate them)

Security headers are browser instructions that tell the visitor’s browser how to treat your site. They’re not a replacement for patching or malware removal, but they’re a strong “seatbelt” when something goes wrong.

For WordPress, the biggest misconception is that hardening is only about PHP updates and plugin hygiene. In reality, a compromised site often still serves pages correctly—so the payload works only if the browser permits it.

Here’s the practical benefit: when an attacker tries to inject JavaScript through an exploited endpoint, a well-tuned CSP can stop the browser from executing it. When an attacker tries to frame your login page to steal credentials, X-Frame-Options (or a CSP frame-ancestors rule) blocks the rendering.

Quick glossary you’ll see in WordPress security headers

  • CSP (Content-Security-Policy) refers to the policy that controls which sources can load scripts, styles, images, and more.
  • X-Frame-Options tells the browser whether your pages can be embedded in iframes.
  • HSTS forces HTTPS-only behavior for a domain.
  • Referrer-Policy controls how much referrer information is sent to other sites.
  • Permissions-Policy reduces what browser features are available (camera, geolocation, etc.).

Best settings for CSP on WordPress (the policy most sites get wrong)

CSP is the cornerstone of security headers on WordPress because it directly limits script execution and exfiltration paths. The mistake I see most is copying a “strict CSP” from a blog and breaking the entire site in an afternoon.

CSP works best when you move in stages: Report-Only first, then enforcement after you’ve captured and approved legitimate sources.

Step-by-step: deploy CSP safely in 2026

  1. Start with Report-Only: Use Content-Security-Policy-Report-Only so violations are logged instead of blocked.
  2. Collect violations for 3–7 days: Include business hours and traffic spikes. On small-business sites, I aim for at least 1000–5000 pageviews worth of logs.
  3. Convert to Enforce: Once you’re confident, switch to Content-Security-Policy.
  4. Lock down gradually: tighten script-src and style-src last, because WordPress plugins frequently rely on third-party scripts.

Baseline CSP template for WordPress

This is a strong starting point for many WordPress sites. You will still need to add exceptions for your theme and plugins (analytics, chat widgets, video embeds).

Content-Security-Policy: default-src 'self';
base-uri 'self';
object-src 'none';
img-src 'self' data: https:;
script-src 'self' 'unsafe-inline' https:;
style-src 'self' 'unsafe-inline' https:;
font-src 'self' https: data:;
connect-src 'self' https:;
frame-src https:;
frame-ancestors 'self';
form-action 'self';
upgrade-insecure-requests;
block-all-mixed-content;

Original insight from real-world work: for WordPress, I often begin with script-src allowing 'unsafe-inline' for the short “stabilization” phase. Then I replace inline needs by using plugin settings to disable inline JS where possible, and by whitelisting nonces if your environment supports it. Trying to eliminate inline scripts on day one is the fastest way to create a support ticket.

More strict CSP option (when you can eliminate inline scripts)

If you’re able to reduce inline scripts/styles, a stricter approach is possible. This is common on sites that use properly built themes and minimize legacy plugins.

Content-Security-Policy: default-src 'self';
base-uri 'self';
object-src 'none';
img-src 'self' data: https:;
script-src 'self' https: 'nonce-REPLACE_WITH_NONCE';
style-src 'self' https: 'nonce-REPLACE_WITH_NONCE';
font-src 'self' https: data:;
connect-src 'self' https:;
frame-src https:;
frame-ancestors 'self';
form-action 'self';
upgrade-insecure-requests;
block-all-mixed-content;

Note: nonces require server-side logic. If you’re using a header plugin that can’t inject nonces, stick with staged enforcement rather than forcing nonces.

CSP exceptions you may need for common WordPress features

  • Analytics (Google Analytics, etc.): add their domains to script-src and connect-src.
  • Tag managers: allow the tag manager container domain (and associated script endpoints) in script-src.
  • Video embeds: allow YouTube/Vimeo in frame-src and sometimes img-src.
  • CDNs for fonts and images: add CDN domains to font-src and img-src.
  • Chat widgets: allow their JS domains in script-src and XHR endpoints in connect-src.

If you see broken layouts after CSP enforcement, use browser DevTools console logs to pinpoint the exact directive blocked. That’s faster than blindly broadening the policy.

X-Frame-Options and frame-ancestors: clickjacking protection done right

WordPress login page shown inside an iframe, illustrating clickjacking protection
WordPress login page shown inside an iframe, illustrating clickjacking protection

For clickjacking defense, prioritize frame control. X-Frame-Options is the classic header, while CSP’s frame-ancestors is the modern, flexible approach.

Best practice in 2026: set both, but keep them consistent to avoid confusion.

Recommended X-Frame-Options values

  • X-Frame-Options: DENY blocks embedding from any site.
  • X-Frame-Options: SAMEORIGIN allows embedding only from your own origin.

On most business WordPress sites that don’t need embedding, DENY is the cleanest choice. If you publish pages intended for embedding (rare for small business), use SAMEORIGIN.

Pair it with CSP frame-ancestors

In your CSP, use this directive:

frame-ancestors 'self';

Alternatively, if you truly want no framing at all:

frame-ancestors 'none';

What most people get wrong about X-Frame-Options

The most common mistake is applying it only to specific templates (like the homepage), leaving login or admin pages exposed. Another issue is forgetting that some security header plugins only run on cached responses or only for HTML.

When I audit a site, I verify the header is present for:

  • Public pages (homepage, posts, product/services pages)
  • Login page
  • Any endpoint that includes sensitive actions (password reset, account details)

Additional high-impact security headers for WordPress (HSTS, Referrer-Policy, and more)

After CSP and framing, the next biggest improvements come from transport, metadata, and browser feature controls. These headers reduce downgrade and information leaks and help limit damage from future vulnerabilities.

HSTS (Strict-Transport-Security)

HSTS forces HTTPS by telling browsers to never use HTTP for your domain for a period.

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

Important limitation: only enable preload if you’re certain your domain supports HTTPS everywhere, including subdomains. Otherwise, you can lock yourself out from HTTP transitions. As a compromise, start with a shorter max-age (for example, 90 days) before moving to 1 year.

Referrer-Policy

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

This keeps referrer data useful while reducing unnecessary exposure when users navigate to other origins.

Permissions-Policy

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

Tailor this for your site. If your WordPress site doesn’t use these features, disabling them is a straightforward win.

Base security trio: nosniff, XSS protection, and referrer

Modern browsers respect these ideas, but they’re still worth setting correctly.

  • X-Content-Type-Options: nosniff
  • Cross-site scripting protection: most legacy X-XSS-Protection headers are not consistently supported anymore, so don’t rely on them as your main defense.
  • Referrer-Policy: choose a strict option as above.

For content type issues, nosniff helps browsers treat declared MIME types correctly instead of guessing.

Download/file hardening headers

If you serve user-facing downloads (PDFs, ZIPs, documents), add these where your stack supports it:

  • X-Content-Type-Options: nosniff
  • Make sure your server sends correct MIME types (headers won’t fix bad content-type detection)

How to implement security headers on WordPress (without breaking plugins)

Developer checking security headers and CSP settings on a web server dashboard
Developer checking security headers and CSP settings on a web server dashboard

Implementation is where most security headers projects fail. If your header solution conflicts with caching or with a CDN/WAF, you’ll see inconsistent results between pages.

Best ways to add headers (ranked for reliability)

Method Best for Pros Watch-outs
Web server config (Nginx/Apache) Stable, uniform header coverage Fast, consistent, works with all routes Requires server access
CDN/WAF header rules (Cloudflare, Fastly, etc.) Managed security and edge enforcement Global enforcement, easy to audit Must align with origin and avoid double headers
WordPress header plugins Non-technical access Simple UI, quick iteration May miss cached pages or REST endpoints

My preferred workflow when a site already has plugins

I usually treat security header rollout like a change-management task:

  1. Check what headers already exist using SecurityHeaders.com or curl -I.
  2. Deploy CSP in Report-Only first.
  3. Wait a few days and review logs for blocked sources.
  4. Disable unnecessary plugins (especially those injecting scripts) before tightening CSP.

If your WordPress site is currently under active attack, fix the infection first. Headers can reduce the blast radius, but they’re not a malware cleanup tool.

For context, you may find it useful to pair this with our guide on WordPress malware removal steps and our WordPress hardening checklist. On compromised sites, I often see security headers missing entirely or set too loosely, which gives injected code a clean path to execute.

People Also Ask: common questions about security headers on WordPress

Should I add CSP, X-Frame-Options, and HSTS all at once?

No—roll out CSP first, then the rest. In my experience, CSP enforcement causes the majority of breakages because it interacts with third-party scripts and inline assets. Start with CSP in Report-Only, then introduce enforcement after you’ve validated functionality.

What if my WordPress site uses inline styles and scripts?

Accept it temporarily, then reduce it. Many themes and plugins still rely on inline JS/CSS. Use staged CSP: allow 'unsafe-inline' during the stabilization window, then remove inline allowances plugin-by-plugin.

Can CSP break my login page or password reset?

It can, if you have blocked the scripts used by those forms. Login and password reset pages often load different assets than the homepage. That’s why you should test all auth flows after enforcement, not just the landing pages.

Do security headers stop malware?

They don’t remove malware, but they can stop payload execution. If malware has already altered files or injected persistent payloads, you need cleanup and patching. Headers reduce the chance that an injected script runs, but they won’t repair compromised PHP, backdoors, or injected templates.

How do I test CSP and X-Frame-Options correctly?

Use both automated tools and manual checks. Lighthouse and SecurityHeaders.com show coverage, but browser console logs show what’s blocked. Also verify that the headers appear on the exact pages you care about (home, post pages, login, account pages, and any forms).

Real-world scenarios: what headers prevent on compromised WordPress sites

I’ve seen attackers succeed even when the site “looks fine”—because the attack is designed to rely on permissive browser behavior. Here are three realistic patterns from incidents I’ve handled.

Scenario 1: Clickjacking on the login page

A compromised or malicious actor targets a WordPress login page by embedding it inside an iframe on a phishing domain. Without X-Frame-Options (or CSP frame-ancestors), the victim can be tricked into typing credentials while the attacker overlays a fake form.

After adding X-Frame-Options: DENY and frame-ancestors 'self', we stop framing entirely. The phishing page still loads, but the real login form can’t render inside the frame.

Scenario 2: Injected JavaScript through a vulnerable plugin

On one small business WordPress site, the attacker injected JavaScript into page output using a compromised plugin template. The malware stayed mostly invisible because content was only altered in the footer and executed only when a script tag was allowed.

Once CSP enforcement blocked unauthorized script sources, the payload stopped executing in the browser. Cleanup still had to remove the infected plugin files, but the header changes reduced repeat exploitation while we restored integrity.

Scenario 3: Broken CSP after “security plugin” changes

Another time, a client enabled a “security headers” plugin that added CSP but accidentally removed analytics allowances. The site didn’t get hacked again, but conversion tracking broke immediately and they thought the site was down.

This is why I recommend Report-Only and a careful exception list. A good CSP rollout improves security and avoids surprise regressions.

If you’re actively responding to an incident, our threat alert and response checklist complements these header steps with the order of operations (cleanup, verify, then harden).

Recommended security header set for WordPress (copy-ready starting point)

Below is a practical “starter set” you can adapt. Treat it as a baseline and adjust third-party domains based on your actual plugin/theme behavior.

Header cheat sheet (starter values)

Header Value (starter) Purpose
Content-Security-Policy default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' https: data:; connect-src 'self' https:; frame-src https:; form-action 'self'; upgrade-insecure-requests; block-all-mixed-content; Controls what can load and execute
X-Frame-Options DENY (or SAMEORIGIN) Prevents clickjacking
Strict-Transport-Security max-age=31536000; includeSubDomains (add ; preload only if ready) Forces HTTPS
X-Content-Type-Options nosniff Prevents MIME sniffing
Referrer-Policy strict-origin-when-cross-origin Limits referrer leakage
Permissions-Policy geolocation=(), microphone=(), camera=(), payment=() Restricts browser features

Where to start if you want the safest path

  1. Deploy X-Frame-Options immediately (DENY). This usually doesn’t break functionality for standard sites.
  2. Enable HSTS carefully with a safe max-age first if you’re unsure about subdomains.
  3. Roll CSP in Report-Only for a week, then enforce.
  4. Validate all key pages: homepage, 3–5 content pages, contact form, checkout (if any), login, password reset.

Validation checklist: prove your headers work (not just that they exist)

Having a header is not enough—you need to confirm it matches your page behavior. Here’s a validation workflow I use during engagements.

Step 1: verify headers are present on every critical URL

  • Use curl -I https://example.com to check header presence.
  • Test key endpoints separately: /wp-login.php, /wp-admin/, password reset, account pages.

Step 2: run Lighthouse and check security-related audits

Lighthouse doesn’t replace manual testing, but it quickly flags missing basics like mixed content behavior and header issues.

Step 3: check browser console for CSP violations

When CSP blocks content, the console shows which directive and which URL was blocked. That’s your checklist for the next CSP adjustment.

Step 4: regression-test plugin-dependent features

  • Contact forms and captcha widgets
  • Analytics dashboards and tag manager scripts
  • Video embeds and social share widgets
  • Any custom scripts added via theme settings

Conclusion: your next best step for security headers on WordPress

Security headers on WordPress pay off fastest when you implement them in the right order: set clickjacking protection (X-Frame-Options / frame-ancestors), then roll out CSP in Report-Only, then add HSTS, Referrer-Policy, and Permissions-Policy.

If you’re dealing with a suspected compromise, don’t start by tightening CSP alone. Start with cleaning and verifying integrity first, then harden. After that, follow the validation checklist so you don’t trade one risk for another—like breaking login or analytics.

If you want a practical path, choose one theme-compatible CSP baseline, deploy it in Report-Only, review violations for 3–7 days, and enforce once the console is quiet. That approach consistently improves security without turning your WordPress site into a troubleshooting project.

Featured image alt text suggestion (for your CMS): “Security headers on WordPress showing CSP and X-Frame-Options settings on an HTTPS site.”