WordPress Security Automation with WP-CLI: Essential Commands
Automate WordPress security tasks using WP-CLI including updates, user management, security scanning, and maintenance operations.
WP-CLI enables powerful security automation for WordPress sites. This guide covers essential security commands and scripts for maintaining site protection.
Essential Security Commands
Core WP-CLI commands for security:
# Check WordPress core integrity
wp core verify-checksums
# Update WordPress core
wp core update
# Update all plugins
wp plugin update --all
# Update all themes
wp theme update --all
# Check for available updates
wp core check-update
wp plugin list --update=available
wp theme list --update=available
User Security Management
Manage user accounts securely:
# List all administrators
wp user list --role=administrator --format=table
# Check for suspicious users
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
# Reset user password
wp user update admin --user_pass="$(openssl rand -base64 24)"
# Remove suspicious user
wp user delete suspicious_user --reassign=1
# List users with no posts
wp user list --format=ids | xargs -I {} sh -c 'count=$(wp post list --author={} --format=count); [ "$count" -eq 0 ] && echo "User {} has no posts"'
# Force all users to reset passwords
wp user list --format=ids | xargs -I {} wp user update {} --user_pass="RESET_REQUIRED"
Security Scanning Script
Comprehensive security scan automation:
#!/bin/bash
# security-scan.sh
SITE_PATH="/var/www/html"
LOG_FILE="/var/log/wp-security-scan.log"
ADMIN_EMAIL="admin@example.com"
cd $SITE_PATH
echo "=== WordPress Security Scan - $(date) ===" >> $LOG_FILE
# Verify WordPress core
echo "Checking WordPress core integrity..." >> $LOG_FILE
CORE_CHECK=$(wp core verify-checksums 2>&1)
if [ $? -ne 0 ]; then
echo "WARNING: Core integrity check failed" >> $LOG_FILE
echo "$CORE_CHECK" >> $LOG_FILE
ALERT_NEEDED=true
fi
# Check for available updates
echo "Checking for updates..." >> $LOG_FILE
CORE_UPDATE=$(wp core check-update --format=count 2>/dev/null)
PLUGIN_UPDATES=$(wp plugin list --update=available --format=count 2>/dev/null)
THEME_UPDATES=$(wp theme list --update=available --format=count 2>/dev/null)
if [ "$CORE_UPDATE" -gt 0 ] || [ "$PLUGIN_UPDATES" -gt 0 ] || [ "$THEME_UPDATES" -gt 0 ]; then
echo "Updates available: Core=$CORE_UPDATE, Plugins=$PLUGIN_UPDATES, Themes=$THEME_UPDATES" >> $LOG_FILE
fi
# Check for suspicious files
echo "Scanning for suspicious files..." >> $LOG_FILE
SUSPICIOUS=$(find $SITE_PATH/wp-content -name "*.php" -newer $SITE_PATH/wp-config.php -mtime -1 2>/dev/null)
if [ -n "$SUSPICIOUS" ]; then
echo "WARNING: Recently modified PHP files found:" >> $LOG_FILE
echo "$SUSPICIOUS" >> $LOG_FILE
ALERT_NEEDED=true
fi
# Check file permissions
echo "Checking file permissions..." >> $LOG_FILE
WRITABLE_CONFIG=$(find $SITE_PATH -name "wp-config.php" -perm -002 2>/dev/null)
if [ -n "$WRITABLE_CONFIG" ]; then
echo "WARNING: wp-config.php is world-writable" >> $LOG_FILE
ALERT_NEEDED=true
fi
# Check for new admin users
echo "Checking admin users..." >> $LOG_FILE
ADMIN_COUNT=$(wp user list --role=administrator --format=count)
EXPECTED_ADMINS=2 # Set your expected count
if [ "$ADMIN_COUNT" -gt "$EXPECTED_ADMINS" ]; then
echo "WARNING: More admins than expected ($ADMIN_COUNT vs $EXPECTED_ADMINS)" >> $LOG_FILE
wp user list --role=administrator --fields=ID,user_login,user_registered >> $LOG_FILE
ALERT_NEEDED=true
fi
# Send alert if needed
if [ "$ALERT_NEEDED" = true ]; then
mail -s "WordPress Security Alert" $ADMIN_EMAIL < $LOG_FILE
fi
echo "Scan complete" >> $LOG_FILE
Automated Updates Script
Safe automated update process:
#!/bin/bash
# auto-update.sh
SITE_PATH="/var/www/html"
BACKUP_DIR="/var/backups/wordpress"
DATE=$(date +%Y%m%d_%H%M%S)
cd $SITE_PATH
# Create backup first
echo "Creating backup..."
mkdir -p $BACKUP_DIR
wp db export $BACKUP_DIR/database_$DATE.sql --allow-root
tar -czf $BACKUP_DIR/files_$DATE.tar.gz wp-content/
# Enable maintenance mode
wp maintenance-mode activate
# Update WordPress core
echo "Updating WordPress core..."
wp core update
wp core update-db
# Update plugins with compatibility check
echo "Updating plugins..."
for plugin in $(wp plugin list --update=available --field=name); do
echo "Updating plugin: $plugin"
wp plugin update $plugin
# Verify site still works
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost)
if [ "$HTTP_CODE" != "200" ]; then
echo "Error after updating $plugin - rolling back"
wp plugin install $plugin --version=previous --force
break
fi
done
# Update themes
echo "Updating themes..."
wp theme update --all
# Flush caches
wp cache flush
wp rewrite flush
# Disable maintenance mode
wp maintenance-mode deactivate
# Verify site is working
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost)
if [ "$HTTP_CODE" != "200" ]; then
echo "ERROR: Site not responding after updates"
# Restore from backup if needed
fi
echo "Updates complete"
Security Hardening Commands
Apply security configurations:
# Disable file editing
wp config set DISALLOW_FILE_EDIT true --raw
# Force SSL for admin
wp config set FORCE_SSL_ADMIN true --raw
# Disable debug mode
wp config set WP_DEBUG false --raw
# Set proper file permissions
find . -type d -exec chmod 755 {} ;
find . -type f -exec chmod 644 {} ;
chmod 400 wp-config.php
# Remove unused themes (keep one default)
wp theme list --status=inactive --field=name | grep -v twentytwentyfour | xargs -I {} wp theme delete {}
# Remove unused plugins
wp plugin list --status=inactive --field=name | xargs -I {} wp plugin delete {}
# Change database prefix (requires manual steps)
echo "Current table prefix: $(wp config get table_prefix)"
Monitoring and Alerting
Set up automated monitoring:
#!/bin/bash
# monitor-security.sh - Run via cron every hour
SITE_PATH="/var/www/html"
STATE_FILE="/var/run/wp-security-state"
cd $SITE_PATH
# Store current state
CURRENT_STATE=$(wp option get active_plugins --format=json | md5sum)
CURRENT_STATE+="_$(wp user list --role=administrator --format=count)"
CURRENT_STATE+="_$(find wp-content -name "*.php" | wc -l)"
# Compare with previous state
if [ -f "$STATE_FILE" ]; then
PREVIOUS_STATE=$(cat $STATE_FILE)
if [ "$CURRENT_STATE" != "$PREVIOUS_STATE" ]; then
echo "Security state changed - investigating..."
# Check what changed
wp plugin list --format=table
wp user list --role=administrator --format=table
# Send alert
echo "WordPress security state changed on $(hostname)" |
mail -s "WordPress State Change Alert" admin@example.com
fi
fi
echo "$CURRENT_STATE" > $STATE_FILE
Database Security
Database maintenance commands:
# Optimize database tables
wp db optimize
# Search for suspicious content
wp db query "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%eval(%' OR post_content LIKE '%base64_decode%'"
# Check for suspicious options
wp db query "SELECT option_name, LEFT(option_value, 100) FROM wp_options WHERE option_value LIKE '%
Cron Job Setup
Schedule security tasks:
# Add to crontab
# Run security scan daily at 3 AM
0 3 * * * /path/to/security-scan.sh
# Run updates weekly on Sunday at 2 AM
0 2 * * 0 /path/to/auto-update.sh
# Monitor changes hourly
0 * * * * /path/to/monitor-security.sh
# Verify checksums daily
0 4 * * * cd /var/www/html && wp core verify-checksums >> /var/log/wp-checksums.log 2>&1
Conclusion
WP-CLI security automation saves time and ensures consistent security maintenance. Combine these commands with proper monitoring and alerting for comprehensive WordPress protection.
Written by Sarah Chen
WP Folder Shield Team