Skip to content
Agentmart
Submit a tool

wp-security-audit

Run a structured security audit on any WordPress site — core integrity, plugin/theme CVE cross-check, wp-config and file-permission hardening…

Skill by mwstech

IndexedMIT★ 2
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/mwstech-wp-security-audit

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Run a structured security audit on any WordPress site — core integrity, plugin/theme CVE cross-check, wp-config and file-permission hardening, malware/compromise detection, and triaged code review of risky plugins. Use this skill whenever the user asks to "audit WordPress security", "check my WP site for vulnerabilities", "is my WordPress site secure", "scan my site", "security check", "harden WordPress", "check my plugins for vulnerabilities", "was my site hacked", or shares a WordPress site URL / SSH access / plugin list with any security concern. Trigger even on loose phrasing like "can you look at this WP site" when security is implied. Works in two modes — remote (URL only, external checks) and full (SSH/WP-CLI access, complete audit). Produces a prioritized findings report (Critical / Important / Polish) with exact fixes, optionally as a branded Word document. Free skill by Macronimous Web Solutions (macronimous.com).

Use cases: documents, security

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/wp-security-audit

What's inside

Skill name
wp-security-audit
Description
Run a structured security audit on any WordPress site — core integrity, plugin/theme CVE cross-check, wp-config and file-permission hardening, malware/compromise detection, and triaged code review of risky plugins. Use this skill whenever the user asks to "audit WordPress security", "check my WP site for vulnerabilities", "is my WordPress site secure", "scan my site", "security check", "harden WordPress", "check my plugins for vulnerabilities", "was my site hacked", or shares a WordPress site URL / SSH access / plugin list with any security concern. Trigger even on loose phrasing like "can you look at this WP site" when security is implied. Works in two modes — remote (URL only, external checks) and full (SSH/WP-CLI access, complete audit). Produces a prioritized findings report (Critical / Important / Polish) with exact fixes, optionally as a branded Word document. Free skill by Macronimous Web Solutions (macronimous.com).
License
MIT
Instructions
211 lines in SKILL.md · view on GitHub

Before installing

  • Instructions call the network

Files (7)

  • README.md
  • SKILL.md
  • macronimous-logo.png · assets/
  • palette.json · assets/
  • audit-checklist.md · references/
  • code-review-patterns.md · references/
  • report-template.md · references/

SKILL.md (first lines)

# WordPress Security Audit

A free, shareable skill by **Macronimous Web Solutions** (macronimous.com) — a web development agency working with WordPress since 2002.

Audits a WordPress site's real attack surface. WordPress core is rarely the problem; plugins, themes, configuration, and existing compromises are. This skill focuses effort where breaches actually happen.

**Authorization comes first.** Before running any check, in either mode, ask the user to confirm that they own the site or are authorized by its owner to audit it. If they say no, or won't confirm, decline the audit and don't run any checks against the site.

## Step 0: Determine the audit mode

Ask (or infer from context) which access is available:

| Mode | Access needed | Coverage |
|---|---|---|
| **Remote** | Site URL only | External surface: headers, exposed files, user enumeration, xmlrpc, version disclosure — plus a CVE cross-check against plugin/theme slugs harvested from page source, with versions treated as unconfirmed leads |
| **Full** | SSH + WP-CLI (or hosting file manager + DB access) | Everything in Remote, plus: core checksums, authoritative plugin/theme inventory (so CVE matches are confirmed, not suspected), wp-config audit, permissions, malware scan, rogue users, code review |

If the user only provides a URL, run Remote mode and state clearly what a full audit would add. Never present a Remote audit as complete coverage.

**Scope discipline:** one site per audit. If the user lists multiple sites, audit the first and offer to repeat for the rest.

## Step 1: Inventory (Full mode)

Via SSH/WP-CLI:

```bash
wp core version
wp core verify-checksums          # modified/injected core files
wp plugin list --format=csv      # name, status, version, update available
wp theme list --format=csv
wp user list --role=administrator --format=csv
php -v
```

Record everything before judging anything.

In Remote mode there's no WP-CLI, so the inventory comes from what the site exposes — generator meta tag, readme.html, and the asset paths in page source. Step 2 covers how to harvest and qualify that inventory.

