← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2025-22327 · CWE-79 · Disclosed 2025-01-07

Improper Neutralization of Input During Web Page Generation

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

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.

"This is a post-auth WordPress plugin XSS on a 100+ install plugin, not a fleet-wide fire drill."
02 · The Attack Path

3 steps from start to impact.

STEP 01

Get a low-privilege WordPress foothold

The attacker first needs a valid WordPress account with at least Contributor privileges on a site running EO4WP. In practice this means insider misuse, credential theft, weak local account hygiene, or chaining from some earlier bug. Weaponization here is trivial: ordinary browser access or a session captured with Burp Suite is enough.
Conditions required:
  • Target site uses the EO4WP plugin in a vulnerable version
  • Attacker has authenticated WordPress access
  • Granted role is Contributor or higher
Where this breaks in practice:
  • 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
Detection/coverage: Standard network scanners will miss this prerequisite. Detection mostly comes from IAM logs, WordPress auth logs, and unusual role assignments.
STEP 02

Plant the stored payload

Using the WordPress editor or plugin-exposed content path, the attacker injects a script payload that survives storage and is rendered later by the EO4WP shortcode/form output. This does not require a public exploit kit; manual payload crafting in a browser or Burp Repeater is enough.
Conditions required:
  • Attacker can create or modify content that reaches the vulnerable output sink
  • Payload is not stripped by other sanitization layers
Where this breaks in practice:
  • 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
Detection/coverage: SAST or plugin-specific intel may flag the vulnerable version, but most commodity scanners will not prove exploitability. Content-security monitoring and diffing of post bodies help more than perimeter scanning.
STEP 03

Wait for a viewer to trigger it

The stored script only pays off when a victim loads the tainted page. Depending on placement, that victim might be a public visitor or an authenticated admin/editor viewing the post. Common follow-on actions are session theft, nonce abuse, forced admin actions, or redirect/defacement style abuse using ordinary browser JavaScript.
Conditions required:
  • A user visits the affected page or admin view
  • Browser executes the injected script in the site's origin
Where this breaks in practice:
  • 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
Detection/coverage: Runtime detection is weak unless you have CSP reporting, browser telemetry, or web logs showing suspicious post edits followed by admin page views.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo 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 availabilityNo 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.
EPSS0.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 statusNot 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 checkCVSS: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 versionsThere 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 version1.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 scanabilityWordPress.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 timelinePatchstack 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 statusDeferred in NVD, so the best structured source of record is the updated CVE/CNA metadata plus Patchstack/WPScan/WordPress plugin changelog.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.9/10)

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.

HIGH Affected/fixed version range and vendor metadata timeline
MEDIUM Operational severity downgrade based on real-world reachability

Why this verdict

  • Start at 6.5, then cut hard for attacker position: PR:L here 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:R is 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.

05 · Compensating Control

What to do — in priority order.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
What doesn't work
  • 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.
06 · Verification

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.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/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
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: identify the small set of WordPress sites that actually run 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

  1. WordPress.org plugin page and changelog
  2. Patchstack advisory
  3. WPScan vulnerability entry
  4. OpenCVE record with updated CNA metadata
  5. CISA Known Exploited Vulnerabilities catalog
  6. CISA weekly bulletin including CVE publication
  7. Rapid7 vulnerability database entry
  8. CVE Details EPSS relay
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.