From wp-agent-skills
Install and configure Wordfence security on a WordPress site — firewall, malware scanner, login protection, and hardening settings. Use when setting up a new site, when the user asks to "secure the site", "add security", "install Wordfence", or before going live. Also use when a security issue is suspected. Applies a layered security baseline: Wordfence + core hardening + file permission checks.
npx claudepluginhub antonysilverhand/wp-agent-skills --plugin wp-agent-skillsThis skill is limited to using the following tools:
Full security setup: Wordfence installation + configuration + site hardening.
Acquire memory dumps from live systems/VMs and analyze with Volatility 3 for processes, networks, DLLs, injections in incident response or malware hunts.
Provides x86-64/ARM disassembly patterns, calling conventions, control flow recognition for static analysis of executables and compiled binaries.
Identifies anti-debugging checks like IsDebuggerPresent, NtQueryInformationProcess in Windows binaries; suggests bypasses via patches/hooks/scripts for malware analysis, CTFs, authorized RE.
Full security setup: Wordfence installation + configuration + site hardening. Run once before going live. Re-run after any suspected compromise.
Use two subagents in parallel:
Merge both reports into a single security summary.
wp eval "echo is_ssl() ? 'HTTPS: yes' : 'HTTPS: no'; echo PHP_EOL;"
wp eval "echo get_bloginfo('url'); echo PHP_EOL;"
wp core version
If is_ssl() is false on a live (non-local) site: stop and set up SSL first.
Wordfence's firewall is far less effective over HTTP.
wp plugin install wordfence --activate
Verify activation:
wp plugin list --status=active | grep wordfence
Wordfence stores its config in the wflogs/ directory and the wp_wfconfig table.
Apply the recommended baseline settings:
# Enable extended protection (firewall before WordPress loads)
wp eval "wf_maybe_update_firewall_rules();" 2>/dev/null || true
# Set security level to HIGH
wp option update wf_secLevel 2
# Enable login security
wp eval "
update_option('wf_loginSecurity', [
'blockBruteForce' => true,
'countFailedForUsername' => true,
'countFailedForIP' => true,
'maxFailuresPerUsername' => 5,
'maxFailuresPerIP' => 20,
'lockoutMins' => 60,
'twoFactorForRoles' => ['administrator'],
]);
echo 'Login security configured';
"
For full Wordfence configuration options, see references/wordfence-options.md.
A free Wordfence API key enables real-time threat intelligence:
wp eval "
update_option('wordfence_apiKey', '<YOUR_API_KEY>');
echo 'API key set';
"
Skip this step for local/dev environments.
Ensure these are set in wp-config.php:
define('DISALLOW_FILE_EDIT', true); // disable theme/plugin editor in admin
define('DISALLOW_FILE_MODS', true); // disable plugin/theme installs from admin (optional - comment out during setup)
define('WP_DEBUG', false); // never true in production
define('FORCE_SSL_ADMIN', true); // admin over HTTPS only (live sites)
Check current state:
wp config get DISALLOW_FILE_EDIT 2>/dev/null || echo "not set"
wp config get WP_DEBUG
Set if missing:
wp config set DISALLOW_FILE_EDIT true --raw --type=constant
wp config set WP_DEBUG false --raw --type=constant
wp post delete 1 --force 2>/dev/null || true # delete "Hello World" post
wp user delete 1 --reassign=<admin_user_id> 2>/dev/null || true # delete default admin if different user exists
wp option update blogdescription '' # remove "Just another WordPress site" tagline
Add to .htaccess (Apache) or Nginx config. For the PHP built-in server, the router.php already blocks direct PHP execution.
For live Apache hosts:
# Block access to wp-config.php
<Files wp-config.php>
Order deny,allow
Deny from all
</Files>
# Block access to .git, .env, readme files
<FilesMatch "^(readme\.html|license\.txt|wp-config-sample\.php|\.env|\.git)">
Order deny,allow
Deny from all
</FilesMatch>
# Block PHP execution in uploads
<Directory "/wp-content/uploads">
<Files "*.php">
Order deny,allow
Deny from all
</Files>
</Directory>
# wp-config.php should be 640 or 600 (owner read/write only)
stat -c "%a %n" wp-config.php
# wp-content/ should be 755
stat -c "%a %n" wp-content/
# Fix if needed
chmod 640 wp-config.php
chmod 755 wp-content/
find wp-content/ -type f -exec chmod 644 {} \;
find wp-content/ -type d -exec chmod 755 {} \;
wp user list --role=administrator --format=table
Flag:
admin or administrator → rename itRename default admin:
wp user update <id> --user_login=<new_name>
# Trigger scan via WP-CLI (Wordfence 7.x+)
wp eval "
if (class_exists('wfScanner')) {
wfScanner::startScan();
echo 'Scan started — check WP Admin → Wordfence → Scan for results';
} else {
echo 'Wordfence scanner not available via CLI — run from WP Admin → Wordfence → Scan';
}
"
# Confirm Wordfence is active and firewall is enabled
wp eval "
echo 'Wordfence active: ' . (is_plugin_active('wordfence/wordfence.php') ? 'yes' : 'no') . PHP_EOL;
echo 'Firewall mode: ' . get_option('wf_howGetIPs', 'not set') . PHP_EOL;
"
# Test that wp-config.php is not web-accessible (live sites)
curl -s -o /dev/null -w "%{http_code}" "$WP_SITE_URL/wp-config.php"
# expect: 403
DISALLOW_FILE_MODS true blocks ALL plugin/theme installs, including from WP-CLI when --allow-root isn't set. Comment it out during initial setup, set it after all plugins are installed..htaccess or php.ini. WP-CLI can't do this — Wordfence does it automatically on first activation through the admin UI. If running headless (no browser), set manually: auto_prepend_file = /path/to/wp-content/wflogs/rules.php.htaccess directives don't apply and the WAF rules will cause errors. Install Wordfence only on live/staging servers.wp user delete 1 will fail if user ID 1 is the only admin. Always ensure another admin exists before deleting.wp eval "echo is_writable(ABSPATH);".Security summary:
| Check | Status |
|---|---|
| Wordfence installed | ✓ / ✗ |
| Firewall active | ✓ / ✗ |
| Login protection | ✓ / ✗ |
| DISALLOW_FILE_EDIT | ✓ / ✗ |
| WP_DEBUG off | ✓ / ✗ |
| wp-config.php permissions | 640 / ⚠ |
| Default admin renamed | ✓ / ✗ |
| Initial scan | clean / issues found |
Flag any ✗ or ⚠ as action items before going live.