Skip to content

The Noiz ModSecurity Rule Set (Custom WAF Rules)

This guide explains the custom ModSecurity rule set that Noiz runs on its web servers: what each rule does in plain language, the policy behind it, and how the rule set is verified and kept current. It is the canonical reference for the rules themselves and is updated as the deployed rules change (currently v8, August 2026). It is written for Noiz operations.

For how to deploy the rules to a specific panel, see the panel guide: Deploy the Noiz ModSecurity Rules on Plesk or Deploy the Noiz ModSecurity Rules on ISPConfig. For diagnosing blocks, see Troubleshooting the Noiz ModSecurity Custom Rules.

Last reviewed: 1 August 2026, against the deployed Noiz rule set v8 with ModSecurity 2. It complements the official ModSecurity documentation; the rule IDs and thresholds are the Noiz-specific ones.

The Noiz estate hosts WooCommerce shops. The rules are built around one observed reality: when a shop is attacked, the attack is a flood of shopping-request shapes — facet filtering, add-to-cart, cart/checkout URLs — replayed from many IPs to burn CPU. The rule set has three jobs:

  1. Flood defence — rate-limit and reject the shopping-flood shapes (rules 1000200–1000203, 1000210).
  2. Bot policy — allow verified search engines, rate-limit AI crawlers, block known-bad named crawlers, and let everything else fall under the per-IP rate rules (rules 1000199, 1000196, 88345501–88345506).
  3. Hygiene — never let client-supplied credentials land in logs (88349100).

The policy behind the bot rules is four tiers:

Tier Who Treatment
T1 Verified search engines (Googlebot, Bingbot, Applebot, DuckDuckBot, Yandex, Baidu, Facebook link-preview) Allow, exempt from all flood rules (IP allowlist, DNS-verified)
T2 AI crawlers (Perplexity, Bytespider, Amazon, Common Crawl, Meta, Cohere) Allow but rate-limited (15 req/30 s per IP); GPTBot and ClaudeBot currently denied outright
T3 Known-bad named crawlers (SEO tools, GraphEmbedScraper) Deny 403 by user agent
T4 Everything else, including the anonymous browser-spoofing farm Covered by the per-IP rate rules — the only enforcement that touches them

A crawler that spoofs a normal browser user agent cannot be blocked by any user-agent rule; only the per-IP behavioural rate rules hold it. That is why T4 exists and why the rate rules are the real enforcement layer.

All rules run at request-header time (phase 1). IDs 10xxxxx are estate flood rules, 8834xxxx are bot-policy rules, 883491xx are hygiene.

Rule Tier What it does Response
88349100 hygiene Blanks the Authorization header from every log and audit entry so client credentials never get written to disk pass
1000199 T1 Client IP is on the verified search-crawler list → skip every flood rule for this request pass, logged
1000196 T2 Client IP is on the verified AI-bot list → skip every flood rule (but not the AI rate limit) pass, logged
1000198 backend Requests to /wp-admin/, /wp-json/, /wp-login.php skip the flood rules (the site’s own admin/AJAX traffic is never rate-limited) pass
88345501 T3 User agent is GPTBot / OAI-SearchBot / ChatGPT → blocked (AI-training opt-out) 403
88345502 T3 User agent is ClaudeBot → blocked 403
1000201 counter Any URL carrying a WooCommerce facet/shopping parameter bumps this IP’s counter (resets after 60 s). Also counts wc-ajax=add_to_cart (the modern AJAX cart vector) pass
1000200 T4 More than 15 counted facet requests from one IP in 60 s → rate-limited. The main lever that held the 31 July flood 429
1000202 T4 Facet endpoint with no cookie at all → a bot or scanner 429
1000203 T4 Facet endpoint with a cookie that is not a session cookie (name lacks woocommerce/wordpress/wp-/phpsessid) 429
1000210 T4 /cart/ or /checkout/ URL carrying add-to-cart anywhere in the query → the cart-page flood vector 403
88345503 T3 User agent is GraphEmbedScraper (price-data scraper) → blocked 403
88345504 T3 User agent is an SEO-tool crawler (ahrefs, Semrush, MJ12, DotBot, petalbot, DataForSEO, Serpstat, SEOKicks, Scorpy, Magpie) → blocked 403
88345505 counter User agent is an allowed AI crawler → bumps this IP’s counter (resets after 30 s) pass
88345506 T2 More than 15 AI-crawler requests from one IP in 30 s → rate-limited 429

Why 429 for rate limits and 403 for denies: 429 (Too Many Requests) is the signal that tells a well-behaved client to slow down and back off, which is what you want from a rate limit. 403 is a straight refusal for named bad actors.

The rule set is deployed through the control panel’s own custom-directives channel, never by editing the generated ModSecurity config file by hand. The generated file is rebuilt from the GUI on every save, so a manual edit is overwritten. The deploy and verify steps are panel-specific:

ModSecurity’s audit log (/var/log/modsec_audit.log) records every rule match. One important distinction: a rule match is not a block. For example, rule 1000202 (no-cookie facet endpoint) writes an audit entry for every facet request it sees; only the transactions that also failed the second condition of the chain got a 429. Count the 429s in the access log, not the rule matches in the audit log, when measuring blocking.

Four things keep the rule set honest:

  1. Allowlist refresh, monthly. The search-engine and AI-bot allowlists are full bypasses for whatever IPs they contain, and crawler ranges change. Re-verify each entry monthly with reverse-DNS + forward-DNS (hostname must be under the vendor’s domain and resolve back to the same address). Remove entries that fail either leg, apply the new list with a diff — never blindly — and record the check date in the file header.
  2. Geo database refresh, monthly. The flood-identification tool reads a country database for crawler attribution; refresh it on the same monthly cadence with npulse geoip-update.
  3. Threshold review. The AI-crawler rate limit and the facet counter thresholds were calibrated from incident evidence. Re-examine them periodically from the audit log; if a legitimate crawler trips a rate limit, raise it with evidence.
  4. Collection-file compaction. Every counting rule in this set writes to ModSecurity’s persistent collections, and those files grow without limit and never reclaim space on their own. Measure the fragmentation rate rather than the file size, and rebuild the collections when it climbs. See Why ModSecurity collection files grow without limit, and how to compact them.
  • Cookie rules check names, not sessions. 1000202/1000203 look at whether a cookie exists and whether its name looks like a session cookie — they cannot ask PHP whether a session is actually live. A bot that sends a cookie named woocommerce_cart_hash with garbage content passes. This is an accepted risk for now; the real fix if the crawler farm escalates is headless-bot detection or application-level cart-hash validation.
  • The anonymous farm is only held by the rate rules. A headless Chrome farm with one request per IP per window is below every per-IP threshold; the 1000200 family catches the floods, not the slow crawl. Density-based or edge (CDN) detection is the escalation path.
  • WordPress backend exemption is wide. Everything under /wp-json/ is exempt from the flood rules; REST API scraping is not rate-limited by this set. Tracked as an open item.
  • xmlrpc.php is unguarded by this set (Jetpack dependency varies per site); pingback reflection abuse is covered elsewhere if enabled.