Cloudflare Automation Starts Here: 6 Zone Config Messes to Find First
Somewhere in your Cloudflare dashboard there's a page rule from 2021. It forwards something, or bypasses cache for something, or turns off security for a path that may not exist anymore. Nobody remembers who created it. Nobody knows what breaks if it goes. So it stays, rule 7 of 23, matching (or not matching) production traffic on every request.
That rule is why most Cloudflare automation efforts stall before they start. You can't automate a zone you don't understand, and after a few years of hand edits most zones are archaeology: layered rules, unowned DNS records, WAF exceptions that outlived their incidents, and settings that drifted apart between zones that were meant to be identical.
This guide maps the six places Cloudflare configuration rots, how each one happens, and a real command or dashboard path to detect it. Everything runs read-only against the Cloudflare API with a scoped token. Nothing here changes your zones.
01Rules
Legacy page rules
Ordered, first-match-wins, and stacked under modern Rules nobody reconciled.
02DNS
Unowned records
Released IPs, abandoned SaaS CNAMEs and TXT records for forgotten tools.
03WAF
Permanent exceptions
Skip rules added during an incident that outlived it by years.
04Settings
Zone drift
Zones that are "the same" with different SSL modes and TLS minimums.
05Events
Unread feed
Blocks and challenges logged daily and reviewed after incidents only.
06Signals
Unwatched edge
Origin 52x errors, cert expiry and config changes with no alert on them.
For the commands below, set three environment variables: CF_API_TOKEN (create a read-only token under My Profile → API Tokens), ZONE_ID and ACCOUNT_ID (both on the zone's Overview page, right sidebar).
1. Page rules nobody dares touch
What it is. Page Rules were Cloudflare's original per-URL configuration, and Cloudflare has been migrating them to modern Rules (Redirect Rules, Cache Rules, Configuration Rules) since 2024. Most zones older than a couple of years carry both generations: legacy page rules underneath, modern rules on top, with different matching and ordering semantics.
Why it happens. Page rules are ordered and first-match-wins, so the safe move was always to add a new rule rather than edit an old one. Multiply that by every redirect campaign, cache experiment and "turn off security here for now" incident since the zone was created.
How to detect it. Dump every active page rule with its target, actions and last-modified date:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/pagerules?status=active" \
-H "Authorization: Bearer $CF_API_TOKEN" | \
jq '.result[] | {id, target: .targets[0].constraint.value,
actions: [.actions[].id], modified_on}'
Then list the modern rulesets living alongside them:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets" \
-H "Authorization: Bearer $CF_API_TOKEN" | \
jq '.result[] | {name, phase, last_updated}'
Any page rule untouched for over a year belongs in the migration review. In the dashboard, compare Rules → Page Rules with Rules → Overview.
Typical impact. The direct cost is incident time. Stacked rules with overlapping URL patterns are a classic source of "cache didn't purge" and "redirect loop in production" tickets, and the debugging routinely takes half a day because nobody knows which of 20 rules fired.
2. DNS records without owners
What it is. A records pointing at IPs released years ago. CNAMEs targeting SaaS trials the company abandoned. TXT verification records for tools nobody uses. A busy zone collects hundreds of records, and typically nobody can say who owns half of them.
Why it happens. Adding a record takes 30 seconds and unblocks someone right away. Deleting one has unknown downside, so nothing gets deleted. DNS records have no owner field and no expiry, and marketing, engineering and IT all write to the same zone.
How to detect it. Export the full record set and sort by last-modified:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?per_page=500" \
-H "Authorization: Bearer $CF_API_TOKEN" | \
jq -r '.result[] | [.type, .name, .content, (.proxied|tostring), .modified_on] | @tsv' | \
sort -t$'\t' -k5
Flag three things. Unproxied A and AAAA records exposing origin IPs that should sit behind the proxy. CNAMEs pointing at third-party hostnames that no longer resolve (dig each target: a dangling CNAME to a deprovisioned SaaS endpoint is the setup for a subdomain takeover). And anything untouched for two years or more with no owner anyone can name.
Typical impact. Dangling records are a real security exposure, not clutter. Subdomain takeover through abandoned CNAMEs remains one of the most commonly reported findings in bug bounty programs.
3. WAF exceptions that never expire
What it is. WAF rules cut both ways. Custom rules block traffic; skip rules and exceptions let it through. During an incident (a false positive blocking a customer, a partner integration tripping a managed rule) someone adds a skip. The incident ends. The skip stays, permanently exempting an IP range, path or user agent from inspection.
Why it happens. Exceptions are created under pressure and removed by nobody. There's no expiry on a WAF exception, and six months later nobody remembers whether the partner still needs it.
How to detect it. Pull the zone's custom WAF rules and isolate anything with a skip action:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_request_firewall_custom/entrypoint" \
-H "Authorization: Bearer $CF_API_TOKEN" | \
jq '.result.rules[] | select(.action == "skip") |
{description, expression, last_updated}'
In the dashboard: Security → WAF → Custom rules, plus the exceptions under the managed rules tab. Review every skip against one question with a current answer: what breaks today if this is removed?
Typical impact. Each stale exception is an unmonitored hole in the exact layer you deployed to be monitored. Teams doing a first review typically find that a meaningful minority of their WAF rules, often a quarter or more, reference IPs, paths or partners that no longer exist.
4. Settings drift between zones
What it is. You run 12 zones that are "configured the same." They aren't. One is on SSL mode Full while the rest are Full (strict). Two allow TLS 1.0 because a legacy client needed it in 2022. Browser Integrity Check is off on the zone where someone once debugged a webhook.
Why it happens. Zone settings are edited one toggle at a time, usually during an incident, and there's no built-in "diff these zones" view. Every hand edit is a fork.
How to detect it. Snapshot each zone's settings to a file and diff them:
for Z in $ZONE_A $ZONE_B; do
curl -s "https://api.cloudflare.com/client/v4/zones/$Z/settings" \
-H "Authorization: Bearer $CF_API_TOKEN" | \
jq -r '.result[] | [.id, (.value|tostring)] | @tsv' | sort > "settings-$Z.tsv"
done
diff settings-$ZONE_A.tsv settings-$ZONE_B.tsv
Start with the security-relevant differences: ssl (anything below strict means Cloudflare doesn't validate your origin certificate), min_tls_version, always_use_https and security_level.
Typical impact. Drift turns every incident into a scavenger hunt: it works on zone A, fails on zone B, and nobody knows why. The weakest zone also sets your real security posture, however well the flagship zone is configured.
5. Security events nobody reviews
What it is. Cloudflare logs every WAF match, challenge and block to Security → Events, with retention that depends on plan, and the same data is queryable through the GraphQL Analytics API in the firewallEventsAdaptive dataset. On most accounts nobody has opened it since the last incident.
Why it happens. The WAF is sold as set-and-forget, and on a quiet day the feed looks like noise. But the feed is where you'd see a credential-stuffing run being challenged, a scanner mapping your API, or your own false positives blocking real customers, days before any of them becomes a ticket.
How to detect it. Open Security → Events, set the range to the longest your plan allows, and group by rule. Two findings matter: rules firing thousands of times (either an attack worth moving from challenge to block, or a false positive quietly hurting users), and managed rules that never fire (candidates to tighten). Ten minutes a week is enough. The problem is that nobody's calendar has those ten minutes.
Typical impact. An unread WAF feed is how teams learn about a three-week-old credential-stuffing campaign from their users instead of their firewall.
6. The signals that matter, unwatched
What it is. Four things on Cloudflare deserve immediate attention: origin errors (edge status codes 520 to 526 mean Cloudflare can't talk to your origin properly), WAF event spikes, certificate expiry on the origin and on edge certificate packs, and unexpected DNS or configuration changes.
Why it happens. Teams alert heavily on their origin infrastructure and not at all on the layer in front of it. Cloudflare will happily serve 526 (invalid origin certificate) to every visitor while your origin dashboards stay green.
How to detect it. Origin errors: Analytics & Logs → Traffic, filtered to edge status codes 520 to 526. Certificate expiry:
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/ssl/certificate_packs" \
-H "Authorization: Bearer $CF_API_TOKEN" | \
jq '.result[] | {type, status, expires_on: .certificates[0].expires_on}'
Unexpected changes: the audit log records every change with actor and timestamp:
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/audit_logs?since=$(date -u -v-7d +%Y-%m-%dT%H:%M:%SZ)" \
-H "Authorization: Bearer $CF_API_TOKEN" | \
jq '.result[] | {when, actor: .actor.email, action: .action.type, resource: .resource.type}'
(On Linux, use date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ.)
Typical impact. These four signals cover most Cloudflare-layer incidents. Watching them turns "the site is down and we don't know why" into "the cert expires Thursday, renew it Tuesday."
Reading the 2021 page rule, one hypothesis at a time
Back to rule 7 of 23. Deleting it blind is how outages start, and leaving it forever is how zones rot. There are three readings, and each one predicts something you can check.
- It's still doing work. Traffic matches its URL pattern, and the action (a redirect, a cache bypass) changes what users get. Predicts: real request volume on the matching paths.
- It's shadowed. A modern Redirect, Cache or Configuration Rule now targets the same paths and overrides it. Predicts: an entry in the rulesets list from pattern 1 with an overlapping expression.
- It's dead. The paths it matches no longer receive traffic. Predicts: zero or near-zero requests on its pattern.
The rulesets dump from pattern 1 settles the second reading. For the first and third, ask the GraphQL Analytics API how much traffic hit the rule's path over the last day (adjust the pattern and window to your rule and plan limits):
curl -s "https://api.cloudflare.com/client/v4/graphql" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"query":"query($zone:String!,$since:Time!,$until:Time!){viewer{zones(filter:{zoneTag:$zone}){httpRequestsAdaptiveGroups(limit:20,orderBy:[count_DESC],filter:{datetime_geq:$since,datetime_leq:$until,clientRequestPath_like:\"/promo/%\"}){count dimensions{clientRequestPath edgeResponseStatus}}}}}","variables":{"zone":"'"$ZONE_ID"'","since":"2026-10-06T00:00:00Z","until":"2026-10-07T00:00:00Z"}}' \
| jq '.data.viewer.zones[0].httpRequestsAdaptiveGroups'
An empty result over a representative window means the rule is dead weight. A steady stream of 301s means it's a live redirect someone depends on, and it should be migrated, not deleted. Then check the audit log for who touched it last, so the next decision has an owner.
Why the one-time cleanup doesn't last
Every pattern above comes from the same loop. An incident creates pressure, someone makes a quick edit, nobody removes it, and the next incident inherits it.
01Incident
Pressure
A customer is blocked, a redirect loops, a cert fails.
02Fix
Quick edit
A skip rule, a new page rule, a toggle flipped on one zone.
03After
Nobody removes it
No owner, no expiry, and unknown downside to deleting it.
04Next incident
Inherits it
The debugging now starts with archaeology.
The structural reasons are specific. Cloudflare objects (records, rules, exceptions, settings) have no owner field and no expiry. Page rules are first-match-wins, so adding is always safer than editing. And there's no native view that diffs zones or ties a symptom to the change that caused it. A cleanup sprint resets the state without changing any of that, so the zone drifts back within a couple of quarters.
| One-time cleanup | Continuous checks | |
|---|---|---|
| DNS | Pruned once, regrows | New dangling records flagged within a day |
| WAF exceptions | Reviewed after an audit | Each skip has an owner and a review date |
| Zone settings | Aligned once | Diffed against a baseline on a schedule |
| Security events | Read during incidents | Ten minutes a week, or watched for you |
| Change history | Searched after an outage | Read alongside every symptom |
The deeper difference is timing. A cleanup finds a stale exception months after it stopped being needed. A continuous check finds it while the person who added it still remembers why.
What healthy zone hygiene looks like
A zone in good shape has properties you can verify:
- Every DNS record has a nameable owner, and nothing dangles.
- Zero legacy page rules, or a dated migration plan for each survivor.
- Every WAF skip rule answers "what breaks if this goes?" with something current.
- Zone settings match a written baseline, and drift is diffed on a schedule.
- Security events get ten minutes of human attention every week.
- Origin errors, WAF spikes, cert expiry and audit-log anomalies page someone.
Part two builds most of this with Cloudflare's own tools: scoped API tokens, Notifications, health checks and the audit log, with no third-party software.
Keep the checks running without keeping an engineer on them
Everything above is scriptable, and part three shows CloudThinker running it for you. Connect Cloudflare with a read-only scoped API token and CloudThinker keeps an inventory of your zones, DNS, WAF rules and settings drift, ties security events to recent config changes, and raises findings before they become incidents. It starts in Manual, so every fix waits for your approval. A good first question:
"Which WAF skip rules across our zones haven't been modified in over a year, and does any traffic still match them?"
Try CloudThinker free with 100 premium credits and no card required, or continue with the DIY automation guide.
