{"id":51048339,"url":"https://github.com/pepperonas/wp-shield","last_synced_at":"2026-06-22T15:02:02.041Z","repository":{"id":361248580,"uuid":"1253725375","full_name":"pepperonas/wp-shield","owner":"pepperonas","description":"WordPress security audit scanner — clean-room WPScan alternative with free local CVE database (WPVulnerability.net + optional Wordfence v3). Python · async · CLI · JSON/HTML/SARIF reports.","archived":false,"fork":false,"pushed_at":"2026-05-29T18:58:56.000Z","size":73,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T20:21:54.786Z","etag":null,"topics":["async","cli","cve","httpx","infosec","pentest","python","sarif","security","security-audit","security-scanner","typer","vulnerability-scanner","wordpress","wpscan"],"latest_commit_sha":null,"homepage":"https://github.com/pepperonas/wp-shield","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pepperonas.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-29T18:50:35.000Z","updated_at":"2026-05-29T18:59:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pepperonas/wp-shield","commit_stats":null,"previous_names":["pepperonas/wp-shield"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pepperonas/wp-shield","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepperonas%2Fwp-shield","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepperonas%2Fwp-shield/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepperonas%2Fwp-shield/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepperonas%2Fwp-shield/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pepperonas","download_url":"https://codeload.github.com/pepperonas/wp-shield/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pepperonas%2Fwp-shield/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34653715,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","cli","cve","httpx","infosec","pentest","python","sarif","security","security-audit","security-scanner","typer","vulnerability-scanner","wordpress","wpscan"],"created_at":"2026-06-22T15:02:00.880Z","updated_at":"2026-06-22T15:02:02.028Z","avatar_url":"https://github.com/pepperonas.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wp-shield\n\n**WordPress security audit scanner** — a clean-room, open-source alternative to [WPScan](https://wpscan.com/), built for legitimate black-box security audits of WordPress installations you own or are authorized to test.\n\n\u003cp\u003e\n  \u003c!-- core project meta --\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/blob/main/LICENSE\"\u003e\u003cimg alt=\"License: GPL-3.0-or-later\" src=\"https://img.shields.io/badge/license-GPL--3.0--or--later-blue.svg\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"Python 3.11+\" src=\"https://img.shields.io/badge/python-3.11%20%7C%203.12-3776AB.svg?logo=python\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"Status: Beta\" src=\"https://img.shields.io/badge/status-beta-yellow.svg\"\u003e\n  \u003cimg alt=\"Version 0.1.0\" src=\"https://img.shields.io/badge/version-0.1.0-success.svg\"\u003e\n  \u003cimg alt=\"Platform: macOS · Linux · Raspberry Pi\" src=\"https://img.shields.io/badge/platform-macOS%20%C2%B7%20Linux%20%C2%B7%20Raspberry%20Pi-lightgrey.svg\"\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n  \u003c!-- tooling --\u003e\n  \u003cimg alt=\"Built with httpx\" src=\"https://img.shields.io/badge/async-httpx-005571.svg\"\u003e\n  \u003cimg alt=\"Typer CLI\" src=\"https://img.shields.io/badge/CLI-Typer-009688.svg\"\u003e\n  \u003cimg alt=\"Pydantic v2\" src=\"https://img.shields.io/badge/models-Pydantic%20v2-E92063.svg?logo=pydantic\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"SQLite\" src=\"https://img.shields.io/badge/storage-SQLite-003B57.svg?logo=sqlite\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"Linter: Ruff\" src=\"https://img.shields.io/badge/linter-Ruff-D7FF64.svg?logo=ruff\u0026logoColor=black\"\u003e\n  \u003cimg alt=\"Tests: pytest\" src=\"https://img.shields.io/badge/tests-pytest-0A9EDC.svg?logo=pytest\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"Output: SARIF 2.1.0\" src=\"https://img.shields.io/badge/output-SARIF%202.1.0-1f6feb.svg\"\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n  \u003c!-- dynamic GitHub badges (populate once the repo is public + has activity) --\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/actions/workflows/test.yml\"\u003e\u003cimg alt=\"CI\" src=\"https://github.com/pepperonas/wp-shield/actions/workflows/test.yml/badge.svg?branch=main\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/commits/main\"\u003e\u003cimg alt=\"Last commit\" src=\"https://img.shields.io/github/last-commit/pepperonas/wp-shield.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/issues\"\u003e\u003cimg alt=\"Open issues\" src=\"https://img.shields.io/github/issues/pepperonas/wp-shield.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/pulls\"\u003e\u003cimg alt=\"Open PRs\" src=\"https://img.shields.io/github/issues-pr/pepperonas/wp-shield.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/stargazers\"\u003e\u003cimg alt=\"GitHub stars\" src=\"https://img.shields.io/github/stars/pepperonas/wp-shield.svg?style=social\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/network/members\"\u003e\u003cimg alt=\"GitHub forks\" src=\"https://img.shields.io/github/forks/pepperonas/wp-shield.svg?style=social\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"Repo size\" src=\"https://img.shields.io/github/repo-size/pepperonas/wp-shield.svg\"\u003e\n  \u003cimg alt=\"Code size\" src=\"https://img.shields.io/github/languages/code-size/pepperonas/wp-shield.svg\"\u003e\n  \u003cimg alt=\"Top language\" src=\"https://img.shields.io/github/languages/top/pepperonas/wp-shield.svg\"\u003e\n  \u003cimg alt=\"Contributors\" src=\"https://img.shields.io/github/contributors/pepperonas/wp-shield.svg\"\u003e\n  \u003ca href=\"CONTRIBUTING.md\"\u003e\u003cimg alt=\"PRs welcome\" src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/pepperonas/wp-shield/blob/main/CHANGELOG.md\"\u003e\u003cimg alt=\"Keep a Changelog\" src=\"https://img.shields.io/badge/changelog-keep%20a%20changelog-orange.svg\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"Conventional Commits\" src=\"https://img.shields.io/badge/commits-conventional-FE5196.svg?logo=conventionalcommits\u0026logoColor=white\"\u003e\n\u003c/p\u003e\n\n\u003cp\u003e\n  \u003c!-- domain badges --\u003e\n  \u003cimg alt=\"Made for WordPress\" src=\"https://img.shields.io/badge/made%20for-WordPress-21759B.svg?logo=wordpress\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"Vuln source: WPVulnerability.net\" src=\"https://img.shields.io/badge/vuln%20source-WPVulnerability.net-darkgreen.svg\"\u003e\n  \u003cimg alt=\"Optional: Wordfence v3\" src=\"https://img.shields.io/badge/optional-Wordfence%20v3-FA0F00.svg\"\u003e\n  \u003cimg alt=\"OWASP-aligned\" src=\"https://img.shields.io/badge/OWASP-aligned-000000.svg\"\u003e\n  \u003cimg alt=\"Authorized-use only\" src=\"https://img.shields.io/badge/use-authorized%20targets%20only-red.svg\"\u003e\n\u003c/p\u003e\n\n```\n                          _     _      _     _\n__      ___ __        ___| |__ (_) ___| | __| |\n\\ \\ /\\ / / '_ \\ _____/ __| '_ \\| |/ _ \\ |/ _` |\n \\ V  V /| |_) |____\\__ \\ | | | |  __/ | (_| |\n  \\_/\\_/ | .__/     |___/_| |_|_|\\___|_|\\__,_|\n         |_|\n```\n\n## Features (v0.1)\n\n- **Component enumeration** — WordPress core version, plugins, themes, users\n- **Misconfiguration detection** — exposed `wp-config.php` backups, debug logs, directory listings, dangerous xmlrpc/wp-cron exposure, missing security headers, open registration\n- **CVE matching** — local SQLite cache of the [WPVulnerability.net](https://www.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).\n- **Multi-format reports** — CLI tables (Rich), JSON, standalone HTML, SARIF 2.1.0 (GitHub Code Scanning)\n- **Polite by default** — respects `robots.txt`, rate-limited, identifies as `wp-shield/0.1` user-agent\n\n## Roadmap\n\n- v0.2: Web dashboard (FastAPI + HTMX), scheduled scans\n- v0.3: Headless Chromium mode (Playwright) for SPA WordPress sites\n- v0.4: Opt-in authentication-stress module (gated by owned-domains allow-list)\n\n## Installation\n\n```bash\npip install wp-shield\n# or for development:\ngit clone https://github.com/pepperonas/wp-shield.git\ncd wp-shield\npip install -e \".[dev]\"\n```\n\n## Quickstart\n\n```bash\n# 1) Sync the local vulnerability database (~once per day, default source: WPVulnerability)\nwp-shield update                # default: source=wpvulnerability, plugin_limit=500, theme_limit=200\n# or for Wordfence Intelligence (requires Bearer token):\n# WORDFENCE_API_TOKEN=xxx wp-shield update --source wordfence\n\n# 2) Run a scan — auto-saves report.{html,json,sarif,txt} into ./out/\u003ctimestamp\u003e_\u003chost\u003e/\nwp-shield scan https://example.com\n\n# 3) Same scan but also open the HTML report in your browser when done\nwp-shield scan https://example.com --open\n\n# 4) Skip the on-disk artefact (CLI-only)\nwp-shield scan https://example.com --no-save\n\n# 5) Stream JSON to stdout (useful in pipelines)\nwp-shield scan https://example.com --output json --no-save\n\n# 6) Custom output directory (also configurable via config.yaml)\nwp-shield scan https://example.com --output-dir /var/lib/wp-shield/scans\n\n# 7) Database stats\nwp-shield db stats\n```\n\n### Auto-save layout\n\nEvery scan creates a timestamped subdirectory inside `out/` (or your\nconfigured `output.output_dir`):\n\n```\nout/\n└── 20260529-185717_wpvulnerability.com/\n    ├── report.txt    # ANSI-stripped Rich CLI snapshot — audit-trail friendly\n    ├── report.html   # standalone styled report (open in browser)\n    ├── report.json   # full Pydantic dump (machine-readable)\n    └── report.sarif  # SARIF 2.1.0 — upload to GitHub Code Scanning\n```\n\n`out/` is in `.gitignore` by default so scan artefacts never get committed.\n\n### One-liner: live demo against a public WordPress site\n\n```bash\ncd /Users/martin/claude/wp-shield \u0026\u0026 source .venv/bin/activate \u0026\u0026 \\\n  wp-shield scan https://wpvulnerability.com/ --mode mixed --rate-limit 3 --open\n```\n\nThis runs a polite mixed-mode scan, prints the live Rich table, writes all\nfour report formats into `out/\u003ctimestamp\u003e_wpvulnerability.com/`, and opens\nthe HTML report in your default browser.\n\n\u003e `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**.\n\n## Detection Modes\n\n`--mode passive` — analyze HTML only (zero \"noisy\" requests)\n`--mode mixed` _(default)_ — passive + targeted readme.txt / style.css probes\n`--mode aggressive` — full plugin/theme wordlist enumeration (~1–10 min, may trigger WAFs)\n\n## Configuration\n\nDefaults can be overridden via `~/.config/wp-shield/config.yaml`:\n\n```yaml\nhttp:\n  timeout: 15\n  max_concurrency: 10\n  user_agent: \"wp-shield/0.1 (+https://github.com/pepperonas/wp-shield)\"\n  respect_robots_txt: true\n  rate_limit_per_second: 5\n\nscan:\n  default_mode: mixed\n  enumerate_users: true\n  follow_redirects: true\n```\n\n## Legal \u0026 Ethics\n\n`wp-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.).\n\nThe author is not responsible for misuse. By using this software you agree that:\n\n1. You will only scan systems you own or are explicitly authorized to test\n2. You accept full responsibility for any consequences of running scans\n3. You will respect rate-limits, `robots.txt`, and target system stability\n\nThe 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.\n\n## Architecture\n\n- **Stack**: Python 3.11+, `httpx` (async), `BeautifulSoup` + `lxml`, `typer` + `rich` (CLI), `pydantic` (models), `sqlite3` (vuln cache), `jinja2` (reports/UI)\n- **Vuln data sources**:\n  - **Default**: [WPVulnerability.net](https://www.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.\n  - **Optional**: [Wordfence Intelligence v3](https://www.wordfence.com/products/wordfence-intelligence/) — requires a free Bearer token since the 2025 v3 migration (their v1/v2 endpoints now return HTTP 410 Gone).\n\nSee `docs/ARCHITECTURE.md` (planned).\n\n## License\n\nGPL-3.0-or-later — same license as the original WPScan and WPVulnerability projects.\n\n## Acknowledgements\n\nInspired by:\n- [WPScan](https://github.com/wpscanteam/wpscan) (Ruby, GPL-3.0) — the reference implementation\n- [WPVulnerability](https://www.wpvulnerability.com/) — open vulnerability database\n- [Wordfence](https://www.wordfence.com/) — for the free, commercial-use intelligence feed\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpepperonas%2Fwp-shield","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpepperonas%2Fwp-shield","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpepperonas%2Fwp-shield/lists"}