This is a loaded nail gun left in the admin closet, not a sniper rifle on the public internet
CVE-2023-23645 is an authenticated PHP code injection flaw in MainWP Code Snippets Extension affecting versions through 4.0.2 and fixed in 4.0.3. If an attacker can log into the MainWP Dashboard with subscriber-or-higher rights, they can abuse the extension's snippet functionality to inject PHP and potentially execute code across the dashboard's managed estate, including child sites and even wp-config.php workflows exposed by the product design.
The vendor/CNA 9.9 CRITICAL score overstates day-two reality because it models the bug like a broadly reachable internet RCE. In practice, this lives on a dedicated management plane, requires authenticated access, and only matters where the paid extension is installed; that sharply narrows exposure. But once that prerequisite is met, the blast radius is ugly because MainWP is a central controller, so this stays HIGH, not MEDIUM.
4 steps from start to impact.
Get into the MainWP dashboard
- A MainWP Dashboard is deployed
- The Code Snippets Extension is installed and enabled
- The dashboard is reachable from the attacker
- The attacker has valid subscriber-or-higher credentials
- MainWP recommends a dedicated dashboard install rather than a public content site
- Many operators do not create subscriber accounts on management dashboards at all
- MFA, SSO, VPN, IP allowlists, or HTTP auth often sit in front of the dashboard
Reach the vulnerable snippet workflow
curl, the attacker interacts with the vulnerable extension workflow intended for creating or executing snippets. The product is explicitly designed to accept PHP code for distribution, so exploit traffic can look like legitimate admin activity unless you know which roles are allowed to use the feature.- Authenticated session on the MainWP Dashboard
- Access to the extension's snippet functionality
- Some deployments restrict extension pages by role or custom policy
- Commercial extension usage is far less common than commodity WordPress plugin exposure
- Auth-only reachability means internet census tools cannot easily verify exploitability
Inject PHP through the extension
wp-config.php-oriented workflows, successful exploitation can move beyond the dashboard itself.- Vulnerable version 4.0.2 or earlier
- Snippet submission path accepts attacker-controlled PHP
- Logging or approval workflows can expose anomalous snippet content
- Some environments disable dangerous PHP functions or harden file write paths
- Child-site execution still depends on the normal MainWP trust relationship being healthy
mainwp_ext_code_snippets, and FIM around wp-config.php are useful. External vuln scanners typically do not validate this safely.Pivot from dashboard to fleet impact
- The dashboard manages connected child sites
- The compromised account can trigger snippet actions against those sites
- Blast radius depends on how many child sites are attached and selected
- Network controls or broken child-site trust can limit propagation
- Some tenants use dedicated dashboards per customer, containing impact to one management island
The supporting signals.
| In-the-wild status | No known active exploitation in the sources reviewed. The CISA ADP enrichment marks exploitation as none and automation as no. |
|---|---|
| Public exploit / PoC | No widely circulated public PoC was evident in the reviewed references. That does not mean hard to exploit; once authenticated, the exploit path is operationally simple because the feature already transports PHP. |
| EPSS | 0.00771 (*<1% probability*), consistent with a niche, auth-required management-plane bug rather than mass internet exploitation. |
| KEV status | Not listed in CISA KEV in the sources reviewed, matching the user-provided intel. |
| CVSS vector reality check | AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H is technically fair, but PR:L on a dedicated admin dashboard is a major real-world brake. S:C is the real danger because the dashboard can affect child sites. |
| Affected versions | MainWP Code Snippets Extension <= 4.0.2. |
| Fixed version | 4.0.3+. MainWP's changelog for 2022-12-07 calls out 'Preventative: Multiple security improvements,' and multiple vuln databases map the fix to 4.0.3. |
| Exposure population | This is a commercial MainWP extension, so public install telemetry is thin; WPScan shows active installs: n/a for the extension. For scale context, MainWP says it had 20,000 dashboards controlling 700,000 WordPress sites as of May 2024, meaning low prevalence but potentially high downstream impact where deployed. |
| Discovery / reporting | Reported by Dave Jong (Patchstack). |
| Disclosure timeline | Patchstack reserved the CVE on 2023-01-17; Wordfence/WPScan list public vuln publication on 2023-01-18; the CVE record was published on 2024-05-17. |
noisgate verdict.
The decisive factor is the authenticated requirement on a dedicated management interface: this is not a sprayable internet RCE against the average WordPress site. It remains HIGH because if that prerequisite is satisfied, the attacker is standing on a central control plane that can fan compromise out across many child sites.
Why this verdict
- Downgrade for attacker position: the exploit requires authenticated remote access (
PR:L), which implies either stolen creds, insider access, or a prior foothold. That is a full stage of attack work the vendor score does not price in aggressively enough. - Downgrade for reachable population: this is not generic WordPress exposure. It requires a MainWP Dashboard plus the Code Snippets Extension, and MainWP itself recommends a dedicated dashboard site, which narrows exposure compared with commodity public plugins.
- Hold at HIGH for blast radius: once exploited, the attacker is abusing a management plane that can execute or distribute code to child sites.
S:Cis not theoretical here; the extension is meant to push code outward, so one weak dashboard account can become a many-site problem.
Why not higher?
There is no evidence in the reviewed sources of KEV listing, broad in-the-wild exploitation, or unauthenticated reachability. The need for a valid low-privileged account on a niche management dashboard is exactly the kind of compounding friction that keeps this out of CRITICAL despite the ugly post-compromise impact.
Why not lower?
This is still a code execution bug on a centralized WordPress administration plane, not a cosmetic XSS in a random plugin. If your environment uses MainWP the wrong way — internet-exposed dashboard, weak auth, shared low-priv users — the compromise can spread across a large managed estate very quickly.
What to do — in priority order.
- Put the dashboard behind a gate — Restrict MainWP Dashboard access with VPN, IP allowlists, reverse-proxy basic auth, or private admin ingress. This directly attacks the biggest friction point in the chain — attacker reachability to the management plane — and for a HIGH verdict should be deployed within 30 days if patching is not already complete.
- Remove low-privileged accounts from the dashboard — Audit WordPress users on the MainWP Dashboard and eliminate subscriber/contributor/editor accounts that do not belong on a control plane. The vulnerability needs subscriber+, so shrinking that population is high-leverage and should be completed within 30 days.
- Enforce MFA or upstream SSO — If the dashboard is internet-reachable at all, require MFA through WordPress, SSO, or the upstream identity proxy. This reduces the chance that credential stuffing or reused passwords turn an ordinary auth weakness into fleet-wide code execution, and should be in place within 30 days.
- Monitor snippet and config changes — Alert on changes involving MainWP snippet records, suspicious admin actions by low-priv users, and modifications to child-site
wp-config.php. This won't prevent exploitation, but it shortens dwell time and should be implemented within 30 days for exposed deployments. - Constrain outbound trust where practical — Review which child sites each dashboard can reach and segment dashboards by tenant or business unit where possible. This reduces blast radius if the dashboard is abused, and for a HIGH issue belongs in the hardening backlog within 30 days for exposed or multi-tenant environments.
- Child-site WAF rules alone do not solve the core problem, because the attacker can abuse the trusted MainWP controller to push code through expected management workflows.
- Unauthenticated external vulnerability scanning is weak coverage here; the bug sits behind login and often on a commercial extension that internet scanners cannot safely verify.
- Security by obscuring
/wp-adminis not a compensating control. If the dashboard is still reachable and credentials exist, the exploit path is intact.
Crowdsourced verification payload.
Run this on the web server hosting the MainWP Dashboard or from an admin shell in the container/VM that has read access to the WordPress files. Invoke it as bash check-mainwp-cve-2023-23645.sh /var/www/html or point it directly at the plugin directory; no root is required if you can read wp-content/plugins.
#!/usr/bin/env bash
# check-mainwp-cve-2023-23645.sh
# Detects whether MainWP Code Snippets Extension is vulnerable to CVE-2023-23645.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
TARGET="${1:-}"
if [[ -z "$TARGET" ]]; then
echo "UNKNOWN - usage: $0 <wordpress-root|plugin-dir>"
exit 2
fi
if [[ -d "$TARGET/wp-content/plugins/mainwp-code-snippets-extension" ]]; then
PLUGIN_DIR="$TARGET/wp-content/plugins/mainwp-code-snippets-extension"
elif [[ -d "$TARGET" && "$(basename "$TARGET")" == "mainwp-code-snippets-extension" ]]; then
PLUGIN_DIR="$TARGET"
else
echo "UNKNOWN - could not locate mainwp-code-snippets-extension under target: $TARGET"
exit 2
fi
if [[ ! -d "$PLUGIN_DIR" ]]; then
echo "UNKNOWN - plugin directory not found: $PLUGIN_DIR"
exit 2
fi
MAIN_FILE="$(grep -RIl --include='*.php' 'Plugin Name:.*MainWP Code Snippets Extension' "$PLUGIN_DIR" 2>/dev/null | head -n1 || true)"
if [[ -z "$MAIN_FILE" ]]; then
# Fallback: look for a version header in likely primary PHP files
MAIN_FILE="$(find "$PLUGIN_DIR" -maxdepth 2 -type f -name '*.php' | head -n1 || true)"
fi
if [[ -z "$MAIN_FILE" || ! -f "$MAIN_FILE" ]]; then
echo "UNKNOWN - could not find plugin main PHP file"
exit 2
fi
VERSION="$(awk 'BEGIN{IGNORECASE=1} /^Version:[[:space:]]*/ {gsub(/\r/, ""); sub(/^Version:[[:space:]]*/, ""); print; exit}' "$MAIN_FILE" | tr -d '[:space:]')"
if [[ -z "$VERSION" ]]; then
echo "UNKNOWN - could not parse plugin version from: $MAIN_FILE"
exit 2
fi
verlt() {
[[ "$1" != "$2" ]] && [[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" == "$1" ]]
}
FIXED="4.0.3"
if verlt "$VERSION" "$FIXED"; then
echo "VULNERABLE - MainWP Code Snippets Extension version $VERSION (< $FIXED)"
exit 1
else
echo "PATCHED - MainWP Code Snippets Extension version $VERSION (>= $FIXED)"
exit 0
fi
If you remember one thing.
Sources
- NVD CVE-2023-23645
- OpenCVE record for CVE-2023-23645
- MainWP Code Snippets Extension changelog
- MainWP documentation: Code Snippets Overview
- MainWP scale statement: 20,000 dashboards / 700,000 sites
- WordPress.org MainWP Dashboard plugin page
- Wordfence vulnerability entry
- CISA Known Exploited Vulnerabilities Catalog
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.