WPScan 4.0.0 is here.
We read through years of community issues. We addressed every major complaint. 75+ open issues → 0. Explicit scan control. Authentication‑based enumeration. Real‑time streaming. Consolidated codebase.
This is WPScan shaped by what you asked for.

You Control What Gets Scanned
The #1 complaint: WPScan scanned plugins automatically, burning API requests and time you didn’t want to spend.
Now it doesn’t. By default, WPScan checks WordPress version, active theme, and security findings. Nothing else. Want plugins? Add ‑e ap. Want everything? Tell it what you want.
# 4.0 default: minimal scanwpscan --url example.com# Explicit vulnerable plugin scanwpscan --url example.com -e vp# For passive-only scanning (closer to old 3.x default behavior)wpscan --url example.com -e ap --plugins-detection passive
Your scan. Your rules.
Authentication-Based Scanning
Traditional scanners guess what’s installed by checking URLs and fingerprints. They miss things.
--wp‑auth changes that. Give WPScan a WordPress Application Password, and it queries the REST API directly for the authoritative list of every plugin and theme (active or inactive). Zero guessing. Zero false negatives.
wpscan --url example.com --wp-auth admin:"xxxxxxx"
Generate Application Passwords at Users → Profile → Application Passwords in wp‑admin.
Real-Time Results
Long scans suck when you’re waiting for output. --format jsonl streams findings as they’re discovered. Pipe to jq, monitor in real‑time, integrate with your tools.
# See results as they arrive
wpscan --url example.com -e ap --format jsonl | jq .
Resume Failed Attacks
Brute force attacks take hours. Network glitches shouldn’t mean starting over.
# Resume at line 5000
wpscan --url example.com -P wordlist.txt --wordlist-skip 5000
# Auto-retry failed requests
wpscan --url example.com -P wordlist.txt --max-retries 3
Everything Else
- Better context: active install counts, last updated dates, PoC links
- Better errors: clearer messages, helpful links, diagnostic info
- Better flexibility:
--follow‑redirect,--proxy‑target‑only,--exclude‑vulns - Better visibility: audit trails, HTTP status tracking
- SAML support:
--expect‑samlfor SAML‑authenticated sites - Backup enumeration:
‑e bffinds backup folders
Breaking Changes
Ruby 3.3+ required (Ruby 4.0 supported). Upgrade before installing 4.0.0.
Default enumeration changed. Plugins and config backups no longer auto‑scan. Use ‑e explicitly.
Detection mode options removed. --config‑backups‑detection, --db‑exports‑detection, --medias‑detection, --timthumbs‑detection are gone (they never worked properly anyway).
XDG directories. Database goes to $XDG_CACHE_HOME/wpscan/db (or ~/.cache/wpscan/db if not set), config to $XDG_CONFIG_HOME/wpscan/ (or ~/.config/wpscan/ if not set). Existing installs keep using ~/.wpscan/.
Built to Last
This isn’t just a cleanup release. We’re setting WPScan up for sustained maintenance:
- Three repos → one: cms_scanner and opt_parse_validator are now part of wpscan. No more coordinated multi‑repo PRs.
- Comprehensive tests: 8.5k+ lines migrated, E2E tests added, skipped tests implemented
- Modern CI/CD: faster builds, better coverage, security scanning
- One place to contribute: clearer architecture, easier onboarding
Get It
# Upgrade (if already installed)
gem update wpscan
# Or via Homebrew
brew upgrade wpscan
# Fresh install
gem install wpscan
# Or via Homebrew
brew tap wpscanteam/tap && brew install wpscan
# Docker
docker pull wpscanteam/wpscan:latest
For complete installation instructions, including system dependencies, see the README.
Get Involved
We’re back and actively maintaining WPScan. Here’s how to get involved:
Found a bug? Open an issue
Have a feature request? Start a discussion or open an issue
Want to contribute? Pull requests welcome – the codebase is cleaner and easier to contribute to than ever