Install
$ agentstack add skill-goldenwing-360-claude-security-skills-cloudflare-hardening ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Cloudflare Hardening
Cloudflare gives you a powerful edge layer for free, but its defaults are conservative — most of the protection is opt-in. This skill walks the security-relevant settings and the ones that catch people out.
Applies to Cloudflare's main product (DNS + Proxy + WAF + Workers/Pages/R2). Not Magic Transit / Spectrum specifics.
When to invoke
- Domain just onboarded to Cloudflare
- Site behind CF was scraped, brute-forced, or DDoSed
- Origin IP may be exposed (showed up in
dnshistory, accidentally A-recorded) - Periodic review of an existing public site
- Setting up Cloudflare Pages or R2 with a custom domain
Step 1 — Lock the account itself
Before site settings, harden the account.
- 2FA on the account with WebAuthn / hardware key, not SMS
- API tokens, not Global API Key — Global API Key has account-wide power and cannot be scoped
- Audit Logs —
Account → Audit Logshows who did what; review monthly - Members — separate humans from automation; each automation gets its own scoped token
API tokens: scope to specific zones + specific permissions. A common mistake is creating a "DNS edit" token at account level when only one zone needs it.
Step 2 — DNS and proxy posture
Zone → DNS → Records
- All public hostnames proxied (orange cloud) unless you have a specific reason for grey-cloud (e.g. mail records — MX must be grey)
- Origin IP must not be in any public DNS record — common leaks:
- Direct A record for
direct.example.comororigin.example.comleft over - MX pointing to a host on the same IP as the web origin (move mail to a separate IP/host)
- SPF/TXT records containing IP literals that match the origin
- DNSSEC — enable in
DNS → Settings. Requires DS record at the registrar. - CAA records — restrict who can issue certs for your domain. Cloudflare adds these automatically if you turn it on.
If your origin IP is known-leaked, rotate it — provider panel usually lets you re-assign. Pair with origin allowlist (next step).
Step 3 — Origin allowlist (defense-in-depth)
Cloudflare proxy is useless if attackers can hit the origin IP directly. Two complementary controls:
1. Authenticated Origin Pulls — origin only accepts TLS connections that present Cloudflare's client cert.
Zone → SSL/TLS → Origin Server → Authenticated Origin Pulls
Then on your origin nginx:
ssl_client_certificate /etc/ssl/cloudflare/authenticated_origin_pull_ca.pem;
ssl_verify_client on;
2. Firewall the origin to Cloudflare's IPs only — at the VPS, restrict 80/443 to CF's published ranges:
# Fetch and ufw-allow only Cloudflare IPs (refresh on a cron)
sudo ufw delete allow 80/tcp
sudo ufw delete allow 443/tcp
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
sudo ufw allow from "$ip" to any port 80,443 proto tcp comment 'cloudflare'
done
for ip in $(curl -s https://www.cloudflare.com/ips-v6); do
sudo ufw allow from "$ip" to any port 80,443 proto tcp comment 'cloudflare-v6'
done
sudo ufw reload
Either alone is acceptable; both is best. Without one of them, the proxy provides little hardening because attackers will bypass it.
Step 4 — TLS
Zone → SSL/TLS
- Encryption mode: Full (strict) — anything less either allows MITM (Full, not strict) or runs plaintext between CF and origin (Flexible). Flexible is a footgun; do not use.
- Minimum TLS Version: 1.2 minimum, 1.3 if your audience tolerates it
- Always Use HTTPS: on
- Automatic HTTPS Rewrites: on
- HSTS — apply via
Edge Certificates → HSTS.max-age=31536000,includeSubDomains, preload only if you understand the lock-in.
Step 5 — WAF and Bot management
Zone → Security → WAF
- Managed Rules → Cloudflare Managed Ruleset: on, default action
Managed Challenge - OWASP Core Ruleset: on, but watch for false positives — start in Log mode, then escalate
- Custom Rules for your stack:
# Block direct access to wp-admin from outside your country (adjust)
(http.request.uri.path contains "/wp-admin" or http.request.uri.path contains "/wp-login.php")
and ip.geoip.country ne "AT"
→ Action: Managed Challenge
# Block known abusive paths
http.request.uri.path in {"/.git/config" "/.env" "/wp-config.php.bak" "/server-status"}
→ Action: Block
# Tighten login endpoints
http.request.uri.path eq "/wp-login.php" and http.request.method eq "POST"
→ Action: Managed Challenge
# Hide xmlrpc unless you actually use it
http.request.uri.path eq "/xmlrpc.php"
→ Action: Block
- Bot Fight Mode (free tier): on. Catches dumb scrapers. False positives are rare.
- Super Bot Fight Mode (paid): better, distinguishes verified bots from definitely-automated traffic.
- Rate Limiting Rules — free tier gives one rule; use it well:
http.request.uri.path eq "/wp-login.php" → 5 requests / 1 minute per IP → Block 10m
Step 6 — Security headers via Transform Rules
You can inject headers without touching the origin. Rules → Transform Rules → Modify Response Header:
Set: Strict-Transport-Security = max-age=31536000; includeSubDomains
Set: X-Content-Type-Options = nosniff
Set: Referrer-Policy = strict-origin-when-cross-origin
Set: Permissions-Policy = camera=(), microphone=(), geolocation=(), interest-cohort=()
Set: Content-Security-Policy =
CSP is too app-specific to template here. Start in Content-Security-Policy-Report-Only with a permissive baseline, watch the reports for a week, tighten, then promote to enforcing.
Step 7 — Zero Trust Access for admin paths
/wp-admin, /admin, /staging, /api/internal/* should not be reachable from the open internet for most projects. Cloudflare Zero Trust (free for ≤ 50 users) gives you SSO-gated access:
Cloudflare Zero Trust → Access → Applications → Add → Self-hosted
- Application domain:
*.example.com/wp-admin* - Identity provider: Google/GitHub/email-OTP
- Policy:
Allow → emails in @yourcompany.comor specific list
Now /wp-admin requires SSO before traffic reaches the origin at all. Brute-force on the WP login endpoint stops being your problem.
Step 8 — Cache and Page Rules
(New zones: Page Rules are being phased out in favor of Cache Rules, Configuration Rules, Origin Rules, and Single Redirects.)
- Cache static assets aggressively, but never cache responses with
Set-Cookieor auth headers - Bypass cache for
/wp-admin/*,/wp-login.php,/cart/*,/checkout/*,/api/*— auth and per-user content - Always Use HTTPS as a Configuration Rule, not a workaround
- Single Redirect is the modern replacement for the "forward url" Page Rule
Step 9 — Cloudflare Pages security
If you use Pages:
- Branch deploy previews are public by default — gate them with Access if they contain anything non-public
- Environment variables marked as Secret are not exposed to client bundles, but
NEXT_PUBLIC_*and similar prefixes still go to the browser. Audit which env vars exist and where they end up. _headersfile in the output directory applies headers per path — convenient for static-site CSP- Custom domain CNAME must be a CF-orange-clouded record on a CF-managed zone
Step 10 — R2 buckets
- Public buckets — only for content actually meant to be public. Check
Bucket → Settings → Public access. - Custom domain on R2 — use it for public assets; never bind sensitive buckets to public custom domains
- CORS — restrict origins, do not use
*unless you understand it - Object listing — disable public listing; serve specific objects, not directory enumeration
Step 11 — Audit and monitoring
Zone → Security → Events
Zone → Analytics → Security
- Review weekly for the first month, then monthly
- Look for: unusual ASNs, sustained 4xx/5xx from one source, spikes in Managed Challenge issuances
- For paid tiers: alerts on rule actions, expensive queries to Workers
Step 12 — Periodic re-audit
Once a quarter, walk through:
- [ ] All DNS records still in use; remove orphans
- [ ] No DNS record exposes origin IP
- [ ] Authenticated Origin Pulls + origin firewall still in place
- [ ] WAF rules still match current app paths
- [ ] CSP still matches frontend (after deploys it can drift)
- [ ] No new public R2 buckets without intent
- [ ] No new long-lived API tokens with broad scope; rotate ones older than 90 days
- [ ] Zero Trust app list matches current team
What this skill will not do
- Recommend Flexible SSL or any setting that allows plaintext between CF and origin
- Help bypass Cloudflare protection on a site you do not own
- Endorse leaving origin IP discoverable when the site is intentionally proxied
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: GoldenWing-360
- Source: GoldenWing-360/claude-security-skills
- License: MIT
- Homepage: https://goldenwing.at
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.