← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2025-22310 · 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 a booby-trapped draft waiting for an editor to open it

CVE-2025-22310 is a stored XSS flaw in the WordPress plugin TemplatesNext ToolKit (templatesnext-toolkit) affecting all versions through 3.2.9. A user with at least Contributor privileges can plant script-bearing content that is stored server-side and later executed in another user's browser when the poisoned page or post is viewed. The plugin was later closed on WordPress.org on 2025-02-27 for a security issue, and public advisories still report no official fix available.

The vendor/CNA MEDIUM 6.5 score is technically fair, but it overstates enterprise urgency. The decisive friction is that exploitation is not unauthenticated internet-to-server compromise; it requires a valid low-privilege WordPress account and then a second user to render the malicious content. That makes this a post-initial-access content-workflow bug, not a perimeter-breaker, though it can still matter on multi-author sites where contributors, editors, and admins routinely cross paths.

"Post-auth stored XSS in a niche, closed WordPress plugin: real risk for multi-author sites, not fleet-wide fire alarm"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain contributor-level access

The attacker needs a valid WordPress account with at least the Contributor role, or a site that allows low-friction author onboarding. In practice this is usually stolen credentials, reused passwords, weak self-registration controls, or an already-compromised user session. Typical tooling is just a browser plus Burp Suite for form tampering and replay.
Conditions required:
  • Target runs the templatesnext-toolkit plugin at version <= 3.2.9
  • Attacker has authenticated WordPress access with Contributor or higher
  • The site permits the attacker to create or edit content that hits the vulnerable rendering path
Where this breaks in practice:
  • Most enterprise WordPress sites do not expose anonymous author registration
  • Contributor access already implies a prior foothold in the application
  • SSO, MFA, and tighter role assignment cut the reachable population sharply
Detection/coverage: External scanners can often identify the plugin slug/version, but cannot prove exploitability without authenticated app context. WPScan/Wordfence/Patchstack provide software-level coverage; content-level abuse usually needs application logging or database inspection.
STEP 02

Plant stored JavaScript payload

Using the vulnerable field or shortcode path described by the advisories, the attacker stores HTML/JavaScript that survives sanitization and is later reflected into rendered content. Tooling is trivial: browser dev tools, Burp Suite Repeater, or a hand-crafted POST request.
Conditions required:
  • The attacker can reach the vulnerable input path in the plugin
  • The plugin does not sanitize or escape the supplied value before later rendering
Where this breaks in practice:
  • Some editorial workflows keep contributor content in draft or pending-review state
  • Moderation plugins, content sanitizers, or WAF rules may strip obvious payloads
  • Not every deployment actively uses the vulnerable widget/shortcode path
Detection/coverage: Signature-based WAFs may catch obvious <script> payloads but often miss obfuscated event handlers, SVG payloads, or shortcode abuse. Authenticated DAST coverage is uneven unless you test from a contributor session.
STEP 03

Wait for a higher-privileged viewer

Impact arrives only when another user renders the stored payload in a browser session. A realistic objective is to target an Editor or Administrator reviewing content, then steal nonces, issue state-changing actions, or hijack the browser session with custom JavaScript or frameworks like BeEF.
Conditions required:
  • A victim user loads the poisoned page, preview, or admin-side rendering view
  • The victim browser executes the injected script
  • The victim has privileges worth stealing or abusing
Where this breaks in practice:
  • UI interaction is mandatory
  • If no admin/editor ever views attacker-authored content, the chain dies here
  • Strict CSP, hardened cookies, and admin isolation can blunt some post-XSS actions
Detection/coverage: This is where many orgs go blind. EDR on the server will not help; detection depends on browser telemetry, suspicious admin actions, audit logs, and unusual post.php or admin-ajax.php activity tied to contributor content.
STEP 04

Abuse the victim session for follow-on actions

With script execution in a privileged browser, the attacker can attempt nonce theft, content tampering, plugin configuration changes, or creation of persistent admin users depending on what the victim can do and what browser-side protections exist. This is usually application compromise via the victim's browser, not direct code execution on the web server.
Conditions required:
  • Victim privileges are sufficient to perform interesting admin actions
  • The site lacks compensating controls that limit XSS impact
Where this breaks in practice:
  • WordPress nonce boundaries and browser cookie protections can limit some actions
  • Many high-impact goals still require precise knowledge of the site's admin flows
  • This is narrower than unauthenticated RCE or arbitrary file upload
