Add Security Headers with Cloudflare Transform Rules

Add HTTP security headers in Cloudflare without touching your server. Includes a safe starting set, a careful HSTS and CSP rollout, and testing steps.

If your website sits behind Cloudflare, you can add security headers from the dashboard. You don't need server access, an .htaccess file or a developer deployment. This guide is for owners and whoever looks after their site.

You will learn how to create the rules, which headers to start with, and how to roll out the two risky ones (HSTS and CSP) without locking visitors out. If you're unsure what each header does, read security headers every small business website needs first. This article covers the "how".

In short: In Cloudflare, open the Rules section, create a Response Header Transform Rule and add one rule per header. Start with the low-risk ones and test after every change. Treat HSTS and Content-Security-Policy as staged projects, not one-click switches.

Before you start

  • Your site is proxied. In DNS, the cloud icon next to your record should be orange ("Proxied"). Headers added in Cloudflare only apply to traffic that passes through Cloudflare.
  • HTTPS works on every page and subdomain you care about. Cloudflare's Full (strict) SSL/TLS mode is the safest target if your server has a valid certificate.
  • You can edit rules on that domain with your Cloudflare login.

Then record what visitors receive today. Open your site in Chrome or Edge, press F12, choose the Network tab, reload, click the first request and read Response Headers. Copy them into a note.

Set static replaces your server's value, leaving one X-Frame-Options: SAMEORIGIN header. Add static appends, so the same header can appear twice as a duplicate.

This matters because a Set static rule (the method used below) replaces your server's value for that header name. An Add static rule appends instead, and can leave you with a duplicate.

Creating a rule

Cloudflare moves menu items around now and then, so if a label differs, look for "Transform Rules". The usual steps are:

Seven steps: select your domain, go to Rules > Overview > Create rule, choose Response Header Transform Rule, name it, match one host, Set static with name and value, then Deploy or save as draft.
  1. Select your domain in the Cloudflare dashboard.
  2. Go to Rules and create a new rule.
  3. Choose Response Header Transform Rule.
  4. Enter a rule name, such as Add nosniff header.
  5. Under When incoming requests match, start narrow, for example only your main site:
(http.host eq "www.yourbusiness.com")
  1. Under Modify response header, choose Set static, then enter the header name and value.
  2. Click Deploy, or save as a draft if you want to come back to it.

We suggest one rule per header, so if something breaks you can switch off just that rule. Widen the match to other hostnames only after the first one is tested, because "all requests" can catch APIs and subdomains you didn't intend. Cloudflare's response header modification documentation lists the available operations and restrictions.

Watch out: Cloudflare also offers a Managed Transform called Add security headers, which switches on a preset group of headers with Cloudflare's own values. That preset includes X-Frame-Options and a referrer policy of same-origin, which differs from the value in the table below, so mixing the two methods can leave you with conflicting settings. Pick one method per header.

A low-risk starting set

HeaderValue to enterCheck after deploying
X-Content-Type-OptionsnosniffScripts and styles still load
Referrer-Policystrict-origin-when-cross-originAnalytics and forms still work
Permissions-Policycamera=(), microphone=(), geolocation=()Allow what you use, e.g. geolocation=(self)
X-Frame-OptionsSAMEORIGINBooking widgets and other embeds

Add them one at a time and test between each. These are low risk on most small business sites, but none is safe everywhere.

HSTS: go slowly

Strict-Transport-Security (HSTS) tells a browser to use HTTPS for your site automatically for a set period (max-age, in seconds). The danger is that browsers remember it.

HSTS rollout: start with max-age=86400, test a few days, raise to max-age=15552000 (about 180 days), add includeSubDomains only when every subdomain works over HTTPS, leave out preload for now.
  • If your certificate expires while HSTS is active, visitors see an error and can't click through to the site.
  • Turning off your Cloudflare rule does not clear what browsers have stored. To reverse HSTS you must serve max-age=0 over valid HTTPS and wait for each browser to receive it.
  • includeSubDomains extends the policy to every subdomain of the host that sent it.

A cautious rollout:

  1. Start with a one-day value: max-age=86400.
  2. Test forms, logins and checkout for a few days.
  3. Raise it to something like max-age=15552000 (about 180 days).
  4. Add includeSubDomains only when every subdomain, including old ones like mail. or shop., works over HTTPS.
  5. Leave out preload for now. It requires a max-age of at least a year plus includeSubDomains, and it is a long-term commitment to HTTPS everywhere.