## Step 2: CVE cross-check (both modes — the highest-ROI step)

**Both modes run this step.** In Full mode the inventory comes from `wp plugin list` and versions are authoritative. In Remote mode, build the inventory from what the site exposes:

- Harvest plugin slugs from page source — `wp-content/plugins/<slug>/` appears in every enqueued stylesheet and script URL
- Harvest theme slugs the same way from `wp-content/themes/<slug>/`
- Take version hints from `ver=` query strings on those enqueued assets

Treat every `ver=` value as **a lead to verify, not a confirmed version.** WordPress appends the version registered with the asset, which is often the plugin's version but can be the asset's own version, the WordPress core version, or a value the developer hardcoded years ago. Cross-check a suspected vulnerable version against a second signal before reporting it — a changelog date, a readme.txt at `wp-content/plugins/<slug>/readme.txt` if readable, or a fingerprint unique to the affected release. When no second signal is available, report it as *suspected version, unconfirmed* and say so in the finding.

For **every** plugin and theme with its version, search the web for known vulnerabilities:

- Search pattern: `<plugin-slug> <version> vulnerability` and `<plugin-slug> CVE`
- Primary sources: WPScan database (wpscan.com), Patchstack (patchstack.com), Wordfence advisories, NVD
- For each hit, record: CVE/advisory ID, severity, affected versions, whether the installed version is affected, patched version, whether exploitation requires authentication

Flag separately, even without a CVE:
- **Abandoned plugins** — no update in 2+ years (check the wordpress.org plugin page "Last updated")
- **Bundled premium plugins** — Slider Revolution, WPBakery, and similar shipped inside premium themes. *(Full mode only:* check the actual version in the plugin's main PHP file header, not the dashboard, because bundled copies don't update through the repo and chronically lag patched versions. That file isn't readable in Remote mode — the most you can do remotely is note the plugin's presence from its asset paths and flag it as needing version confirmation.*)*
- **Nulled/pirated plugins** — premium plugins with no license key configured, or files containing suspicious obfuscation, are a red flag for backdoored copies

## Step 3: Configuration audit (Full mode)

Read `references/audit-checklist.md` for the complete item-by-item checklist. The headline checks:

- **wp-config.php**: `WP_DEBUG` off in production, unique salts (not the default placeholders), `DISALLOW_FILE_EDIT` defined, table prefix, no credentials committed anywhere
- **Leftover files**: `wp-config.php.bak`, `.old`, `.save`, `wp-config.txt`, `.env`, database dumps (`.sql`), `error_log` files in webroot, `.git/` exposed
- **Permissions**: directories 755, files 644, wp-config.php 600/640, nothing 777, correct ownership
- **PHP version**: flag anything below the oldest actively supported PHP branch
- **Users**: admin accounts with username `admin`, stale admin accounts, admins with weak-looking emails (possible rogue accounts — cross-check with the user)

## Step 4: Compromise detection (Full mode)

Sites live for years often already carry something. Check:

```bash
wp core verify-checksums                              # modified core = red alert
find wp-content/uploads -name "*.php"                 # PHP in uploads = almost always malware
grep -rl "base64_decode\|eval(\|gzinflate\|str_rot13" wp-content/themes/<active-theme>/ --include="*.php"
wp user list --format=csv                             # rogue admins
crontab -l                                            # malicious cron entries
```

Also inspect: `functions.php` of the active theme for injected code at the top/bottom, `.htaccess` for unexpected redirects or RewriteRules, recently modified files (`find . -mtime -7 -name "*.php"` when investigating a suspected incident).

When recommending removal of a rogue user, always include `--reassign`: `wp user delete <id> --reassign=<legitimate-admin-id>`. Without it, WP-CLI deletes any content the account authored along with the account — unlikely to matter for a backdoor user, but the report's fix commands must be safe to paste verbatim.

Obfuscation patterns and how to distinguish legitimate uses (some plugins legitimately use base64 for assets) are detailed in `references/code-review-patterns.md`.

If any check here turns up a compromise indicator — a rogue admin, PHP in uploads, a modified core file, an injected `.htaccess` — offer the Access Log Sweep below to date it. Logs can tell the owner *when* it started and what else the source touched. Offer; don't run it unprompted.

