WordPress Site Health Security Headers Issue

Site Health Security Error

Security headers can be a frequently failed item in WordPress Site Health. The error in Site Health is:

Not all essential security headers are installed
Not all essential security headers are installed

All of these headers can be set at CloudFlare:

  • Upgrade Insecure Requests
  • X-XSS protection
  • X-Content Type Options
  • Referrer-Policy
  • Permissions-Policy
  • HTTP Strict Transport Security

Review site headers using curl

To see what headers are being returned from a website use the following command: curl -I foo.com

curl is a command-line tool for making HTTP/HTTPS requests. The request defaults to https.

  • The -I parameter tells curl to:
  • Send an HTTP HEAD request instead of GET
  • Return headers only
  • Skip downloading the response body (HTML, JSON, etc.)
curl command
curl command

Cloudflare – Add a Response Header Transform Rule

  • Log in to Cloudflare and select a domain.
  • Go to Rules → Overview.
  • Click Create rule and choose Response Header Transform Rules
  • Give the rule a clear name. Example: Security Headers (WordPress Site Health)
  • Set All incoming requests to Apply this rule to all requests.
  • Under Then, choose Set static and enter the Header name and Value you want to add or modify.
  • Click Set new header to add additional headers if needed
  • Click Deploy to activate the rule.
Response Header Transform Rule
Response Header Transform Rule

Recommended Header Name and Value Settings

Header name Value
Set static Content-Security-Policy upgrade-insecure-requests
Set static Permissions-Policy geolocation=(), microphone=(), camera=()
Set static Strict-Transport-Security max-age=31536000; includeSubDomains; preload
Set static X-Content-Type-Options nosniff
Set static X-XSS-Protection 1; mode=block
Set static strict-origin-when-cross-origin Referrer-Policy

Settings Explanation

  • Content-Security-Policy: upgrade-insecure-requests — Automatically upgrades all HTTP resource requests to HTTPS to prevent mixed-content issues and improve transport security.
  • Permissions-Policy: geolocation=(), microphone=(), camera=() — Explicitly disables access to geolocation, microphone, and camera APIs for the site and all embedded content.
  • Strict-Transport-Security: max-age=31536000; includeSubDomains; preload — Forces browsers to use HTTPS only for one year for the site and all subdomains and signals eligibility for browser HSTS preload lists. (Note: the header name should be Strict-Transport-Security*.)*
  • X-Content-Type-Options: nosniff — Prevents browsers from MIME-sniffing responses and forces them to respect the declared Content-Type.
  • X-XSS-Protection: 1; mode=block — Enables the browser’s legacy XSS filter and blocks rendering of the page if an attack is detected.
  • Referrer-Policy: strict-origin-when-cross-origin — Sends the full referrer URL for same-origin requests but only the origin for cross-origin requests, and nothing when downgrading from HTTPS to HTTP.⠀

Confirm Response Header Transform Rule

To confirm the new headers are being returned use the curl command from earlier:

curl -I foo.com

ColdFusion Scheduled Tasks Failing with 403 Forbidden Error (Cloudflare Issue)

My company recently experienced an issue where all of the scheduled tasks in CFADMIN were failing. The first step I took to troubleshoot the issue was to check the scheduler.log log file. Each task had 2 lines in the log file. The first line indicated that the task had been triggered. The second line indicated an error of 403 Forbidden.

"Information","DefaultQuartzScheduler_Worker-3","11/08/24","07:00:00","","Task DEFAULT.NIGHTLY CLEANUP JOB triggered."
"Error","DefaultQuartzScheduler_Worker-3","11/08/24","07:00:00","","403 Forbidden"

Since no permissions had been changed on the server this was a perplexing error. The next step that I took was to execute one of the task URLs from a web browser on the sever. The task completed successfully. This led me to try to obtain more information about CFADMIN running the task so I enabled Save output to file under the Publish section of the Scheduled Task and specified a file to output the result.

CFADMIN Scheduled Task Log to File
CFADMIN Scheduled Task Log to File

Once this setting was in place I executed the task again from CFADMIN > Server Settings > Scheduled Tasks and checked the log file. The log file contained the text error code: 1010.

CFADMIN Scheduled Task Log to File result
CFADMIN Scheduled Task Log to File result

Researching error code: 1010 led me to several articles regarding Cloudfare blocking access to a site based on the browser signature.

This narrowed the issue to either an issue with Cloudfare or the task not running correctly when executed by ColdFusion. I decided to try execute the URL from a ColdFusion cfhttp call using the following basic script.

The task completed successfully when called from cfhttp. Below is a dump of the result:

Dump of cfhttp
Dump of cfhttp

The issue therefore seemed to be narrowed to the fact that Cloudfare was rejecting calls to URLs from the CFADMIN (apparently based on an issue with the browser signature). The browser signature is examined at Cloudfare by a Browser Integrity Check (BIC) as a component of a WAF.

A WAF or web application firewall helps protect web applications by filtering and monitoring HTTP traffic between a web application and the Internet. It typically protects web applications from attacks such as cross-site forgery, cross-site-scripting (XSS), file inclusion, and SQL injection, among others.

Read more about Cloudfare’s WAF.

You can create a custom WAF rule to turn off the Browser Integrity Check (BIC). First, use the Go to navigation to search for WAF and choose Security | WAF | Custom Rules:

WAF Go to
WAF Go to

Next, click the Create rule button to begin. Our solution will use the following settings to disable the BIC on requests only from our server IP to scripts residing in a certain directory:

  • For the `Field` select `IP Source Address`, for `Operator` select `equals` and enter the IP address of your server as the `Value` (this will allow the rule to only apply to requests from your server).
  • Click the `And` button to add another row.
  • For the `Field` select `URI Path`, for `Operator` select `wildcard` and and enter the directory of your scheduled tasks as the `Value` (this will allow a single rule to apply to multiple task scripts in the directory). Notice the directory uses a wildcard at the end `/jobs/*`.
  • For the `Choose action` select `skip`.
  • Select `On` for `Log matching requests`.
  • Under `WAF components to skip` check `Browser Integrity Check` (you may need to click the `More components to skip` link to locate it).
  • Click the `Deploy` button to enable the rule immediately.
WAF Create rule
WAF Create rule

You can view the logging of the Firewall events. First, use the Go to navigation to search for Events and choose Security | Events:

Events Go to
Events Go to

As you can see the previously blocked requests via CFADMIN are now allowed at Cloudfare via a Skip action using Custom rules.

Firewall events
Firewall events