WHA Docs

Security

Security layers from Cloudflare edge rules to WordPress application hardening.

Security is handled at multiple layers — Cloudflare at the edge, Nginx at the web server, and the yax-security mu-plugin at the application level.

Cloudflare (Edge)

WAF / Security Rules

OrderRuleMatchAction
1Protect LoginURI starts with /wp-login.phpManaged Challenge
2BrightEdgeIP source in BrightEdge rangeSkip (allow crawler)
3Allow FacebookAS Num 32934Skip (disabled)
4Block non-USA originCountry is not US and not CABlock
5Bypass WAF for healthURI starts with /healthzSkip

IP Access Rules

IP-level allow/block rules are managed in the Cloudflare dashboard under Security → WAF → IP access rules. These are used to allowlist monitoring services and block known bad actors.

Geo-Blocking

Non-US and non-CA traffic is blocked at the edge (rule 4). This is a healthcare site serving patients in the Pacific Northwest — international traffic is almost entirely bot or attack traffic.

Turnstile

Cloudflare Turnstile provides bot protection on forms via the simple-cloudflare-turnstile WordPress plugin. It replaces traditional CAPTCHAs with a non-intrusive challenge that doesn't require user interaction in most cases.

SSL

SSL is terminated at Cloudflare (proxied mode). The connection between Cloudflare and Heroku uses Heroku's ACM (Automated Certificate Management). WordPress detects HTTPS via the X-Forwarded-Proto header passed through the proxy chain.

Nginx (Web Server)

Nginx enforces several security rules in both nginx.conf (production) and nginx.dev.conf (local dev):

RuleWhat it blocks
location ~ /\.Dotfiles (.env, .git, .htaccess)
`location ~ ^/(wp-config.phpreadme.html
location ~* /(?:uploads|files)/.*\.php$PHP execution in upload directories
location = /xmlrpc.phpXML-RPC endpoint (common attack vector)

Security headers set by Nginx:

HeaderValue
X-Frame-OptionsSAMEORIGIN
X-XSS-Protection1; mode=block
X-Content-Type-Optionsnosniff
Referrer-Policyno-referrer-when-downgrade

WordPress Application

yax-security Plugin

The yax-security mu-plugin provides application-level hardening with configuration via an options page in wp-admin. Capabilities include disabling file editing, hiding WordPress version info, and other standard hardening measures.

yax-cleanup Plugin

The yax-cleanup mu-plugin removes WordPress features that expose attack surface:

  • Emoji scripts and styles (reduces fingerprinting)
  • oEmbed discovery links
  • WordPress generator meta tag (version disclosure)
  • Windows Live Writer manifest
  • RSD (Really Simple Discovery) link

AJAX Nonce Verification

All AJAX endpoints use WordPress nonce verification. The theme generates a nonce via wp_create_nonce('wha_ajax') and passes it to JavaScript through wp_localize_script. AJAX handlers verify with check_ajax_referer().

Output Escaping

Template output uses WordPress escaping functions (esc_html(), esc_attr(), wp_kses_post()) throughout. The production readiness audit (2026-02) identified and fixed unescaped output in utility functions and templates.

Build-Time and Deploy Hardening

The build script strips info-disclosure files (readme.html, license.txt), and dev-only plugins are physically removed on every container start. See Deployment and Plugin System.

Health Check

The /healthz endpoint (provided by healthz.php mu-plugin) returns a simple 200 response for uptime monitoring. It bypasses both Cloudflare WAF rules and cache rules to ensure accurate monitoring.

On this page