## Access Log Sweep / Incident Timeline (Full mode · opt-in)

Web server access logs are the fourth leg of the audit, alongside the filesystem (checksums), the database (direct queries), and the external surface (HTTP checks). They are the only leg that can **date** a breach rather than merely detect it: nginx and Apache write these logs, not PHP, so they sit outside the runtime a compromise controls. In earlier testing, a rogue-admin account was dated from database fields — a log line would have caught it the week it happened.

**Do not overstate immutability.** "Malware can't alter what was already logged" holds on shared hosting, where the site's account user can't write to `/var/log/nginx/`. It does NOT hold if an attacker has root on a VPS, and cPanel-style `~/access-logs/` sits closer to the account. Logs are harder to tamper with than the filesystem, not impossible — say exactly that in the report. Overclaiming here repeats the sin the skill criticizes plugins for.

**Full mode only.** Remote mode can't read logs — note it in the report the same way as other Full-only checks.

**This is an incident-timeline tool, not a routine step.** It is opt-in, and it pivots from a known indicator wherever possible. Do not run it in every audit.

### When to offer it
1. The user asks directly — "check my logs", "when was I hacked", "can you tell when this started".
2. The audit found a compromise indicator (rogue admin, PHP in uploads, modified core file, injected `.htaccess`). Offer, don't run: *"I found an admin account created outside your normal process. Your logs could tell you when it was created and what else that IP touched — if retention goes back far enough. Want me to look?"* Wait for a yes.
3. The user suspects a hack or reports the site behaving oddly.

### The briefing (present this, then stop and wait)
Before reading a single log line, lay out the trade in plain language:
- **What it can find** — *when* a break-in happened (not just that it did), requests to files that shouldn't exist, backdoor check-in patterns.
- **What it costs** — the slowest part of the audit; a busy site means large logs.
- **Shared-hosting caution** — heavy log scanning burns CPU and can trip per-account resource limits on budget hosts (Hostinger, SiteGround), which can throttle or suspend the site. Keep commands conservative, one file at a time.
- **What it probably won't find** — most shared hosts keep only 1–3 days of raw logs. If the suspected break-in was months ago, the answer isn't there. Say this up front; for many users it makes the wait not worth it.
- **Privacy** — logs contain visitor IP addresses, which are personal data under GDPR and similar laws. Offer masking (default on) for report output. Be honest about what masking does: full IPs are still read into the session to do the correlation; only the report output is masked. Don't call this anonymization.

Then offer three choices: **run it**, **skip it**, or **check retention first**. The retention check is one cheap command (below) that returns how many days of logs exist — often enough to decide. If retention is 2 days and the suspected compromise is older, stop there and save an hour.

### Pre-flight (before any analysis)
1. **Locate the logs.** Paths vary by host — see the table in `references/audit-checklist.md` §12.
2. **Measure retention and volume.** Oldest and newest entry, total size across rotated files. Report as *"log coverage: N days."*
3. **Detect the log format.** Combined vs common vs custom — verify field positions against a real sample line. Never assume column order.
4. **Check whether the logged IPs are real — decide this from the log, not from DNS.** A site can sit behind Cloudflare/Sucuri and *still* log real client IPs, because the host restores them (`mod_remoteip`, `CF-Connecting-IP`, `X-Forwarded-For`). So don't reason "the site has a CDN, therefore skip IP checks." Look at the actual field-1 IPs: if they're dominated by CDN ranges (Cloudflare `104.16/12`, `172.64/13`, `162.158/15`, `173.245.48/20`, and similar), the real client is hidden — run **file-path checks only**, and never report a CDN edge IP as an attacker. If they're diverse real addresses, the per-IP checks are valid even though a CDN is in front. PHP responses are never cached, so the file-path checks stay valid either way.

From mwstech/wp-security-audit-skill, MIT.

Signals

Stars
2
Forks
1
Open issues
0
Last commit (this folder)
Oct 6, 2026 (22 days ago)
Last release
Oct 6, 2026 (22 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from mwstech

Cite this page

wp-security-audit skill. Agent Mart. https://agentmart.dev/skills/mwstech-wp-security-audit (last updated 2026-10-24)