If you have ever looked at your Cloudflare firewall events log, you have probably seen a wall of blocked requests hitting paths like /.env, /wp-config.php, /xmlrpc.php, or /backup.sql. These are not real visitors. They are automated scanners running around the clock, probing millions of websites simultaneously looking for exposed credentials, unprotected admin panels, and sensitive files left in public directories.
Every one of those requests costs your server something. It processes the request, checks the path, returns a 403 Forbidden response, and moves on. Multiply that by hundreds or thousands of requests per day and you have a real resource drain, and on shared hosting that translates directly into slower response times, throttling, and errors for your real visitors. Cloudflare can stop every single one of those requests at the edge before they ever reach your server.
What Is a 403 Error?
Why Bots Target These Paths
Scanners are not targeting your site specifically. They scan every IP address and every domain they can find, running through a checklist of known vulnerable paths. The same script that hit your site this morning hit ten thousand other sites the same way.
What they're looking for falls into a few categories:
Credential files
.env, wp-config.php, credentials.json, authorized_keys. If these are publicly accessible, the scanner finds your database passwords and API keys in plain text.
Database backups
backup.sql, database.sql, db.sql. Developers sometimes export a database backup to the web root and forget to remove it. Scanners know this and check for it constantly.
Admin interfaces
/phpmyadmin, /adminer.php, /wp-admin/install.php. Exposed database admin tools are a direct path to full site compromise.
Server config files
.htaccess, .htpasswd, /server-status. These reveal server configuration, directory structure, and in some cases password hashes.
Source control
/.git/, /.svn/. An exposed git directory lets an attacker download your entire codebase and commit history, including any secrets ever committed to the repo.
Framework probes
/_ignition/ (Laravel RCE), /actuator/env (Spring Boot), /api/env, /api/config. Framework-specific paths that can expose environment variables or enable remote code execution.
How Cloudflare Stops Them
Cloudflare sits between the internet and your server. Every request hits Cloudflare's network first. When you add a WAF Custom Rule with a Block action, Cloudflare evaluates that rule on every incoming request before anything reaches your server. If the request matches a blocked path, the connection is terminated at Cloudflare's edge. Your server never sees it.
Rule Order Matters
If you already have an "Allow Good Bots" rule that uses a Skip action, your block rule needs to be positioned above it in the rule list. A Skip rule tells Cloudflare to stop evaluating rules for that request, which means if the allow rule fires first, good bots will bypass your block rule entirely. Put the block rule first so sensitive path requests get blocked regardless of who is making them.
To reorder rules: go to Security > WAF > Custom Rules and drag the block rule to the top of the list.
Wordpress vs. Static Sites
If your site runs on WordPress, do not add a blanket contains ".php" block. WordPress needs PHP to function, and blocking all .php requests will lock visitors and you out of the site. Instead, target specific dangerous PHP paths like /xmlrpc.php, /wp-config.php, /adminer.php, and similar. The rule below is designed to work safely for both WordPress and non-PHP sites.
The Sensitive Path Block Rule
Block Sensitive Path Probes
✗ BlockThis rule blocks requests targeting sensitive file paths, backup files, admin tools, source control directories, and server-side scripts that should never be publicly accessible. It covers the most common paths targeted by automated scanners and security bots.
What it blocks
- Environment and credential files (
.env,credentials.json) - Database backups (
.sql,.zip,.tar) - WordPress sensitive paths (xmlrpc, wp-config, adminer)
- PHP, ASP, JSP, and CFM scripts (on non-PHP sites)
- Git, SVN, and Mercurial directories
- Admin interfaces (phpMyAdmin, Adminer)
- Framework probe paths (Laravel Ignition, Spring Boot actuator)
- Server config files (.htaccess, server-status)
- CI/CD config files with potential secrets (.yml, .yaml)
Why block instead of challenge
A Managed Challenge makes sense for ambiguous traffic where you want to allow real humans through. These paths are different: no real visitor ever needs to access /backup.sql or /.env. The request is either a scanner, a misconfigured tool, or someone actively probing for vulnerabilities. There is no legitimate use case to protect, so a hard block is the right action.
PHP Files on Non-PHP Sites
If your site is built on Astro, Hugo, Next.js, or any other non-PHP framework, you can add (http.request.uri.path contains ".php") to the rule. Your site generates zero PHP files, so any request for a .php path is 100% a scanner. This single line replaces dozens of specific WordPress path checks and catches every new PHP probe path scanners invent.
Skip this addition if your site runs WordPress or any PHP-based CMS. Use the specific path blocks in the rule below instead.
Expression
(http.request.uri.path eq "/readme.html") or (http.request.uri.path eq "/license.txt") or (http.request.uri.path eq "/wlwmanifest.xml") or (http.request.uri.path eq "/error_log") or (http.request.uri.path eq "/.htaccess") or (http.request.uri.path eq "/.htpasswd") or (http.request.uri.path eq "/server-status") or (http.request.uri.path eq "/server-info") or (http.request.uri.path eq "/.DS_Store") or (http.request.uri.path contains ".sql") or (http.request.uri.path contains ".zip") or (http.request.uri.path contains ".tar") or (http.request.uri.path contains ".log") or (http.request.uri.path contains ".env") or (http.request.uri.path contains ".bak") or (http.request.uri.path contains ".key") or (http.request.uri.path contains ".tfstate") or (http.request.uri.path contains ".yaml") or (http.request.uri.path contains ".yml") or (http.request.uri.path contains "credentials.json") or (http.request.uri.path contains "authorized_keys") or (http.request.uri.path contains "/.git/") or (http.request.uri.path contains "/.svn/") or (http.request.uri.path contains "/.hg/") or (http.request.uri.path contains "/.ssh/") or (http.request.uri.path contains "/actuator/") or (http.request.uri.path contains "/_ignition/") or (http.request.uri.path contains "/vendor/phpunit/") or (http.request.uri.path contains "/storage/logs/") or (http.request.uri.path contains "/wp-json/wp/v2/users") or (http.request.uri.path contains "/phpmyadmin") or (http.request.uri.path contains "/pma/") or (http.request.uri.path contains "/administrator/") or (http.request.uri.path contains "/cgi-bin/") or (http.request.uri.path contains "/swagger") or (http.request.uri.path contains "/api-docs") or (http.request.uri.path contains "/api/env") or (http.request.uri.path contains "/api/config") or (http.request.uri.path contains "/config.json") or (http.request.uri.path contains "firebase/init") or (http.request.uri.path contains "docker-compose") or (http.request.uri.path contains "etc/passwd") or (http.request.uri.path contains "proc/self/") or (http.request.uri.query contains "author=")
Adding the PHP Block for Non-PHP Sites
If your site does not use PHP, add these lines to the expression above. They replace the individual WordPress path checks and catch everything in one shot:
(http.request.uri.path contains ".php") or (http.request.uri.path contains ".asp") or (http.request.uri.path contains ".jsp") or (http.request.uri.path contains ".cfm")
Reading the Results in Cloudflare
Once the rule is active, go to Security > Events in your Cloudflare dashboard. You will see every request that matched the rule, the IP address it came from, the path it requested, and the action taken. Within the first few hours you will likely see dozens or hundreds of blocked scanner requests that were previously hitting your server.
Each blocked event is a request your server did not have to process. Over time this adds up to real resource savings, especially on shared hosting plans where CPU and memory limits directly affect site performance.
Watch for False Positives on Day One
Review the events log after enabling the rule and check that no legitimate services are getting blocked. Things like uptime monitors, CI/CD tools, or third party integrations that POST to API endpoints could occasionally match a rule pattern. If something legitimate gets blocked, add its IP to your Allow Good Bots rule or adjust the specific condition that is matching.
The block rule above handles path-level probing. For more comprehensive protection including aggressive crawler blocking, VPN challenges, cloud provider filtering, and TOR blocking, see the full five-rule set: Best Cloudflare WAF Rules V3. That post covers everything you need to lock down a client site on any Cloudflare plan.
Rather have us set it up for you?
We configure Cloudflare WAF rules, DNS, page rules, and security settings for agency clients every week. You get a properly configured setup without spending your afternoon on it.
White label friendly. We work directly in your client's Cloudflare account, never in yours.
See Cloudflare Support Services- ✓ WAF rules and firewall setup
- ✓ DNS configuration and migration
- ✓ SSL and HTTPS troubleshooting
- ✓ Page rules and cache settings
- ✓ Bot and attack response