Wordfence CLI
** Wordfence CLI – Malware Scanning & WordPress Security Hardening for VPS**
Wordfence CLI is a command-line malware scanner developed by Wordfence. It is designed to protect WordPress sites by scanning files for threats like backdoors, trojans, web shells, and malicious injections. Unlike the Wordfence plugin, Wordfence CLI runs outside WordPress and does not require PHP execution from inside WordPress, making it more secure and performance-friendly for VPS environments.
Purpose and Position in Security Stack
Wordfence CLI is part of Application Layer Security Hardening and works alongside UFW, Fail2Ban, SSH hardening, ModSecurity, and Cloudflare rules.
- Network layer: UFW, Cloudflare, VPN
- SSH layer: Key auth, disable root, rate limit
- IDS layer: Fail2Ban
- Web Application layer: ModSecurity, WAF
- Application Anti-Malware layer: Wordfence CLI
- Backup layer: Rsync, Rclone, snapshots
What You Will Learn
- What Wordfence CLI is and when to use it
- Installation and environment requirements
- Core syntax formula and scan commands
- Configuration options and flags
- Performance optimization
- Malware scan strategies for multi-site VPS
- Workflow for automation
- Real use cases for malware response
- Best practices and limitations
- Cheat sheet and mini-quiz
Prerequisites
- VPS running Ubuntu 20.04/22.04/24.04
- OpenLiteSpeed stack
- wp-cli installed
- Curl + PHP + Zip enabled
- 64-bit Linux environment
- Root or sudo access
- Valid Wordfence CLI API key (Free license OK)
Core Syntax Formula
wordfence verify-key <API_KEY>
wordfence scan <PATH> [OPTIONS]
wordfence version
wordfence help
Installation
5.1 Install Dependencies
sudo apt update
sudo apt install php php-cli php-curl php-zip unzip curl -y
5.2 Download Wordfence CLI
curl -O https://www.wordfence.com/wordfence-cli/wordfence
chmod +x wordfence
sudo mv wordfence /usr/local/bin/
5.3 Verify Installation
wordfence version
Expected output:
Wordfence CLI version X.X.X
5.4 Register License (Free Available)
wordfence verify-key YOUR_API_KEY
Commands and Options Reference
| Command | Description |
|---|---|
| wordfence scan PATH | Scan directory for malware |
| wordfence version | Check CLI version |
| wordfence verify-key | Activate license |
| wordfence help | Show help |
Common Options
| Option | Description |
|---|---|
| --no-scan-plugins | Skip plugins folder |
| --no-scan-themes | Skip themes |
| --no-scan-core | Skip wp core |
| --file-scan-size | Limit scan size |
| --exclude | Exclude paths |
| --output | Write results to file |
| --log | Enable logging |
| --timeout | Set scan timeout |
| --threads | Multi-thread scanning |
| --memory-limit | Control memory usage |
Example Scans
7.1 Scan single WordPress site
wordfence scan /home/user/site1/public_html
7.2 Scan all sites on VPS
wordfence scan /home
7.3 Scan with exclusions
wordfence scan /home --exclude=/home/user/backup
7.4 Fast scan mode
wordfence scan /home/user/site1/public_html --no-scan-core --threads=4
Malware Response Workflow
-
Identify infected files:
wordfence scan /home/user/site1/public_html --output=malware.txt -
Open report:
cat malware.txt -
Backup infected files:
mkdir infected && cp $(cat malware.txt | awk '{print $1}') infected/ -
Delete/clean manually
-
Patch vulnerabilities
-
Re-scan
Scheduling and Automation
Cron job daily scan:
crontab -e
Add:
0 3 * * * wordfence scan /home --output=/var/log/wf-scan.log
Performance Optimization
| Option | Purpose |
|---|---|
| --threads=4 | Parallel scanning |
| --timeout=900 | Avoid hang |
| --exclude | Reduce scan scope |
| --file-scan-size=10M | Speed scan |
Best Practices
- Run weekly malware scan
- Store logs in
/var/log - Combine with UFW + Fail2Ban + Cloudflare
- Disable write permissions after deploy
- Scan backups before restore
- Use
.wp-cliconfig for large sites
Limitations
| Limitation | Description |
|---|---|
| No automatic cleaning | Manual action required |
| API key required | Free plan ok but limited |
| PHP memory dependent | Scan may fail low memory |
| File only | Does not scan DB malware |
Cheat Sheet
| Task | Command |
|---|---|
| Verify license | wordfence verify-key KEY |
| Scan site | wordfence scan /home/site |
| Fast scan | wordfence scan /home --threads=4 |
| Exclude dirs | --exclude=/path |
| Output result | --output=malware.txt |
Mini Quiz (5 Questions)
- What security layer does Wordfence CLI belong to?
- Can Wordfence CLI remove malware automatically?
- What flag is used to exclude folders?
- How to schedule automated scans?
- Should you scan backups before restore? Why?
Advanced Configuration
15.1 Set Global Config Directory
Create directory to store logs and configs:
sudo mkdir -p /etc/wordfence-cli
sudo mkdir -p /var/log/wordfence
sudo chown -R $USER:$USER /etc/wordfence-cli /var/log/wordfence
15.2 Configure Runtime Settings
Example config /etc/wordfence-cli/wf.conf:
threads=4
memory_limit=512M
timeout=1200
scan_images=true
scan_archives=true
log=/var/log/wordfence/scan.log
Run using config:
wordfence scan /home --config=/etc/wordfence-cli/wf.conf
Multi-Site Scan Automation (VPS with many WordPress sites)
16.1 Detect all WP installations
find /home -type f -name "wp-config.php"
16.2 Auto Scan All Sites Script
#!/bin/bash
SITES=$(find /home -type f -name "wp-config.php" -printf '%h\n')
for SITE in $SITES; do
echo "Scanning: $SITE"
wordfence scan $SITE --threads=4 --output=$SITE-scan.log
done
Threat Response Playbook
| Severity | Example Threat | Action |
|---|---|---|
| High | PHP web shell, backdoor | Quarantine + root cause check |
| Medium | Suspicious eval() injection | Review + clean |
| Low | Modified plugin file | Compare with original version |
| Critical | Malware persists | Full site isolation |
Action Steps (Standard Procedure)
-
Isolate infection:
chmod -R 000 /home/user/site1/public_html/wp-content/uploads -
Backup infected files:
tar -czf infected-backup.tar.gz $(cat malware.txt) -
Remove malware:
sed -i '/base64_decode/d' infected-file.php -
Patch access:
- Rotate WP salts
- Reset SFTP/SSH passwords
- Change DB user password
-
Re-scan:
wordfence scan /home/user/site1/public_html
Integration with UFW + Fail2Ban + Cloudflare
| Layer | Tool | Purpose |
|---|---|---|
| Network | UFW | Block unused ports |
| SSH | Fail2Ban | Brute force protection |
| CDN/WAF | Cloudflare | Block bad bots |
| Anti-malware | Wordfence CLI | Detect file-level threats |
Logging and Reporting
19.1 Write logs
wordfence scan /home --log=/var/log/wordfence/scan.log
19.2 View last scan
tail -n 50 /var/log/wordfence/scan.log
19.3 Filter infected files only
grep "MALWARE" /var/log/wordfence/scan.log
Advanced Use Cases
20.1 Scan only changed files in last 48 hours
find /home/user/site1/public_html -type f -mtime -2 -print0 | xargs -0 wordfence scan
20.2 Exclude cache folders
wordfence scan /home --exclude=cache,tmp
20.3 Scan uploaded files only
wordfence scan /home/user/site1/public_html/wp-content/uploads
Security Automation Scripts
21.1 Auto-Isolate Infected Files
wordfence scan /home/user/site1 --output=mal.txt
mkdir quarantine
xargs -a mal.txt -I{} mv {} quarantine/
21.2 Auto Email Report
wordfence scan /home/user/site1 --output=/tmp/scan.log
mail -s "Wordfence Scan Result" admin@example.com < /tmp/scan.log
Incident Response: One-Command Recovery
Clone fresh WP core:
wp core download --force --skip-content
Compare and restore:
diff -r wp-admin/ clean-core/wp-admin/
Best Practices – Strict VPS Policy
- Scan uploads daily
- Disable write access for wp-config.php
- Block php in uploads directory using
.htaccess - Block dangerous PHP functions in php.ini
- Combine file scan + db scan (search base64, eval)
Real Attack Patterns to Watch
| Pattern | Risk |
|---|---|
eval(base64_decode | Malware obfuscation |
assert($_POST[ | Remote code exec |
preg_replace /e | Hidden webshell |
.ico PHP payload | Hidden malware |
random wp-tmp.php | Backdoor dropper |
Cheat Sheet – Command Quickfire
| Task | Command |
|---|---|
| Full scan | wordfence scan /home |
| Fast scan | --no-scan-core |
| Skip plugins | --no-scan-plugins |
| Exclude cache | --exclude=cache |
| Output to file | --output=scan.txt |
Mini Quiz (Advanced)
- How do you schedule VPS-wide scans?
- Which flag controls CPU usage?
- What is the best folder to quarantine malware?
- Why scan uploads separately?
- How to detect obfuscated malware?
Enterprise Use Strategy
| Scenario | Implementation |
|---|---|
| Multi-client WordPress server | Centralized scan job + site-level quarantine |
| High-risk agency environment | Upload scan enforcement |
| Shared Linux accounts | Per-user isolation strategy |
| Production eCommerce site | Incremental scan strategy + rollback plan |
Safe Scan Pipeline (Standard Operating Procedure)
[Scan] → [Verify] → [Quarantine] → [Patch] → [Harden] → [Re-scan] → [Deploy]
Bash Safety Wrappers
29.1 Scan wrapper (safer execution)
#!/bin/bash
TARGET=$1
LOG=/var/log/wordfence/scan-$(date +%F).log
wordfence scan $TARGET --threads=4 --output=$LOG
29.2 Auto block PHP malware inside uploads
find /home -path "*/uploads/*" -name "*.php" -exec mv {} quarantine/ \;
Upload Protection (Zero Malware Upload Policy)
30.1 Real-time enforcement script
Add in cron every 5 minutes:
*/5 * * * * find /home/*/public_html/wp-content/uploads -type f -name "*.php" -delete
30.2 Nginx/OpenLiteSpeed-level hardening
Block PHP inside uploads:
location ~* /wp-content/uploads/.*\.php$ { deny all; }
Defensive Backup Strategy
| Problem | Risk | Solution |
|---|---|---|
| Backups contain malware | Reinfection | Scan backups weekly |
| Infection spreads to new servers | Persistent malware | Scan before restore |
| Unsafe restore | Data loss | Backup quarantine |
31.1 Scan backup directory
wordfence scan /backup --threads=4
Log Security and Audit Trail
32.1 Log scan history centralized
grep "MALWARE" /var/log/wordfence/*.log
32.2 Track highest risk sites
grep -R "MALWARE FOUND" /var/log/wordfence | cut -d: -f1 | uniq -c | sort -nr
Team Workflow (Agency Model)
| Role | Responsibility |
|---|---|
| Security Lead | Approves actions |
| DevOps | Runs CLI scans |
| WP Engineer | Cleans malware |
| Compliance | Keeps reports |
Email and Alert Integration
34.1 Send alert if malware is found
if grep -q "MALWARE" scan.log; then
mail -s "ALERT: Malware Found" admin@example.com < scan.log
fi
Scheduled VPS Protection
| Schedule | Task |
|---|---|
| Daily | wp uploads scan |
| Every 3 days | system-wide scan |
| Weekly | full malware and signature update |
| Monthly | retention cleanup |
Integration with Rclone + Rsync
Prevent malware inside backups
wordfence scan /backup-before-rclone
rclone copy /backup clean-storage:
CPU & Memory Tuning
| Flag | Use |
|---|---|
| --threads | Control CPU |
| --timeout | Prevent hangs |
| --memory-limit | Prevent OOM kill |
Advanced Protection Rules
| Detection Pattern | Command |
|---|---|
| Base64 malware search | grep -R "base64_decode" . |
| PHP obfuscation | grep -R "eval(" . |
| Infected backdoor users | grep -R "wp-create-user" . |
Incident Categories
| Category | Example | Action |
|---|---|---|
| Red (Critical) | active web shell | isolate immediately |
| Yellow | obfuscated spam links | clean |
| Blue | modified plugin file | compare |
| Grey | false warning | ignore |
Scan + Clean Automation (Quick)
wordfence scan /home --output=mal.txt
mkdir quarantine
xargs -a mal.txt -I{} mv {} quarantine/
Full Security Pipeline
UFW + Fail2Ban + SSH Hardening
↓
Cloudflare Firewall Rules
↓
ModSecurity WAF
↓
Wordfence CLI File Scan
↓
Backup Integrity Check
↓
Automation + Logs + Alerts
Risk Rating Table
| Threat | Risk 1–100 | Detection by Wordfence CLI |
|---|---|---|
| PHP Backdoor | 95 | Yes |
| Malware Upload | 87 | Yes |
| SQL Injection | 50 | No |
| Brute Force | 30 | No |
| XML-RPC attack | 40 | No |
Final Cheat Sheet
| Task | Command |
|---|---|
| Full scan | wordfence scan /home |
| Log view | tail -f /var/log/wordfence |
| Exclude dirs | --exclude |
| Upload clean | find uploads -name "*.php" -delete |
Final Mini Quiz (Advanced)
- Why scan backups before restore?
- How do you stop PHP execution in uploads?
- What does quarantine folder do?
- Which threats are NOT detected by Wordfence CLI?
- Why combine Wordfence CLI with UFW and Fail2Ban?