Red padlock on keyboard

Every WordPress site on the internet is being attacked right now. That's not hyperbole — it's a verifiable fact you can see in the access logs of any production site. Most of the traffic is automated, most of it is junk, and most of it is preventable at the edge before it ever reaches your origin.

Cloudflare's Web Application Firewall is the cheapest, highest-leverage piece of infrastructure for a WordPress site in 2026. Their free tier blocks the obvious stuff; their paid plans add managed rules that catch most of the rest. This article is the exact configuration we deploy on every client site, with the reasoning behind each rule.

What Cloudflare's WAF actually does

The WAF sits between the public internet and your origin server. Every request hits Cloudflare's edge first. Rules examine the request — headers, URL, body, IP, user agent, country, behavior pattern — and decide whether to pass it to your origin, challenge it (CAPTCHA, JavaScript challenge), block it, or rate-limit it.

For WordPress, this matters because the attack patterns are well-known and easy to fingerprint. Cloudflare's managed rules already catch:

  • Common WordPress vulnerability scans (/wp-admin/admin-ajax.php with specific abuse signatures)
  • Plugin-specific CVE exploitation attempts
  • Brute-force login attempts (rate-limited by IP and globally)
  • Malicious file uploads
  • SQL injection patterns

The free tier gets you most of the value. Pro adds the managed rule sets that actually catch attacks, with pricing scoped per zone. Business adds enterprise features that are overkill for most agency clients. Cloudflare's plan page has current pricing — check it against your traffic profile before committing.

The minimum config we run on every WordPress client

This is the bare-minimum ruleset that should be on every WordPress site. We've never had a security incident on a site with this configuration. Every rule below is in the free tier or Pro.

1. Lock down wp-login.php

The single most common attack pattern is brute-force login attempts. The fix is a rate limit:

  • Rule: when URI Path contains /wp-login.php AND Request Method equals POST
  • Rate limit: 5 requests per minute per IP
  • Action: block for 1 hour

A legitimate user typing their password wrong a few times will not hit this limit. An automated brute-forcer will hit it on the first script invocation.

2. Restrict xmlrpc.php

xmlrpc.php is the legacy WordPress XML-RPC endpoint, used for pingback notifications and remote publishing. It's been a vector for both brute-force attacks (because authentication can be batched) and DDoS amplification.

Unless you have a specific app that uses XML-RPC (most clients don't), block it entirely:

  • Rule: when URI Path equals /xmlrpc.php
  • Action: block

If a client uses an external publishing app or pingbacks, allow the specific IP range that needs access.

3. Block direct access to PHP files in wp-content/uploads

A common malware vector is uploading a malicious PHP file disguised as an image, then accessing it directly via URL. Prevent execution at the edge:

  • Rule: when URI Path contains /wp-content/uploads/ AND URI Path ends with .php
  • Action: block

This rule is so high-leverage that the WordPress core team has been talking about doing it at the application level for years. Until they do, the edge is where to enforce it.

4. Geo-block obvious origin countries (with care)

For clients whose business is region-specific, blocking traffic from countries that don't contain customers reduces bot noise significantly. Be careful with this one — false positives are real. Don't block based on stereotypes; block based on traffic patterns.

  • Look at your access logs. Identify countries that generate scan traffic but no legitimate users.
  • Common targets: Russia, China, North Korea, Iran — if you can confirm you have no legitimate users from those geographies.
  • Rule: when IP Country Code is in [list]
  • Action: challenge (not block) — CAPTCHA gives real users an out

For B2B clients with a national footprint (Canadian-only or US-only services), challenging non-domestic traffic eliminates 80%+ of bot noise with minimal collateral damage.

5. Block the obvious bots

There's a category of "good" bots (Googlebot, Bingbot) and a category of "bad" bots (content scrapers, vulnerability scanners). Cloudflare's "Bot Fight Mode" (free) does a decent job; "Super Bot Fight Mode" (Pro) is meaningfully better.

For Pro clients, enable Super Bot Fight Mode and set:

  • Definitely automated: block
  • Likely automated: managed challenge
  • Verified bots: allow

This single setting catches more attacks than any of the custom rules above, because it operates on behavioral fingerprinting that's harder for attackers to evade.

6. Enable the WordPress managed ruleset (Pro)

On Pro plans, Cloudflare exposes a "WordPress" managed ruleset specifically. Enable it. This is where the CVE-specific protections live — WordFence-style virtual patches at the edge.

What we don't do (and why)

Block all admin access except specific IPs. This is secure, but it's a support nightmare. The marketing manager works from a coffee shop, the IP changes, they can't log in. We've moved to MFA + strong passwords + rate-limiting instead. The exception: highly sensitive client sites where admin access is genuinely restricted to a known list — for those, lock it down.

Use a WordPress security plugin. WordPress security plugins (WordFence, Sucuri, etc.) operate at the application level — after the request has already hit your origin and started executing PHP. This means they consume your server's CPU and memory to defend against attacks. The edge is the right place to defend; the application is the wrong place. We don't run security plugins on Cloudflare-protected sites.

Custom regex on bodies for SQL injection patterns. This is a category error. Cloudflare's managed rules already do this, and they update for new attack patterns faster than we ever could. Don't reinvent.

Abstract red network data flow

The performance impact

Running everything above on a typical WordPress site reduces origin traffic by 60-85% during normal operation. This is real money: less CPU, less memory, less database load, and less bandwidth at the origin. For clients on WP Engine or similar managed hosting, this often delays the need to upgrade to higher plans by 6-12 months.

The latency impact: positive. Cloudflare's edge serves cached assets faster than your origin ever could, and the WAF processing time is sub-millisecond for rules that don't trigger. Real users barely notice.

What this doesn't replace

Edge security is one layer. It doesn't replace:

  • WordPress core, plugin, and theme updates — keep them current. We run weekly automated update windows on every client site.
  • Strong admin passwords + MFA — the front line of defense against the credential attacks that do get through.
  • Regular backups — every Rough Works WordPress site has off-host backups every night. WAF rules eventually fail; backups never do.
  • An incident response plan — when something does get through, you need to know what to do.

The point isn't that the WAF makes you invulnerable. It's that the WAF stops 99% of the noise so you can focus your attention on the 1% that gets through. Without it, you spend your time triaging script kiddies.

Where this fits in a wider hosting story

Cloudflare WAF is one piece of the edge security picture. The others — rate limiting at the application layer, WordPress hardening, hosting choice — we've written about elsewhere. For a complete picture of how we approach WordPress operations, see our headless WordPress build pattern — the same security principles apply whether the WordPress front-end is rendering pages or just serving a CMS API.

The configuration above is the floor. Every WordPress site we manage runs at least this. Yours should too.

Keep reading

Work with Rough Works

Need a partner for your next site? We're a Vancouver-based digital agency building websites and AI-enhanced experiences for brands across Canada and the United States. Start a project →