This is graffiti in a side hallway, not a master key to the building
CVE-2025-22327 is a stored XSS issue in the WordPress plugin EO4WP: EmailOctopus for WordPress (fw-integration-for-emailoctopus). The vendor/CVE metadata started with an affected range of through 1.0.7 on 2025-01-07, but the later updated CVE record, Patchstack, WPScan, and the plugin changelog all line up on a broader practical range of <= 1.0.8.1, fixed in 1.0.8.2. The exploit path is contributor-level-or-higher content injection that later renders in the plugin's shortcode/form output.
The vendor's 6.5 MEDIUM is technically defensible in a vacuum, but it overstates enterprise urgency. Real-world friction is heavy: the attacker needs authenticated WordPress access, typically Contributor+, and then needs the poisoned content to be viewed. On top of that, the plugin has only 100+ active installs on WordPress.org, which crushes reachable population. For a team patching 10,000 hosts, this belongs in low-priority application hygiene, not emergency response.
3 steps from start to impact.
Get a low-privilege WordPress foothold
- Target site uses the EO4WP plugin in a vulnerable version
- Attacker has authenticated WordPress access
- Granted role is Contributor or higher
- This is not unauthenticated internet-reachable exploitation
- Contributor accounts are uncommon on many enterprise marketing sites
- SSO, MFA, and role minimization often block this stage entirely
Plant the stored payload
- Attacker can create or modify content that reaches the vulnerable output sink
- Payload is not stripped by other sanitization layers
- Exact exploitation depends on how the site uses the plugin shortcode or form
- Some editorial workflows require review before contributor content goes live
- Other hardening plugins may partially neuter the payload
Wait for a viewer to trigger it
- A user visits the affected page or admin view
- Browser executes the injected script in the site's origin
- No viewer, no impact
- Blast radius is generally one WordPress site or tenant, not the server fleet
- Modern browser protections help at the edges, but do not stop same-origin stored XSS
The supporting signals.
| In-the-wild status | No evidence of active exploitation found. CISA KEV does not list this CVE, and the CISA ADP SSVC data in the CVE record shows Exploitation: none, Automatable: no, Technical Impact: partial. |
|---|---|
| Proof-of-concept availability | No public GitHub/Metasploit PoC located during lookup. Realistically, this does not need one: a contributor account plus a browser or Burp Suite is sufficient to test payload injection. |
| EPSS | 0.00254 from the supplied intel, which is ~0.254% probability over 30 days. Secondary EPSS relays place it in a low percentile band; treat that as directional because EPSS shifts daily. |
| KEV status | Not KEV-listed at lookup. That matters here because there is also no public campaign reporting to override the otherwise low operational urgency. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:L translates to network reachable but authenticated, user-interaction-required, low direct impact. The decisive real-world modifier is PR:L on a CMS plugin: it usually means post-initial-access. |
| Affected versions | There is a date-driven metadata discrepancy. The original Patchstack/CVE publication on 2025-01-07 said through 1.0.7; the later updated CVE record, Patchstack page, WPScan, and Rapid7 all indicate <= 1.0.8.1. |
| Fixed version | 1.0.8.2 is the first fixed release. WordPress.org changelog explicitly notes a security fix in 1.0.8.2: output escaping in the form shortcode. |
| Exposure and scanability | WordPress.org shows only 100+ active installations. This plugin is also not meaningfully internet-fingerprintable in the same way as a VPN or edge appliance, so internet scan telemetry is limited and reachable population is small. |
| Disclosure timeline | Patchstack says it was reported on 2024-10-20 by SOPROBRO and publicly published on 2025-01-03; the CVE was published on 2025-01-07. |
| NVD status | Deferred in NVD, so the best structured source of record is the updated CVE/CNA metadata plus Patchstack/WPScan/WordPress plugin changelog. |
noisgate verdict.
The single biggest severity reducer is that exploitation requires authenticated Contributor+ access, which means this is usually a post-compromise or insider-abuse issue, not an initial-access bug. The second reducer is population: a 100+ install WordPress plugin with no meaningful internet fingerprinting is not a mass-enterprise exposure problem.
Why this verdict
- Start at 6.5, then cut hard for attacker position:
PR:Lhere means the attacker already has a WordPress foothold with Contributor+ rights. That is downward pressure because it implies either prior compromise, credential theft, or an insider. - Cut again for trigger friction: the payload is stored, but impact still needs a victim to load the poisoned content.
UI:Ris not theoretical here; no page view means no payoff. - Cut again for reachable population: WordPress.org reports only 100+ active installs. This is not a ubiquitous enterprise platform or an edge service sitting on the public internet.
- Keep it above IGNORE because stored XSS can pivot: if an admin views the page, same-origin JavaScript can steal nonces, abuse sessions, or stage admin-side actions inside that site.
Why not higher?
This is not remotely unauthenticated, not wormable, and not broadly exposed. The attacker must already be inside WordPress with enough permissions to plant content, which is exactly the kind of prerequisite that should drag a CVSS-medium application bug down in enterprise patch triage.
Why not lower?
It is still a stored XSS, not a self-XSS or dead-code issue. On sites that use contributors, agencies, guest authors, or shared marketing workflows, this can become a practical tenant compromise path if an admin later views the tainted content.
What to do — in priority order.
- Trim Contributor access — Remove dormant or low-trust Contributor/Author accounts and convert unnecessary write-capable roles to read-only where possible. This directly attacks the main prerequisite; for a LOW verdict there is no mitigation SLA, so treat this as backlog hygiene during the next access review.
- Gate content publication — Require editorial review for contributor-submitted posts and shortcodes before publishing. That adds human friction to the stored payload step; for LOW, there is no mitigation SLA, so fold it into normal WordPress governance work.
- Alert on plugin-related post edits — Monitor WordPress post revisions, shortcode insertions, and unusual edits by low-privilege roles on sites running EO4WP. This improves odds of catching weaponization before an admin or visitor triggers it.
- Enforce MFA and SSO on wp-admin — Because the main risk is a post-auth actor, stronger admin and contributor authentication shrinks the real attack surface more than perimeter filtering does. For LOW, implement through normal IAM backlog rather than emergency change windows.
- A perimeter WAF will not reliably save you once the payload is stored and later rendered from legitimate content.
- A WordPress core update alone does not remediate a vulnerable plugin release.
- Generic external vulnerability scans usually cannot confirm this plugin, its exact version, and the authenticated contributor precondition.
Crowdsourced verification payload.
Run this on the target WordPress host or inside the web container, not from an auditor workstation. Invoke it as bash verify_eo4wp_cve_2025_22327.sh /var/www/html/wp-content/plugins/fw-integration-for-emailoctopus; it needs only read access to the plugin files.
#!/usr/bin/env bash
# verify_eo4wp_cve_2025_22327.sh
# Check whether the WordPress plugin fw-integration-for-emailoctopus (EO4WP)
# is vulnerable to CVE-2025-22327.
#
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN / usage / missing files
set -u
PLUGIN_DIR="${1:-}"
if [ -z "$PLUGIN_DIR" ]; then
echo "UNKNOWN - usage: $0 /path/to/wp-content/plugins/fw-integration-for-emailoctopus"
exit 2
fi
if [ ! -d "$PLUGIN_DIR" ]; then
echo "UNKNOWN - plugin directory not found: $PLUGIN_DIR"
exit 2
fi
MAIN_FILE=""
for f in "$PLUGIN_DIR"/*.php; do
[ -f "$f" ] || continue
if grep -qiE '^\s*Plugin Name:\s*EO4WP|^\s*Plugin Name:\s*EO4WP: EmailOctopus for WordPress' "$f" 2>/dev/null; then
MAIN_FILE="$f"
break
fi
done
VERSION=""
if [ -n "$MAIN_FILE" ]; then
VERSION=$(awk -F': ' 'BEGIN{IGNORECASE=1} /^Version:/ {print $2; exit}' "$MAIN_FILE" 2>/dev/null | tr -d '\r')
fi
if [ -z "$VERSION" ] && [ -f "$PLUGIN_DIR/readme.txt" ]; then
VERSION=$(awk -F': ' 'BEGIN{IGNORECASE=1} /^Stable tag:/ {print $2; exit}' "$PLUGIN_DIR/readme.txt" 2>/dev/null | tr -d '\r')
fi
normalize_version() {
local v="$1"
v="${v%%[^0-9.]*}"
echo "$v"
}
VERSION=$(normalize_version "$VERSION")
if [ -z "$VERSION" ]; then
echo "UNKNOWN - unable to determine plugin version from plugin header or readme.txt"
exit 2
fi
if printf '%s\n%s\n' "$VERSION" "1.0.8.2" | sort -V -C; then
if [ "$VERSION" = "1.0.8.2" ] || [ "$VERSION" = "1.0.8.5" ] || [ "$VERSION" = "1.0.8.6" ] || [ "$VERSION" = "1.0.10" ] || [ "$VERSION" = "1.0.11" ] || [ "$VERSION" = "1.0.11.1" ] || [ "$VERSION" = "1.0.11.2" ] || printf '%s\n%s\n' "1.0.8.2" "$VERSION" | sort -V -C; then
echo "PATCHED - EO4WP version $VERSION is >= 1.0.8.2"
exit 0
fi
fi
if printf '%s\n%s\n' "$VERSION" "1.0.8.1" | sort -V -C; then
echo "VULNERABLE - EO4WP version $VERSION is <= 1.0.8.1"
exit 1
fi
# Fallback logic in case sort -V behavior is odd on a non-GNU platform
if [ "$VERSION" = "1.0.8.2" ] || [ "$VERSION" = "1.0.8.5" ] || [ "$VERSION" = "1.0.8.6" ] || [ "$VERSION" = "1.0.10" ] || [ "$VERSION" = "1.0.11" ] || [ "$VERSION" = "1.0.11.1" ] || [ "$VERSION" = "1.0.11.2" ]; then
echo "PATCHED - EO4WP version $VERSION is >= 1.0.8.2"
exit 0
fi
echo "UNKNOWN - determined version $VERSION but could not classify confidently"
exit 2
If you remember one thing.
fw-integration-for-emailoctopus, verify whether any of them still sit at <= 1.0.8.1, and patch them during the next normal plugin maintenance cycle. Because this is LOW, there is no noisgate mitigation SLA and no noisgate remediation SLA—treat it as backlog hygiene, document the post-auth friction, and prioritize only those sites that use contributor-style publishing workflows or third-party content authors.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.