Detection/coverage: Watch for unexpected admin account creation, plugin/theme changes, option updates, or content edits immediately after privileged users view contributor-authored content.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo CISA KEV listing and I found no credible public reporting of active exploitation campaigns for this CVE specifically. That lines up with the very low EPSS and the post-auth workflow requirements.
Proof-of-concept availabilityNo public exploit repo or exploit-db entry surfaced in source review. That said, this is still easy to weaponize manually once an attacker has contributor access because stored XSS usually needs only crafted content, not a memory-corruption chain.
EPSS0.00152 (~0.152% probability over 30 days), which is very low and supports a downgrade from the raw vendor score for enterprise prioritization.
KEV status and datesNot listed in CISA KEV. Public disclosure landed on 2025-01-07 in NVD/CNA records; the plugin was closed on WordPress.org on 2025-02-27 for a security issue.
CVSS vector and what it really meansCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:L means network reachable, but not unauthenticated; it needs low privileges and user interaction. In plain English: this is a content-author abuse path, not a server-breakout.
Affected versionsAll versions through 3.2.9 are reported vulnerable by NVD/Patchstack/Wordfence/WPScan.
Fixed versionNo official fixed version is published in Patchstack, Wordfence, or WPScan. WordPress.org shows the plugin as closed, so the practical remediation is remove/replace, not wait for a patch that may never ship.
Exposure and reachabilityWordfence shows roughly 10,000 active installs and 561,764 downloads, so this is not tiny, but it is still a niche plugin population. I found no reliable Shodan/Censys/FOFA fingerprint that would let defenders cleanly estimate internet-exposed instances of this exact plugin.
Disclosure and researcherCredited researcher: LVT-tholv2k. Patchstack and NVD date the public disclosure to 2025-01-06/2025-01-07 depending on feed normalization.
Historical signalThis plugin has a repeat XSS history: Wordfence/Patchstack list earlier stored-XSS issues in 2023 and another XSS entry in 2025. Recurrent input/output handling bugs are a negative maintenance signal and strengthen the case for replacement.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to MEDIUM (4.9/10)

The single biggest downgrade driver is that exploitation requires authenticated Contributor access and then a victim to view the payload. That makes this a post-auth, workflow-dependent browser compromise with a materially smaller exposed population than the vendor score suggests, even though the absence of an official fix keeps it above LOW.

HIGH Affected version range `<= 3.2.9` and lack of official fix
MEDIUM Exploitability in real enterprise content workflows
MEDIUM Assessment that public exploitation is currently absent

Why this verdict

  • Downward pressure: requires authenticated remote access. The attacker must already hold a WordPress account with at least Contributor rights, which implies prior compromise, weak registration controls, or insider access.
  • Downward pressure: user interaction is mandatory. A second user has to render the poisoned content before impact lands; plenty of malicious drafts die in moderation queues and never execute.
  • Downward pressure: limited deployment slice. This is a single niche plugin with about 10,000 installs, not WordPress core or a top-tier plugin with massive enterprise reach.
  • Downward pressure: threat telemetry is quiet. EPSS is very low and there is no KEV listing or clear campaign evidence.
  • Upward pressure: no fix exists and the plugin was removed. That weakens the long-term maintenance story and raises residual risk for sites that keep it installed.
  • Upward pressure: stored XSS can still become privilege escalation. On multi-author sites, contributor-to-admin browser compromise is a real path even if it is not a perimeter RCE.

Why not higher?

This is not an unauthenticated internet exploit against the server. The chain needs Contributor access, a vulnerable content path actually in use, and a privileged user to load the payload, so the reachable population and reliability are both substantially lower than HIGH or CRITICAL cases. There is also no strong evidence of active exploitation pressure.

Why not lower?

I would not drop this to LOW because it is stored, not reflected, and it can realistically target editors or admins in normal WordPress review workflows. The fact that the plugin is closed for security issues with no official fix means residual exposure can persist until defenders actively remove or replace it.

05 · Compensating Control

What to do — in priority order.

  1. Remove or replace the plugin — Because there is no official fixed release, the cleanest control is to remove templatesnext-toolkit entirely or replace it with a maintained alternative. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but on internet-facing multi-author CMS estates I would treat this as sooner-than-backlog hygiene because the plugin is already closed upstream.
  2. Restrict contributor creation — Shut off open registration where possible, review who still has Contributor/Author roles, and require SSO/MFA for any content publisher accounts. This directly attacks the most important prerequisite in the chain; for this MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but role cleanup should happen opportunistically during the next access review.
  3. Quarantine contributor-authored content — Require editorial review and avoid rendering contributor drafts in privileged admin sessions until the plugin is gone. This reduces the second key prerequisite: a higher-privileged victim viewing poisoned content.
  4. Add WAF and content filtering rules — Block obvious script-bearing payloads, dangerous event handlers, and suspicious shortcode inputs on WordPress content submission endpoints. This is only a partial control, but it can trim low-effort weaponization while you work through removal.
  5. Audit for existing payloads — Search wp_posts and related metadata for <script, onerror=, onload=, javascript:, svg/onload, and abnormal shortcode attributes in content authored by low-privilege users. Do this before and after plugin removal to catch already-planted stored payloads.
