Lw firewall registration guard
Skill Lonsdale201/wp-agent-skills/lw-plugins/lw-firewall-registration-guard
Integrate custom WordPress registration forms with LW Firewall's registration spam protection. Use when code renders or validates custom signup forms, AJAX/REST registration endpoints, Woo/CRM/LMS registration flows, or files referencing `RegisterGuard::render_fields`, `RegisterGuard::validate`, `RegisterToken::issue`, `RegisterToken::verify`, `lw_fw_reg_token`, `lw_fw_url`, `registration_errors`, honeypot fields, proof-of-render tokens, single-use tokens, or spam auto-ban behavior.From its SKILL.md
npx -y skills add Lonsdale201/wp-agent-skills --skill lw-firewall-registration-guardAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.1 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
LW Firewall: registration spam guard
Use this when a plugin/theme renders its own registration form and still wants LW Firewall's proof-of-render token, honeypot, single-use replay protection, and rejected-registration auto-ban.
LW Firewall automatically protects only the default WordPress registration form
via register_form and registration_errors, and only when users_can_register
is enabled. Custom forms must opt in.
Core contract
Verified field names:
| Field | Purpose |
|---|---|
lw_fw_reg_token | signed HMAC proof-of-render token |
lw_fw_url | honeypot text field; must stay empty |
Verified public methods:
| Method | Use |
|---|---|
LightweightPlugins\Firewall\Rules\RegisterGuard::render_fields() | echo hidden token and optional honeypot |
LightweightPlugins\Firewall\Rules\RegisterGuard::validate( WP_Error $errors ) | validate current $_POST, record reject, add generic error |
LightweightPlugins\Firewall\Rules\RegisterToken::issue() | issue token for headless/custom rendering |
LightweightPlugins\Firewall\Rules\RegisterToken::verify() | verify token manually |
LightweightPlugins\Firewall\Rules\RegisterTracker::record_reject() | count reject and auto-ban after threshold |
Do not call private methods or edit worker/lw-firewall-worker.php.
Preferred integration
If the form is server-rendered PHP, render fields directly inside the form:
use LightweightPlugins\Firewall\Rules\RegisterGuard;
if ( class_exists( RegisterGuard::class ) ) {
RegisterGuard::render_fields();
}
Then validate before creating the user:
use LightweightPlugins\Firewall\Rules\RegisterGuard;
$errors = new WP_Error();
if ( class_exists( RegisterGuard::class ) ) {
$errors = RegisterGuard::validate( $errors );
}
if ( $errors->has_errors() ) {
return $errors;
}
// Create the user only after the guard passes.
This path keeps the plugin's own behavior intact: honeypot check, token age check, optional single-use storage, reject counting, whitelist skip, and auto-ban through the shared firewall ban store.
Headless or REST form
If the form is not rendered by PHP output, issue the token server-side and send it in the response that renders the form:
use LightweightPlugins\Firewall\Options;
use LightweightPlugins\Firewall\Rules\RegisterToken;
$payload['lwFirewall'] = [
'enabled' => class_exists( RegisterToken::class ),
'token' => class_exists( RegisterToken::class ) ? RegisterToken::issue() : '',
'tokenName' => 'lw_fw_reg_token',
'honeyName' => 'lw_fw_url',
'honeypot' => (bool) Options::get( 'register_honeypot', true ),
];
Render the honeypot as a hidden/off-screen text input and submit both fields with the registration request. Do not create a public "give me a token" endpoint that can be spammed independently from the form render.
Manual validation
Use manual validation only when RegisterGuard::validate() cannot fit the
handler shape:
use LightweightPlugins\Firewall\Options;
use LightweightPlugins\Firewall\Rules\RegisterToken;
use LightweightPlugins\Firewall\Rules\RegisterTracker;
$honeypot = isset( $_POST['lw_fw_url'] )
? sanitize_text_field( wp_unslash( $_POST['lw_fw_url'] ) )
: '';
if ( Options::get( 'register_honeypot', true ) && '' !== $honeypot ) {
RegisterTracker::record_reject();
return new WP_Error( 'lw_fw_spam', __( 'Registration failed, please try again.', 'text-domain' ) );
}
$token = isset( $_POST['lw_fw_reg_token'] )
? sanitize_text_field( wp_unslash( $_POST['lw_fw_reg_token'] ) )
: '';
$storage = null;
if ( Options::get( 'register_single_use', true ) && function_exists( 'lw_firewall_resolve_storage' ) ) {
$storage = lw_firewall_resolve_storage( (string) Options::get( 'storage', 'auto' ) );
}
$ok = RegisterToken::verify(
$token,
(int) Options::get( 'register_min_fill_time', 2 ),
(int) Options::get( 'register_token_max_age', 3600 ),
$storage
);
if ( ! $ok ) {
RegisterTracker::record_reject();
return new WP_Error( 'lw_fw_spam', __( 'Registration failed, please try again.', 'text-domain' ) );
}
Use a generic error. Do not tell bots whether the honeypot, token age, expiry, or single-use check failed.
Important behavior
- Missing token is spam.
- Filled honeypot is spam when
register_honeypotis enabled. - Token age lower than
register_min_fill_timeis spam. - Token age higher than
register_token_max_ageis spam. - Reused token is spam when
register_single_useis enabled. RegisterTracker::record_reject()skips whitelisted IPs.- After
register_ban_thresholdrejects, the IP is banned forregister_ban_duration. - Auto-ban is written to the same storage used by the MU-plugin worker, so later requests are blocked before WordPress fully loads.
Checklist
- Render the guard fields inside every custom registration form.
- Preserve both fields through AJAX/REST serialization.
- Validate before calling
wp_insert_user(),wp_create_user(), Woo customer creation, CRM contact creation, or LMS enrollment. - Keep normal CSRF nonce/capability checks; LW Firewall token is anti-spam, not a WordPress nonce.
- Test too-fast submit, expired token, reused token, filled honeypot, and valid submit.
- Confirm whether your custom form should respect
users_can_register; LW Firewall's automatic core hook does.
Cross-references
- Run
wp-security-auditfor nonce/sanitization/escaping checks around the form. - Run
lw-firewall-rate-limit-workerwhen the endpoint also needs rate limiting. - Run
wp-rest-apiif the form submits through a REST route.
What this skill does NOT cover
- Captcha provider integration.
- Non-registration contact-form spam.
- Editing LW Firewall internals or the MU-plugin worker.
References
- Official documentation: https://github.com/lwplugins/lw-firewall
- Verified source paths:
wp-content/plugins/lw-firewall/includes/Plugin.phpwp-content/plugins/lw-firewall/includes/Rules/RegisterGuard.phpwp-content/plugins/lw-firewall/includes/Rules/RegisterToken.phpwp-content/plugins/lw-firewall/includes/Rules/RegisterTracker.phpwp-content/plugins/lw-firewall/includes/Rules/AutoBanner.phpwp-content/plugins/lw-firewall/includes/Options.phpwp-content/plugins/lw-firewall/includes/helpers.phpwp-content/plugins/lw-firewall/tests/register-token-test.phpwp-content/plugins/lw-firewall/CHANGELOG.md
What ships with it: 1 file
255 B alongside SKILL.md
agents/
- openai.yaml255 B