WP Manifestindependent plugin directory
manifest / security / security-kit

Security Kit

Zero-admin-UI bot and brute-force protection for WordPress and WooCommerce. Honeypot, timing trap, and login lockout that covers every auth vector: wp-login, WooCommerce, XML-RPC, REST.

by axeldegouyon · github.com/axeldegouyon/security-kit

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/axeldegouyon/security-kit/archive/refs/heads/main.zip

Readme

Security Kit

Lightweight bot and brute-force protection for WordPress and WooCommerce.
Single file, no settings screen, no dashboard footprint — every behavior is controlled by constants at the top of security-kit.php.

What it does

  • Honeypot: a hidden form field real visitors never fill in. A non-empty submission means a bot.
  • Timing trap: rejects submissions that arrive faster than a human could plausibly fill the form.
  • Nonce verification: on every protected form.
  • Login lockout: dual-key on IP and username, checked with OR logic, so it defends against both attack shapes: credential stuffing (many passwords against one account, from many IPs) and password spraying (a few passwords against many accounts, from one IP). Fires on the authenticate filter, so it covers wp-login.php, WooCommerce account login, XML-RPC, REST, and application passwords — not just the standard login form.
  • Comment cooldown: — a minimum interval between comments per identity.
  • WooCommerce checkout protection: honeypot + timing on the checkout form.
  • Cloudflare-aware IP resolution: only trusts the CF-Connecting-IP header when the direct connection genuinely originates from a published Cloudflare edge range, so the header can't be spoofed by hitting the origin directly.
  • Optional XML-RPC hardening: disable XML-RPC entirely, or just remove system.multicall, the method that lets one request carry hundreds of credential attempts.

Install

Upload security-kit.php to wp-content/plugins/security-kit/ and activate.
This creates one dedicated table, wp_securitykit_state — never written to WordPress core tables (no transients, no wp_options bloat).

Configuration

All at the top of the file:

Constant Default Meaning
SECURITY_KIT_FIELD_NAME sk_ref_confirm Honeypot field name. Change per install to something non-obvious — a guessable name (website, url) is one bots already know to skip.
SECURITY_KIT_MIN_SECONDS 3 Minimum seconds between form render and submit.
SECURITY_KIT_LOGIN_MAX_ATTEMPTS 5 Failed attempts before lockout.
SECURITY_KIT_LOGIN_LOCKOUT 600 Lockout duration, in seconds.
SECURITY_KIT_COMMENT_COOLDOWN 15 Minimum seconds between comments per identity.
SECURITY_KIT_TRUSTED_PROXY_RANGES Cloudflare's published ranges Re-check against cloudflare.com/ips periodically — Cloudflare updates this list occasionally.
SECURITY_KIT_DISABLE_XMLRPC false Disables XML-RPC entirely.
SECURITY_KIT_DISABLE_XMLRPC_MULTICALL false Keeps XML-RPC but removes the amplification method.

Known trade-offs — read before relying on this alone

  • The username lockout can be turned against you. Anyone who knows your admin username or email can deliberately fail 5 logins to lock your own account for 10 minutes, repeatedly. The IP counter has no equivalent downside. If that risk outweighs the protection for your site, drop the username half of the check and keep IP-only.
  • This is an application-level backstop, not a wall. It still runs inside PHP, so it still consumes a worker per attempt. Edge-level protection (a Cloudflare rate-limit rule on POST /wp-login.php, blocking /xmlrpc.php outright if you don't use it) stops traffic before it costs you anything, and is worth setting up regardless of this plugin.
  • XML-RPC hardening is opt-in, not on by default — enabling it will break Jetpack, the WordPress mobile app, or any remote-publishing tool that depends on it. Confirm nothing on the site uses XML-RPC before turning it on.

Extending

Every check (honeypot, timing, nonce) runs through security_kit_validate_get_error(), and every stateful counter (lockouts, cooldowns) runs through the four security_kit_state_*() functions backed by the dedicated table.
A new protected form or a new counter should be built on those existing primitives rather than introducing a new storage mechanism.

Read the full README on GitHub →