WordPress security audit scanner — a clean-room, open-source alternative to WPScan, built for legitimate black-box security audits of WordPress installations you own or are authorized to test.
_ _ _ _
__ ___ __ ___| |__ (_) ___| | __| |
\ \ /\ / / '_ \ _____/ __| '_ \| |/ _ \ |/ _` |
\ V V /| |_) |____\__ \ | | | | __/ | (_| |
\_/\_/ | .__/ |___/_| |_|_|\___|_|\__,_|
|_|
- Component enumeration — WordPress core version, plugins, themes, users
- Misconfiguration detection — exposed
wp-config.phpbackups, debug logs, directory listings, dangerous xmlrpc/wp-cron exposure, missing security headers, open registration - CVE matching — local SQLite cache of the WPVulnerability.net feed (free, no API key, no commercial fee). Wordfence Intelligence v3 is supported as an opt-in source if you have a Bearer token (their previously-free v1/v2 endpoints returned HTTP 410 Gone in 2025).
- Multi-format reports — CLI tables (Rich), JSON, standalone HTML, SARIF 2.1.0 (GitHub Code Scanning)
- Polite by default — respects
robots.txt, rate-limited, identifies aswp-shield/0.1user-agent
- v0.2: Web dashboard (FastAPI + HTMX), scheduled scans
- v0.3: Headless Chromium mode (Playwright) for SPA WordPress sites
- v0.4: Opt-in authentication-stress module (gated by owned-domains allow-list)
pip install wp-shield
# or for development:
git clone https://github.com/pepperonas/wp-shield.git
cd wp-shield
pip install -e ".[dev]"# 1) Sync the local vulnerability database (~once per day, default source: WPVulnerability)
wp-shield update # default: source=wpvulnerability, plugin_limit=500, theme_limit=200
# or for Wordfence Intelligence (requires Bearer token):
# WORDFENCE_API_TOKEN=xxx wp-shield update --source wordfence
# 2) Run a scan — auto-saves report.{html,json,sarif,txt} into ./out/<timestamp>_<host>/
wp-shield scan https://example.com
# 3) Same scan but also open the HTML report in your browser when done
wp-shield scan https://example.com --open
# 4) Skip the on-disk artefact (CLI-only)
wp-shield scan https://example.com --no-save
# 5) Stream JSON to stdout (useful in pipelines)
wp-shield scan https://example.com --output json --no-save
# 6) Custom output directory (also configurable via config.yaml)
wp-shield scan https://example.com --output-dir /var/lib/wp-shield/scans
# 7) Database stats
wp-shield db statsEvery scan creates a timestamped subdirectory inside out/ (or your
configured output.output_dir):
out/
└── 20260529-185717_wpvulnerability.com/
├── report.txt # ANSI-stripped Rich CLI snapshot — audit-trail friendly
├── report.html # standalone styled report (open in browser)
├── report.json # full Pydantic dump (machine-readable)
└── report.sarif # SARIF 2.1.0 — upload to GitHub Code Scanning
out/ is in .gitignore by default so scan artefacts never get committed.
cd /Users/martin/claude/wp-shield && source .venv/bin/activate && \
wp-shield scan https://wpvulnerability.com/ --mode mixed --rate-limit 3 --openThis runs a polite mixed-mode scan, prints the live Rich table, writes all
four report formats into out/<timestamp>_wpvulnerability.com/, and opens
the HTML report in your default browser.
wpvulnerability.com/is used as the demo target because its maintainer publishes the very vulnerability data this tool consumes — it is an explicitly invited test surface. Replace the URL with any system you own or have written authorization to test.
--mode passive — analyze HTML only (zero "noisy" requests)
--mode mixed (default) — passive + targeted readme.txt / style.css probes
--mode aggressive — full plugin/theme wordlist enumeration (~1–10 min, may trigger WAFs)
Defaults can be overridden via ~/.config/wp-shield/config.yaml:
http:
timeout: 15
max_concurrency: 10
user_agent: "wp-shield/0.1 (+https://github.com/pepperonas/wp-shield)"
respect_robots_txt: true
rate_limit_per_second: 5
scan:
default_mode: mixed
enumerate_users: true
follow_redirects: truewp-shield is intended exclusively for authorized security testing. Running this tool against sites you do not own or have explicit written permission to test may be illegal in your jurisdiction (StGB §202a/b in Germany, Computer Fraud and Abuse Act in the US, UK Computer Misuse Act, etc.).
The author is not responsible for misuse. By using this software you agree that:
- You will only scan systems you own or are explicitly authorized to test
- You accept full responsibility for any consequences of running scans
- You will respect rate-limits,
robots.txt, and target system stability
The brute-force module (planned for v0.4) is deliberately gated behind a local ~/.config/wp-shield/owned-domains.txt allow-list to prevent accidental misuse.
- Stack: Python 3.11+,
httpx(async),BeautifulSoup+lxml,typer+rich(CLI),pydantic(models),sqlite3(vuln cache),jinja2(reports/UI) - Vuln data sources:
- Default: WPVulnerability.net — free, no API key, per-component lookup. We pre-warm the cache with the top-N plugin/theme slugs from a built-in wordlist.
- Optional: Wordfence Intelligence v3 — requires a free Bearer token since the 2025 v3 migration (their v1/v2 endpoints now return HTTP 410 Gone).
See docs/ARCHITECTURE.md (planned).
GPL-3.0-or-later — same license as the original WPScan and WPVulnerability projects.
Inspired by:
- WPScan (Ruby, GPL-3.0) — the reference implementation
- WPVulnerability — open vulnerability database
- Wordfence — for the free, commercial-use intelligence feed