Cloudflare also has a built-in HSTS setting on its Edge Certificates page, where the duration is chosen in months; 6 months is the closest match to the 180-day step. Choose either that setting or a Transform Rule, so you know which value is being sent. The MDN reference for HSTS explains each directive.

Content-Security-Policy: report first, enforce later

CSP lets you list which sources of scripts, images and frames your pages may use. It is the most powerful header here and the most likely to break something, so use two stages.

Stage 1 Observe: Content-Security-Policy-Report-Only blocks nothing and needs a reporting endpoint. When important pages are quiet, Stage 2 Enforce: Content-Security-Policy with your tuned value.

Stage 1: observe

Create a rule with the header name Content-Security-Policy-Report-Only and a value like this:

default-src 'self'; img-src 'self' data: https:; object-src 'none'; base-uri 'self'

Report-only mode blocks nothing, but it doesn't collect anything on its own either. Per the MDN page for Content-Security-Policy-Report-Only, violations are delivered through the Reporting API, and only when a reporting endpoint is configured (a report-to directive in the policy, matched by a Reporting-Endpoints header). Setting up somewhere to receive reports is a job for a developer or a reporting service, so decide where they will go first.

Keep in mind:

  • The sandbox directive is ignored in report-only policies, so test that separately.
  • Reports only cover pages that get loaded. Test the homepage, contact form, checkout and login on desktop and mobile.

Treat each report as a question: do we actually need this resource? If yes, add its source to the right directive. If you don't recognise it, investigate before loosening the policy. Removing an unused tracker beats widening script-src. The sample above is a starting point and will flag many inline scripts and third-party tools, which is the point of observing.

Stage 2: enforce

When the important pages are quiet, add a second rule named Content-Security-Policy with your tuned value. Expect several passes on sites built with WordPress or similar platforms, where themes, plugins and analytics load from many places.

Removing headers that reveal your stack

Transform Rules can also remove response headers. If your server sends X-Powered-By (which can reveal the language or framework), create a response header transform rule, choose Remove and enter X-Powered-By. This is minor tidying, not protection by itself.

Test after every change

SymptomLikely causeFix
Header doesn't appearRule disabled or match doesn't fitCheck status and hostname/path match
Header appears twiceA rule uses Add staticSwitch to Set static or remove the other source
Wrong valueAnother rule overrides itCheck rule order
Old resultBrowser cacheRetest with dev tools open and Disable cache ticked
Page features breakCSP or framing header too strictDisable that one rule, then tune

After each save:

  1. Load your homepage and a deeper page, then confirm the header in Response Headers on the main document.
  2. Check a redirect, a 404 page and an image or script file. Rules can match these differently.
  3. Click through forms, login, checkout, maps, chat widgets and embedded video.
  4. Look for blocked-resource messages in developer tools once a policy is enforced.

Tip: Keep a note of every rule you add, with the date and its value. When something breaks next month, you'll know what changed.

When Cloudflare isn't the right place

Edge rules suit sites that are fully proxied and want one place for site-wide headers. Set headers at the origin server instead if only part of your traffic is proxied, if your server already sends a carefully tuned CSP, or if headers must vary by page or by signed-in state.

Once your rules are live, the free Safe Scan at pentest.lordevo.com gives an outside view of your site's security headers. It can't test every route or logged-in workflow, so still click through your key pages yourself.

Key takeaways

  • Confirm the site is proxied and HTTPS works before you begin.
  • Create one rule per header, matched to one hostname at first, using Set static and one method per header.
  • Start with nosniff, a referrer policy, a permissions policy and a framing rule.
  • Begin HSTS at one day, raise it gradually, and delay includeSubDomains and preload.
  • Run CSP in report-only mode with a reporting endpoint in place, then enforce.
  • Test after every rule and keep notes so you can undo changes.

FAQ

Do I need a developer to do this?

Not for the simple headers. CSP on a complex site, including setting up a reporting endpoint, is where a developer's help pays off.

Will security headers make my site secure?

No. They add a layer of browser-side protection, but they don't replace updates, strong passwords or backups.

Can I use the same rules for subdomains?

Only once each subdomain has been tested. Widen the match step by step, and remember HSTS includeSubDomains affects all of them at once.

What if my site isn't on Cloudflare?

Set the same headers at your web server, hosting control panel or a plugin. The values and testing advice stay the same.