What doesn't work
  • Updating WordPress core does not fix this; the flaw is in the plugin.
  • Relying on perimeter vuln scanners alone will miss the real risk because the exploit path is authenticated and content-workflow dependent.
  • Server-side EDR will not reliably catch browser-side XSS abuse against admins; the attack happens in the victim's session, not as obvious malware on disk.
  • A generic password reset for admins only is insufficient if low-privilege contributor accounts remain exposed and the plugin is still installed.
06 · Verification

Crowdsourced verification payload.

Run this on the target WordPress host or against a mounted filesystem copy. Invoke it as bash verify-cve-2025-22310.sh /var/www/html and use a user that can read the WordPress plugin directory; root is not required unless file permissions are tight.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# verify-cve-2025-22310.sh
# Detects whether a WordPress instance has TemplatesNext ToolKit installed at a vulnerable version.
# Usage: bash verify-cve-2025-22310.sh /path/to/wordpress
# Exit codes: 0 PATCHED, 1 VULNERABLE, 2 UNKNOWN

set -u

WP_ROOT="${1:-}"
PLUGIN_DIR=""
MAIN_FILE=""
VERSION=""

if [ -z "$WP_ROOT" ]; then
  echo "UNKNOWN - missing WordPress root path argument"
  exit 2
fi

PLUGIN_DIR="$WP_ROOT/wp-content/plugins/templatesnext-toolkit"

if [ ! -d "$PLUGIN_DIR" ]; then
  echo "PATCHED - plugin directory not present: $PLUGIN_DIR"
  exit 0
fi

# Try common files for version extraction.
for f in \
  "$PLUGIN_DIR/readme.txt" \
  "$PLUGIN_DIR/templatesnext-toolkit.php" \
  "$PLUGIN_DIR/index.php"; do
  if [ -f "$f" ]; then
    MAIN_FILE="$f"
    break
  fi
done

if [ -z "$MAIN_FILE" ]; then
  echo "UNKNOWN - plugin directory exists but no readable version source found"
  exit 2
fi

extract_version() {
  local file="$1"
  local v=""

  v=$(grep -Eim1 '^[[:space:]]*Stable tag:[[:space:]]*[0-9][0-9A-Za-z._-]*' "$file" 2>/dev/null | sed -E 's/^[^:]+:[[:space:]]*//I')
  if [ -n "$v" ]; then
    echo "$v"
    return 0
  fi

  v=$(grep -Eim1 '^[[:space:]]*Version:[[:space:]]*[0-9][0-9A-Za-z._-]*' "$file" 2>/dev/null | sed -E 's/^[^:]+:[[:space:]]*//I')
  if [ -n "$v" ]; then
    echo "$v"
    return 0
  fi

  return 1
}

VERSION=$(extract_version "$MAIN_FILE") || true

if [ -z "$VERSION" ] && [ -f "$PLUGIN_DIR/templatesnext-toolkit.php" ]; then
  VERSION=$(extract_version "$PLUGIN_DIR/templatesnext-toolkit.php") || true
fi

if [ -z "$VERSION" ] && [ -f "$PLUGIN_DIR/readme.txt" ]; then
  VERSION=$(extract_version "$PLUGIN_DIR/readme.txt") || true
fi

if [ -z "$VERSION" ]; then
  echo "UNKNOWN - could not parse plugin version from $PLUGIN_DIR"
  exit 2
fi

# Normalize: keep leading numeric dotted component only.
VERSION=$(echo "$VERSION" | sed -E 's/^([0-9]+(\.[0-9]+){0,3}).*$/\1/')

if [ -z "$VERSION" ]; then
  echo "UNKNOWN - parsed version is empty"
  exit 2
fi

if printf '%s\n%s\n' "$VERSION" '3.2.9' | sort -V -C; then
  echo "VULNERABLE - TemplatesNext ToolKit version $VERSION detected (affected: <= 3.2.9)"
  exit 1
else
  echo "PATCHED - TemplatesNext ToolKit version $VERSION detected (> 3.2.9)"
  exit 0
fi
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, identify every WordPress instance still carrying templatesnext-toolkit, especially sites with Contributor/Author workflows or open registration. Because this is MEDIUM, there is no noisgate mitigation SLA — go straight to the 365-day remediation window; in practice, since the plugin is closed and has no official fix, schedule removal/replacement rather than waiting for a vendor patch, and complete that by the noisgate remediation SLA of ≤ 365 days. If any site is internet-facing and allows low-privileged content authors, accelerate access review and content audit immediately even though this does not rise to emergency patch status.

Sources

  1. NVD CVE-2025-22310
  2. Patchstack vulnerability record
  3. Patchstack plugin vulnerability history
  4. Wordfence vulnerability record
  5. Wordfence plugin overview
  6. WPScan vulnerability record
  7. WordPress.org plugin page
  8. CISA weekly vulnerability bulletin (week of January 6, 2025)
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.