{"id":49108329,"url":"https://github.com/Plecost/plecost","last_synced_at":"2026-05-07T09:01:05.029Z","repository":{"id":15112138,"uuid":"17839039","full_name":"Plecost/plecost","owner":"Plecost","description":"Plecost - Professional WordPress Security Scanner","archived":false,"fork":false,"pushed_at":"2026-05-06T13:32:19.000Z","size":44123,"stargazers_count":372,"open_issues_count":0,"forks_count":81,"subscribers_count":28,"default_branch":"main","last_synced_at":"2026-05-06T15:39:16.894Z","etag":null,"topics":["security","security-tools","vulnerability","wordpress"],"latest_commit_sha":null,"homepage":"","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/Plecost.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"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":"2014-03-17T18:39:04.000Z","updated_at":"2026-05-06T13:32:48.000Z","dependencies_parsed_at":"2022-08-07T08:00:54.373Z","dependency_job_id":"ca363ada-930e-4e4b-8e48-6abee0fd332c","html_url":"https://github.com/Plecost/plecost","commit_stats":{"total_commits":95,"total_committers":7,"mean_commits":"13.571428571428571","dds":"0.17894736842105263","last_synced_commit":"4895e345d71bffe956be43530632e303dd379a5f"},"previous_names":["plecost/plecost"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/Plecost/plecost","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Plecost%2Fplecost","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Plecost%2Fplecost/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Plecost%2Fplecost/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Plecost%2Fplecost/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Plecost","download_url":"https://codeload.github.com/Plecost/plecost/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Plecost%2Fplecost/sbom","scorecard":{"id":488817,"data":{"date":"2025-08-11","repo":{"name":"github.com/iniqua/plecost","commit":"4895e345d71bffe956be43530632e303dd379a5f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.5,"checks":[{"name":"Code-Review","score":1,"reason":"Found 3/26 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating python:3.6-slim to python:3.6-slim@sha256:2cfebc27956e6a55f78606864d91fe527696f9e32a724e6f9702b5f9602d0474","Warn: pipCommand not pinned by hash: Dockerfile:7-8","Warn: pipCommand not pinned by hash: Dockerfile:7-8","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact latest not signed: https://api.github.com/repos/iniqua/plecost/releases/46187659","Warn: release artifact latest does not have provenance: https://api.github.com/repos/iniqua/plecost/releases/46187659"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'develop'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 7 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"18 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2023-120 / GHSA-45c4-8wx5-qw6w","Warn: Project is vulnerable to: GHSA-5m98-qgg9-wh84","Warn: Project is vulnerable to: GHSA-7gpw-8wmc-pm8g","Warn: Project is vulnerable to: GHSA-8495-4g3g-x7pr","Warn: Project is vulnerable to: PYSEC-2024-26 / GHSA-8qpw-xqxj-h4r2","Warn: Project is vulnerable to: GHSA-9548-qrrj-x5pj","Warn: Project is vulnerable to: PYSEC-2023-246 / GHSA-gfw2-4jvh-wgfg","Warn: Project is vulnerable to: GHSA-pjjw-qhg8-p2p9","Warn: Project is vulnerable to: PYSEC-2023-250 / GHSA-q3qx-c6g2-7pw2","Warn: Project is vulnerable to: PYSEC-2023-251 / GHSA-qvrw-v9rv-5rjx","Warn: Project is vulnerable to: PYSEC-2021-76 / GHSA-v6wp-4m6f-gcjg","Warn: Project is vulnerable to: PYSEC-2023-247 / GHSA-xx9p-xxvh-7g8j","Warn: Project is vulnerable to: GHSA-55x5-fj6c-h6m8","Warn: Project is vulnerable to: PYSEC-2014-9 / GHSA-57qw-cc2g-pv5p","Warn: Project is vulnerable to: PYSEC-2021-19 / GHSA-jq4v-f5q6-mjqq","Warn: Project is vulnerable to: GHSA-pgww-xf46-h92r","Warn: Project is vulnerable to: PYSEC-2022-230 / GHSA-wrxv-2j5q-m38w","Warn: Project is vulnerable to: PYSEC-2018-12 / GHSA-xp26-p53h-6h2p"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T18:31:55.820Z","repository_id":15112138,"created_at":"2025-08-19T18:31:55.821Z","updated_at":"2025-08-19T18:31:55.821Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32730282,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["security","security-tools","vulnerability","wordpress"],"created_at":"2026-04-21T03:00:45.961Z","updated_at":"2026-05-07T09:01:05.011Z","avatar_url":"https://github.com/Plecost.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://avatars.githubusercontent.com/u/275428243?s=200\u0026u=235faecc7c473dc147aa16990cbada030e4703c5\u0026v=4\" alt=\"Plecost\" width=\"120\" /\u003e\n  \u003ch1\u003ePlecost\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eProfessional WordPress Security Scanner\u003c/strong\u003e\u003c/p\u003e\n  \u003cp\u003eAsync-first, library-friendly, no external API required.\u003c/p\u003e\n\n  [![CI](https://github.com/Plecost/plecost/actions/workflows/ci.yml/badge.svg)](https://github.com/Plecost/plecost/actions)\n  [![PyPI](https://img.shields.io/pypi/v/plecost.svg)](https://pypi.org/project/plecost/)\n  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://python.org)\n  [![Docker](https://img.shields.io/badge/docker-ghcr.io%2Fplecost%2Fplecost-blue)](https://ghcr.io/plecost/plecost)\n  [![License: PolyForm NC](https://img.shields.io/badge/License-PolyForm%20NC%201.0-lightgrey)](https://polyformproject.org/licenses/noncommercial/1.0.0/)\n\u003c/div\u003e\n\n---\n\n## Table of Contents\n\n- [What is Plecost?](#what-is-plecost)\n- [Plecost vs WPScan](#plecost-vs-wpscan)\n- [Quick Start](#quick-start)\n- [Installation](#installation)\n- [CVE Database](#cve-database)\n- [Scanning](#scanning)\n- [Detection Modules](#detection-modules)\n- [WooCommerce Security](#woocommerce-security)\n- [WP eCommerce Security](#wp-ecommerce-security)\n- [Output Formats](#output-formats)\n- [Library Usage](#library-usage)\n- [Environment Variables](#environment-variables)\n- [Architecture](#architecture)\n- [Troubleshooting](#troubleshooting)\n- [Local Test Environment](#local-test-environment)\n- [License](#license)\n\n---\n\n## What is Plecost?\n\nPlecost detects vulnerabilities in WordPress installations — core, plugins, and themes — and correlates findings against a daily-updated local CVE database. It runs as a CLI tool, a Python library, or inside task queues like Celery, with a consistent and automation-friendly output format.\n\n**No Ruby. No API key. No subscription. No data sent to third parties on every scan.**\n\n\n## Plecost vs WPScan\n\nPlecost was built from scratch to fix the limitations teams hit in production when using WPScan: API rate caps, external data dependencies, no library API, no async architecture, and a narrow detection surface.\n\n### At a Glance\n\n| Capability | Plecost v4 | WPScan |\n|---|:---:|:---:|\n| **Language / runtime** | Python 3.11+ | Ruby |\n| **Async concurrent scanning** | ✅ httpx + asyncio | ❌ |\n| **Python library API** | ✅ `from plecost import Scanner` | ❌ |\n| **API key required** | ❌ never | ⚠️ required for CVE data |\n| **CVE data — free tier limit** | ✅ unlimited (local DB) | ❌ 25 API tokens/day |\n| **Offline scanning (CVEs included)** | ✅ | ❌ |\n| **Data sent to third parties on scan** | ❌ none | ⚠️ every request |\n| **Docker native** | ✅ | ✅ |\n| **Celery / task queue compatible** | ✅ | ❌ |\n| **PostgreSQL support (shared team)** | ✅ | ❌ |\n\n### Scanning Capabilities\n\n| Capability | Plecost v4 | WPScan |\n|---|:---:|:---:|\n| Fast mode (top 150 plugins / 50 themes) | ✅ | ❌ |\n| Deep mode (4,750+ plugins / 900+ themes) | ✅ | ✅ |\n| Configurable concurrency (10–50 requests) | ✅ | ✅ |\n| Stealth mode (random UA + passive only) | ✅ | ✅ |\n| Aggressive mode (50 parallel requests) | ✅ | ✅ |\n| Authenticated scans | ✅ | ✅ |\n| Proxy support (HTTP + SOCKS5) | ✅ | ✅ |\n| Bulk scan (multiple URLs from file) | ✅ | ❌ |\n| Pre-flight 403 detection (aborts cleanly) | ✅ | ❌ |\n| Per-module options (`--module-option`) | ✅ | ❌ |\n| Run / skip individual modules | ✅ | ✅ |\n| Selective module list (`--modules`) | ✅ | ❌ |\n| Auto-retry with SSL verification disabled | ✅ | ❌ |\n\n### Vulnerability Detection\n\n| Capability | Plecost v4 | WPScan |\n|---|:---:|:---:|\n| WordPress core fingerprinting | ✅ (meta, readme, RSS, wp-login) | ✅ |\n| Plugin detection — passive HTML | ✅ | ✅ |\n| Plugin detection — active wordlist | ✅ 4,750+ slugs | ✅ |\n| Theme detection — passive HTML | ✅ | ✅ |\n| Theme detection — active wordlist | ✅ 900+ themes | ✅ |\n| CVE correlation (core + plugins + themes) | ✅ local DB, daily NVD sync | ✅ API |\n| Exploit availability flag per CVE | ✅ | ✅ |\n| CVSS scores per finding | ✅ | ✅ |\n| WAF / CDN detection | ✅ 7 providers | ⚠️ limited |\n| User enumeration — REST API | ✅ | ✅ |\n| User enumeration — author archives | ✅ | ✅ |\n| XML-RPC — access, pingback DoS, method list | ✅ 3 checks | ⚠️ basic |\n| REST API — disclosure, oEmbed, CORS | ✅ 3 checks | ❌ |\n| HTTP security headers | ✅ 8 checks (HSTS, CSP, X-Frame…) | ❌ |\n| SSL / TLS misconfiguration | ✅ 3 checks | ❌ |\n| Misconfiguration (wp-config, .env, .git…) | ✅ 12 checks | ⚠️ partial |\n| Directory listing (wp-content subdirs) | ✅ | ❌ |\n| Debug mode / PHP version disclosure | ✅ | ❌ |\n| Open user registration | ✅ | ❌ |\n| Content / card skimmer analysis | ✅ scripts, iframes, hardcoded keys | ❌ |\n| Webshell detection | ✅ 147–523 paths | ❌ |\n| Malicious upload detection (PHP in uploads) | ✅ | ❌ |\n| **WooCommerce dedicated module** | ✅ 22 checks | ❌ |\n| **WP eCommerce dedicated module** | ✅ 22 checks | ❌ |\n| Semi-active eCommerce CVE probes | ✅ boolean-only, no time-based | ❌ |\n| WooCommerce REST API auth bypass | ✅ CVE-2023-28121 | ❌ |\n| WooCommerce IDOR / PII disclosure | ✅ CVE-2023-34000 | ❌ |\n\n### Output and Integration\n\n| Capability | Plecost v4 | WPScan |\n|---|:---:|:---:|\n| Rich terminal output (color-coded) | ✅ | ✅ |\n| JSON output (stable schema) | ✅ | ✅ |\n| Verbose real-time progress (`-v`) | ✅ | ✅ |\n| Quiet mode (HIGH + CRITICAL only) | ✅ | ❌ |\n| **Stable permanent finding IDs** | ✅ 79 IDs (`PC-MOD-NNN`) | ❌ |\n| `plecost explain \u003cID\u003e` — per-finding remediation | ✅ | ❌ |\n| Safe to track findings in JIRA / ticketing | ✅ IDs never change | ❌ |\n| Remediation ID per finding (`REM-MOD-NNN`) | ✅ | ❌ |\n| i18n / multilingual output | ✅ EN + ES | ❌ |\n| Included vulnerable test environment (DVWP) | ✅ Docker Compose | ❌ |\n\n### Data Independence\n\n\u003e WPScan sends every scan to `wpscan.com` to look up CVE data. On the free tier you get **25 API tokens per day** — enough for a handful of targets. Plecost keeps the entire CVE database locally, updated daily via GitHub Actions with no per-scan network call to any third-party API.\n\n| | Plecost v4 | WPScan |\n|---|:---:|:---:|\n| Local CVE database (SQLite / PostgreSQL) | ✅ | ❌ |\n| Data sent externally on each scan | ❌ none | ✅ to wpscan.com |\n| CVE updates mechanism | GitHub Actions, NVD API v2 | SaaS subscription |\n| Daily incremental patch download | ✅ (\u003c 100 KB/day) | — |\n| First-run full database download | ✅ `plecost update-db` | — |\n| Works fully air-gapped after DB download | ✅ | ❌ |\n| SHA256 integrity check before download | ✅ | ❌ |\n\n\n## Quick Start\n\n```bash\npip install plecost\n\n# Download the CVE database (first time only — takes a few seconds)\nplecost update-db\n\n# Scan a target\nplecost scan https://target.wordpress.com\n```\n\nThat's it. No account, no API key, no daemon running in the background.\n\n\n## Installation\n\n**pip**\n\n```bash\npip install plecost\npip install plecost[fast]      # adds uvloop for higher throughput\npip install plecost[postgres]  # adds asyncpg for PostgreSQL support\n```\n\n**Docker**\n\n```bash\ndocker run --rm ghcr.io/plecost/plecost scan https://target.com\n\n# Save JSON report to local directory\ndocker run --rm -v $(pwd):/data ghcr.io/plecost/plecost scan https://target.com \\\n  --output /data/report.json\n```\n\n**From source**\n\n```bash\ngit clone https://github.com/Plecost/plecost.git\ncd plecost\npip install -e \".[dev]\"\n```\n\n\n## CVE Database\n\nPlecost ships with a **local SQLite database** covering WordPress core, plugins, and themes. It lives at `~/.plecost/db/plecost.db` and is never sent to any external service during scans.\n\n**The database needs to be downloaded once before the first scan, and kept up to date thereafter.**\n\n### First-time setup\n\n```bash\nplecost update-db\n```\n\nThis downloads a pre-built snapshot from [plecost-db releases](https://github.com/Plecost/plecost-db/releases) (~10–50 MB). Subsequent runs only download the daily diff — typically under 100 KB.\n\n### Keeping it current\n\nRun `update-db` regularly (weekly is fine for most use cases):\n\n```bash\nplecost update-db\n```\n\nPlecost checks a SHA256 checksum before downloading anything. If nothing changed since your last run, no data is transferred.\n\n### How the update mechanism works\n\nThe [plecost-db](https://github.com/Plecost/plecost-db) repository runs a GitHub Actions workflow daily at 02:00 UTC. It queries the [NVD API v2.0](https://nvd.nist.gov/developers/vulnerabilities) for all WordPress-related CVEs modified in the last 24 hours, applies Jaro-Winkler fuzzy matching to correlate CVE product names against ~50,000 known plugin/theme slugs, and publishes a small JSON patch file as a release asset.\n\nWhen you run `plecost update-db`, it:\n1. Downloads `index.json` from the `plecost-db` releases (64 bytes)\n2. Compares its SHA256 against the local copy\n3. Downloads only the missing patch files and applies them in order\n4. On first run, downloads `full.json` instead (complete history)\n\n| Run | What's downloaded | Typical size |\n|-----|-------------------|--------------|\n| First time | `full.json` (all CVEs) | 10–50 MB |\n| Daily update | today's patch | \u003c 100 KB |\n| Already up to date | nothing (checksum match) | 64 bytes |\n\n### Custom database location\n\n```bash\n# SQLite at a custom path\nexport PLECOST_DB_URL=sqlite:////data/plecost.db\nplecost update-db\nplecost scan https://target.com\n\n# PostgreSQL (shared team setup)\npip install plecost[postgres]\nexport PLECOST_DB_URL=postgresql+asyncpg://user:pass@host/plecost\nplecost update-db\nplecost scan https://target.com\n```\n\n\n## Scanning\n\n### Basic scan\n\n```\n$ plecost scan https://target.com\n\n  Plecost v4.1 — WordPress Security Scanner\n  Target: https://target.com\n\n  WordPress 6.4.2 detected  |  WAF: Cloudflare\n\n  Plugins (3)\n    woocommerce        8.2.1    VULNERABLE\n    contact-form-7     5.8      OK\n    elementor          3.17.0   OK\n\n  Findings (7)\n    PC-CVE-CVE-2023-28121   WooCommerce SQLi                       CRITICAL\n    PC-SSL-001              HTTP does not redirect to HTTPS         HIGH\n    PC-HDR-001              Missing Strict-Transport-Security       MEDIUM\n    PC-USR-001              User enumeration via REST API           MEDIUM\n    PC-XMLRPC-001           XML-RPC interface accessible            MEDIUM\n    PC-REST-001             REST API user data exposed              LOW\n    PC-MCFG-009             readme.html discloses WP version        LOW\n\n  Summary: 1 Critical  1 High  3 Medium  2 Low  |  Duration: 4.2s\n```\n\n### Common options\n\n```bash\n# Authenticated scan\nplecost scan https://target.com --user admin --password secret\n\n# Route traffic through Burp Suite or OWASP ZAP\nplecost scan https://target.com --proxy http://127.0.0.1:8080\n\n# Run only specific detection modules\nplecost scan https://target.com --modules fingerprint,plugins,cves\n\n# Aggressive mode — 50 parallel requests (use on internal targets)\nplecost scan https://target.com --aggressive\n\n# Deep mode — full wordlist (4750+ plugins, 900+ themes); default scans top 150/50\nplecost scan https://target.com --deep\n\n# Stealth mode — random UA, passive detection only, slower\nplecost scan https://target.com --stealth\n\n# Save results as JSON\nplecost scan https://target.com --output report.json\n\n# Show only HIGH and CRITICAL findings\nplecost scan https://target.com --quiet\n```\n\n### All scan flags\n\n| Flag | Description | Default |\n|------|-------------|---------|\n| `--concurrency N` | Parallel requests | 10 |\n| `--timeout N` | Request timeout (seconds) | 10 |\n| `--proxy URL` | HTTP or SOCKS5 proxy | — |\n| `--user / -u` | WordPress username | — |\n| `--password / -p` | WordPress password | — |\n| `--modules` | Modules to run (comma-separated) | all |\n| `--skip-modules` | Modules to skip | — |\n| `--stealth` | Passive mode, random UA, slower pacing | off |\n| `--aggressive` | Max concurrency (50 requests) | off |\n| `--output / -o` | JSON output file | — |\n| `--no-verify-ssl` | Skip certificate verification | off |\n| `--force` | Scan even if WordPress not detected | off |\n| `--deep` | Full wordlist scan (4750+ plugins, 900+ themes); default is top 150/50 | off |\n| `--verbose / -v` | Real-time module progress and findings during scan | off |\n| `--quiet` | Show only HIGH and CRITICAL findings | off |\n| `--module-option` | Module-specific option: `MODULE:KEY=VALUE` (repeatable) | — |\n\n\n## Detection Modules\n\nPlecost runs **18 async modules** in parallel, wired through an explicit dependency graph. Modules without interdependencies run concurrently from the start; `cves` waits for `plugins` and `themes` to complete before correlating results against the local database.\n\n| Module | What it checks | Finding IDs |\n|--------|----------------|-------------|\n| `fingerprint` | WordPress version (meta, readme, RSS, wp-login) | PC-FP-001/002 |\n| `waf` | WAF/CDN detection (Cloudflare, Sucuri, Wordfence, Imperva, AWS, Akamai, Fastly) | PC-WAF-001 |\n| `plugins` | Plugin enumeration — passive HTML + brute-force against `readme.txt` | PC-PLG-NNN |\n| `themes` | Theme detection via passive scan + `style.css` brute-force | PC-THM-001 |\n| `users` | User enumeration via REST API and author archive pages | PC-USR-001/002 |\n| `xmlrpc` | XML-RPC access, `pingback.ping` DoS vector, `system.listMethods` | PC-XMLRPC-001/002/003 |\n| `rest_api` | REST API link disclosure, oEmbed, CORS misconfiguration | PC-REST-001/002/003 |\n| `misconfigs` | 12 checks: `wp-config.php`, `.env`, `.git`, `debug.log`, directory traversal... | PC-MCFG-001–012 |\n| `directory_listing` | Open directory listing in `wp-content/` subdirs | PC-DIR-001–004 |\n| `http_headers` | Missing HSTS, CSP, X-Frame-Options, X-Content-Type, Referrer-Policy... | PC-HDR-001–008 |\n| `ssl_tls` | HTTP→HTTPS redirect, certificate validity, HSTS preload | PC-SSL-001/002/003 |\n| `debug_exposure` | Active `WP_DEBUG`, PHP version disclosure via response headers | PC-DBG-001/003 |\n| `content_analysis` | Card skimming scripts, suspicious iframes, hardcoded API keys | PC-CNT-001/002/003 |\n| `auth` | Authenticated checks: login verification, open user registration | PC-AUTH-001/002 |\n| `cves` | CVE correlation for core + plugins + themes against local DB | PC-CVE-{CVE-ID} |\n| `webshells` | Webshell detection across upload paths (147–523 paths depending on mode) | PC-WS-NNN |\n| `woocommerce` | WooCommerce-specific security checks (see below) | PC-WC-000–021 |\n| `wp_ecommerce` | WP eCommerce-specific security checks (see below) | PC-WPEC-000–021 |\n\nUse `plecost explain \u003cID\u003e` for full technical detail and remediation steps on any finding ID.\n\n\n## WooCommerce Security\n\nThe `woocommerce` module performs dedicated security checks for WooCommerce installations and its official extensions (Payments, Blocks, Stripe Gateway). It runs automatically when WooCommerce is detected.\n\n### Passive checks (always on)\n\n- **Fingerprinting** — detects WooCommerce version, active extensions (Payments, Blocks, Stripe Gateway), and exposed API namespaces\n- **REST API without authentication** — checks whether `/wp-json/wc/v3/customers`, `/orders`, `/coupons`, and `/system-status` are accessible without credentials (CRITICAL/HIGH)\n- **Sensitive file exposure** — directory listing on `/wp-content/uploads/wc-logs/`, access to `/wp-content/uploads/woocommerce_uploads/`\n\n### Semi-active checks (opt-in)\n\nSemi-active checks send additional HTTP requests that could leave traces in server logs. Enable explicitly:\n\n```bash\nplecost scan https://target.com --module-option woocommerce:mode=semi-active\n```\n\n| Check | CVE | CVSS |\n|-------|-----|------|\n| WooCommerce Payments authentication bypass | CVE-2023-28121 | 9.8 Critical |\n| WooCommerce Stripe Gateway IDOR (PII disclosure) | CVE-2023-34000 | 7.5 High |\n\n### Authenticated checks (optional)\n\nProvide WooCommerce REST API credentials to unlock additional checks (system configuration disclosure, payment gateway enumeration):\n\n```bash\nplecost scan https://target.com \\\n  --module-option woocommerce:wc_consumer_key=ck_xxx \\\n  --module-option woocommerce:wc_consumer_secret=cs_xxx\n```\n\n### WooCommerce JSON output\n\nWhen WooCommerce is detected, the scan result includes a dedicated `woocommerce` section:\n\n```json\n{\n  \"woocommerce\": {\n    \"detected\": true,\n    \"version\": \"8.5.2\",\n    \"active_plugins\": [\"core\", \"payments\", \"blocks\", \"stripe-gateway\"],\n    \"api_namespaces\": [\"wc/store/v1\", \"wc/v3\"]\n  }\n}\n```\n\n\n## WP eCommerce Security\n\nThe `wp_ecommerce` module performs dedicated security checks for the **WP eCommerce** (wp-e-commerce) plugin. It runs automatically when WP eCommerce is detected.\n\n\u003e **Important:** WP eCommerce has been abandoned since 2020 (last version: 3.15.1). All current installations are vulnerable to unpatched CVEs. PC-WPEC-003 is always emitted when the plugin is detected.\n\n### Passive checks (always on)\n\n- **Fingerprinting** — detects version via `readme.txt`, active payment gateways (ChronoPay)\n- **Directory exposure** — plugin directory listing, `uploads/wpsc/`, `uploads/wpsc/digital/` (digital downloads)\n- **Admin scripts** — direct access to `wpsc-admin/db-backup.php` and `wpsc-admin/display-log.php`\n- **ChronoPay endpoint** — callback endpoint accessibility check\n\n### Semi-active checks (opt-in)\n\nEnable explicitly:\n\n```bash\nplecost scan https://target.com --module-option wpec:mode=semi-active\n```\n\n| Check | CVE | CVSS |\n|-------|-----|------|\n| ChronoPay SQL Injection | CVE-2024-1514 | 9.8 Critical |\n| PHP Object Injection via AJAX | CVE-2026-1235 | 8.1 High |\n\nDetection is **boolean-only** (SQL error strings, deserialization patterns) — no time-based probes.\n\n### WP eCommerce JSON output\n\nWhen WP eCommerce is detected, the scan result includes a dedicated `wp_ecommerce` section:\n\n```json\n{\n  \"wp_ecommerce\": {\n    \"detected\": true,\n    \"version\": \"3.15.1\",\n    \"active_gateways\": [\"chronopay\"],\n    \"checks_run\": [\"readme\", \"directories\", \"sensitive_files\", \"chronopay_endpoint\"]\n  }\n}\n```\n\n\n## Output Formats\n\n### Terminal (default)\n\nRich-formatted tables with color-coded severities. Use `--quiet` to suppress LOW/MEDIUM findings.\n\n### JSON\n\n```bash\nplecost scan https://target.com --output report.json\n```\n\n```json\n{\n  \"url\": \"https://target.com\",\n  \"scanned_at\": \"2026-04-13T09:00:00Z\",\n  \"is_wordpress\": true,\n  \"wordpress_version\": \"6.4.2\",\n  \"waf_detected\": \"Cloudflare\",\n  \"plugins\": [{ \"slug\": \"woocommerce\", \"version\": \"8.2.1\" }],\n  \"themes\": [{ \"slug\": \"twentytwentyfour\", \"version\": \"1.2\" }],\n  \"users\": [\"admin\", \"editor\"],\n  \"findings\": [\n    {\n      \"id\": \"PC-CVE-CVE-2023-28121\",\n      \"remediation_id\": \"REM-CVE-CVE-2023-28121\",\n      \"title\": \"WooCommerce SQLi (CVE-2023-28121)\",\n      \"severity\": \"CRITICAL\",\n      \"cvss_score\": 9.8,\n      \"description\": \"...\",\n      \"remediation\": \"Update WooCommerce to version 7.8.0 or later.\",\n      \"references\": [\"https://nvd.nist.gov/vuln/detail/CVE-2023-28121\"],\n      \"evidence\": { \"plugin\": \"woocommerce\", \"version\": \"8.2.1\" },\n      \"module\": \"cves\"\n    }\n  ],\n  \"summary\": { \"critical\": 1, \"high\": 1, \"medium\": 3, \"low\": 2 },\n  \"duration_seconds\": 4.2,\n  \"blocked\": false,\n  \"woocommerce\": {\n    \"detected\": true,\n    \"version\": \"8.2.1\",\n    \"active_plugins\": [\"core\", \"payments\", \"blocks\"],\n    \"api_namespaces\": [\"wc/store/v1\", \"wc/v3\"]\n  },\n  \"wp_ecommerce\": null\n}\n```\n\n\n## Library Usage\n\nPlecost is a first-class Python library. The same logic that powers the CLI is available as an importable API — no subprocess, no parsing CLI output.\n\n### Standalone script\n\n```python\nimport asyncio\nfrom plecost import Scanner, ScanOptions\n\nasync def main():\n    options = ScanOptions(\n        url=\"https://target.com\",\n        concurrency=10,\n        timeout=10,\n        modules=[\"fingerprint\", \"plugins\", \"cves\"],  # None = all modules\n    )\n    result = await Scanner(options).run()\n\n    print(f\"WordPress {result.wordpress_version}  |  WAF: {result.waf_detected}\")\n    for finding in result.findings:\n        print(f\"[{finding.severity.value}] {finding.id}: {finding.title}\")\n\nasyncio.run(main())\n```\n\n### Celery workers\n\n```python\nfrom celery import Celery\nfrom plecost import Scanner, ScanOptions\nimport asyncio\n\napp = Celery(\"tasks\")\n\n@app.task\ndef scan_wordpress(url: str) -\u003e dict:\n    opts = ScanOptions(url=url, modules=[\"fingerprint\", \"plugins\", \"cves\"])\n    result = asyncio.run(Scanner(opts).run())\n    return {\n        \"url\": result.url,\n        \"critical\": result.summary.critical,\n        \"findings\": [f.id for f in result.findings],\n    }\n```\n\n\n## Environment Variables\n\n| Variable | Description | Used by |\n|----------|-------------|---------|\n| `PLECOST_DB_URL` | Database URL (SQLite or PostgreSQL) | `update-db`, `scan` |\n| `PLECOST_TIMEOUT` | Request timeout in seconds | `scan` |\n| `PLECOST_OUTPUT` | JSON output file path | `scan` |\n| `GITHUB_TOKEN` | GitHub token to avoid download rate limiting | `update-db` |\n\n\n## Architecture\n\n\u003cimg src=\"docs/architecture.svg\" alt=\"Plecost architecture diagram\" width=\"780\"/\u003e\n\nModules without interdependencies run concurrently from the start. `cves` waits for `plugins` and `themes` to complete so it has a full list of installed software to match against the CVE database.\n\n\n## Troubleshooting\n\n**\"CVE database not found\"**\n\nThe local database hasn't been downloaded yet:\n\n```bash\nplecost update-db\n```\n\n**Target returns 429 (rate limiting)**\n\n```bash\n# Reduce concurrency\nplecost scan https://target.com --concurrency 3\n\n# Or use stealth mode (includes automatic pacing)\nplecost scan https://target.com --stealth\n```\n\n**SSL certificate errors**\n\n```bash\nplecost scan https://target.com --no-verify-ssl\n```\n\n\u003e Only use `--no-verify-ssl` in controlled environments.\n\n**Target returns 403 (scanner blocked)**\n\nPlecost detects this automatically on the pre-flight probe and aborts cleanly with finding `PC-PRE-001`. Try a different IP, a proxy, or a different User-Agent:\n\n```bash\nplecost scan https://target.com --proxy http://127.0.0.1:8080\nplecost scan https://target.com --random-user-agent\n```\n\n**WordPress not detected**\n\n```bash\nplecost scan https://target.com --force\n```\n\n\n## Local Test Environment\n\nA self-contained Docker Compose environment — **Damn Vulnerable WordPress (DVWP)** — is included for local testing and development. It spins up a fully configured WordPress instance with a curated set of outdated, intentionally vulnerable plugins.\n\nLocated at [`tests/dvwp/`](tests/dvwp/).\n\n### Start\n\n```bash\ncd tests/dvwp\ndocker compose up -d\ndocker compose logs wpcli -f   # watch setup (~60s), wait for plugin table\n```\n\nOnce `wpcli` exits, the environment is ready:\n\n| URL | Credentials |\n|-----|-------------|\n| http://localhost:8765 | — |\n| http://localhost:8765/wp-admin | `admin` / `admin` |\n\n### Pre-installed vulnerable plugins\n\n| Plugin | Version | CVE |\n|--------|---------|-----|\n| wpDiscuz | 7.0.4 | CVE-2020-24186 — unauthenticated RCE via file upload (CVSS 9.8) |\n| Contact Form 7 | 5.3.1 | CVE-2020-35489 — unrestricted file upload |\n| WooCommerce | 5.0.0 | CVE-2021-32790 — multiple |\n| WooCommerce Payments | 3.9.0 | CVE-2023-28121 — unauthenticated privilege escalation (CVSS 9.8) |\n| WooCommerce Stripe Gateway | 4.3.0 | CVE-2019-15826 — order information disclosure |\n| Easy Digital Downloads | 2.11.5 | CVE-2021-39351 — stored XSS |\n| Give – Donation Plugin | 2.10.3 | CVE-2021-34634 — SQL injection |\n| YITH WooCommerce Wishlist | 2.2.9 | CVE-2021-24987 — stored XSS |\n| Ninja Forms | 3.4.34.2 | CVE-2021-34648 — unauthenticated email injection |\n| Duplicator | 1.3.26 | CVE-2020-11738 — path traversal |\n| Loginizer | 1.6.3 | CVE-2020-27615 — SQL injection |\n| Elementor | 3.1.2 | CVE-2022-1329 — authenticated RCE |\n| WP Super Cache | 1.7.1 | CVE-2021-33203 — authenticated XSS |\n| Wordfence | 7.5.0 | CVE-2021-24875 — reflected XSS |\n\n### Run plecost against it\n\n```bash\nplecost scan http://localhost:8765 -v\nplecost scan http://localhost:8765 --deep -v\n```\n\n### Reset\n\n```bash\ndocker compose down -v \u0026\u0026 docker compose up -d\n```\n\nSee [`tests/dvwp/README.md`](tests/dvwp/README.md) for full details.\n\n\u003e **Warning:** For local/isolated use only. Never expose to the internet.\n\n\n## License\n\nPlecost is distributed under the [PolyForm Noncommercial License 1.0.0](https://polyformproject.org/licenses/noncommercial/1.0.0/).\n\n**Free for:** personal security research, internal corporate audits, academic and educational use, open source projects, charitable and government organizations.\n\n**Requires a commercial license for:** scanning-as-a-service, inclusion in a commercial product, or any use generating direct or indirect revenue.\n\nFor commercial licensing: **cr0hn@cr0hn.com** (Dani) · **ffranz@mrlooquer.com** (Fran)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPlecost%2Fplecost","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPlecost%2Fplecost","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPlecost%2Fplecost/lists"}