Firewall and WAF
Hive inspects requests in two places that behave the same: an engine inside WordPress and an optional guard that runs before WordPress loads. The rules are not written into the plugin but delivered signed from reportedip.com, with a bundled baseline that always works offline. The engine is free on every plan.
The engine inside WordPress
On init at priority 1 the engine matches the active ruleset against the URI, the query string,
the request body (also in a decoded copy) and the user agent: SQL injection, cross-site scripting, path
traversal, command injection, file inclusion wrappers, SSRF, Log4Shell, PHP object injection, XXE, web shell
uploads, CRLF and template injection, scanner user agents. A hit ends in the shared 403 block page.
- Safe by construction: bounded regular expressions, a malformed rule is skipped, and an error lets the request through instead of taking the site down.
- No false alarms for your editors: signed-in users who may edit content, wp-admin, cron and WP-CLI are not inspected by the engine; the whitelist always wins.
- Report-only: the firewall can log what it would block (
waf_would_block) without blocking. - Where: engine, mode and Paranoia Level under Protection → Firewall & Bots; rule sync and exceptions on Tools → Rules; the firewall log on Activity.
Signed rule delivery and Priority Sync
Rulesets come versioned and Ed25519-signed from reportedip.com. The plugin checks every ruleset against a public key it ships with and keeps the bundled baseline when a feed is missing, too large or does not verify, so a tampered feed cannot change your rules. New signatures reach every connected site within hours, without a plugin release.
| Plan | Rules | Refresh |
|---|---|---|
| Local Shield, any plan | Bundled OWASP Top 10 baseline, Paranoia Level 1 | With the plugin updates |
| Free, Community Network | Server ruleset at Paranoia Level 1, which covers more than the bundled one | Every six hours |
| Contributor | Priority Sync: Paranoia Level 2 and the bot address range feeds | Weekly |
| Professional and up | Priority Sync: Paranoia Level 3, bot ranges, the live list of disposable mail domains | Daily |
Paranoia Level 3 is strict and catches obfuscated payloads, at the price of more false positives; it is meant for experienced operators. Contributor is a free plan for accounts that contribute data, for example through a honeypot or the Linux agent.
Extended Protection: the guard before WordPress
An optional auto_prepend_file guard applies the same rules, exceptions, whitelist and IP blocks
before WordPress loads, so a blocked request costs almost nothing. Its hits are written to a queue and imported
into the log and the escalation ladder; a block set by the plugin reaches the guard within the same request.
The guard is off by default and set up on Tools → Server:
- Apache and PHP-FPM (also nginx with PHP-FPM) are configured automatically through
.htaccessor a.user.iniin the document root. - Other stacks get the line for php.ini or the hosting panel, or an nginx
fastcgi_paramsnippet. - Signed-in users: the guard skips body inspection when a WordPress sign-in cookie is present, so saving content never trips it; URL and user agent rules still apply.
- Status you can trust: the Server tab reports whether the guard really ran for the current request, and the readiness register warns when its queue is not writable.
- Fail-open and safe to remove: any error lets the request through. Switching it off removes the directives Hive controls and leaves an inert placeholder file, so a leftover line in a hand-edited configuration never points at a missing file. Report-only mode switches the guard off as well.
Exceptions for false positives
A form that accepts HTML, a page builder posting raw markup or an API receiving attack samples can trip a signature now and then. An exception lets that one case pass while the rest stays protected.
- Where: Tools → Rules → WAF Exceptions, or Allow on a firewall row in the log, which fills in a narrow exception for exactly that rule on that path.
- Scope: one rule, a rule group or, for an endpoint of your own, the whole engine on a path, optionally narrowed to an address or range. A whole-engine exception always needs a path or address, so the firewall can never be switched off globally by accident.
- Keep it narrow: a rule on a path before a group, a group before the whole engine. The log row shows the matched value, the inspected part, method, URI and user agent, and for
admin-ajax.phpthe AJAX action. - Both layers: exceptions are baked into the guard and rebuilt whenever the list changes. On a network they apply to all sites. Every plan.
- In code: the filter
reportedip_hive_waf_bypass_routesexcludes REST routes by an anchored prefix on the resolved route; it works in the engine only.
Reference codes and the block page
Every block, firewall or sensor, carries a code such as WAF_SQLI-3F9A2B71 on the block page and in
the X-RIP-Ref header. A visitor who was blocked by mistake quotes the code, and you find the row in
the log. The code is a one-way hash of address, reason and hour, so it reveals nothing. The texts of the block
page can be replaced with the filter reportedip_hive_blocked_page_strings.
Page caches
The block page defines DONOTCACHEPAGE, DONOTCACHEDB and DONOTCACHEOBJECT
and sends Cache-Control: no-store, no-cache, must-revalidate, max-age=0, Pragma: no-cache
and the WordPress nocache_headers(). WP Rocket, W3 Total Cache, WP Super Cache and LiteSpeed Cache
respect this, so one blocked attacker never leaves a cached 403 for real visitors. The form check carries
nothing request-specific, so cached pages keep working with it.
Last updated: · Maintained by the ReportedIP team