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

Improper Neutralization of Input During Web Page Generation

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

This is a rotten screen door on a shed, not a blown vault door

CVE-2025-31431 is a reflected XSS bug in the WordPress wp-bookmarks plugin from conlabz GmbH, affecting all versions through 1.1. An unauthenticated attacker can craft a malicious request that reflects attacker-controlled input into a page; the payload only fires if a victim user loads the crafted URL or otherwise performs the required action in a browser session.

The vendor/CNA CVSS 7.1 HIGH is technically defensible from a pure CVSS standpoint, but it overstates enterprise urgency. The real-world chain has two big brakes: user interaction is mandatory and the plugin is tiny/removed/unpatched, with Wordfence showing only about 60 active installs and WordPress.org showing the plugin was closed on March 24, 2025 for a security issue. That makes this a cleanup-and-replace issue, not an all-hands patch fire.

"Remote and ugly on paper, but this is still a click-required reflected XSS in a tiny, removed plugin."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Find a site still running wp-bookmarks

The attacker first needs a WordPress site that still has the abandoned plugin installed. There is no strong internet-wide network fingerprint for this plugin, so discovery is usually opportunistic, content-based, or inventory-driven rather than mass-precise. Tools like httpx, wpscan, or custom search dorks can help, but this is not the same as scanning for a clean RCE banner.
Conditions required:
  • Target runs WordPress with the wp-bookmarks plugin installed
  • Attacker can reach the vulnerable web application over HTTP/HTTPS
Where this breaks in practice:
  • Plugin appears removed/closed from WordPress.org
  • Very small estimated install base reduces reachable population
  • No reliable network signature for broad internet-scale detection
Detection/coverage: External scanners may flag the plugin only if plugin enumeration is possible. Asset/SBOM/plugin inventory is more reliable than perimeter scanning.
STEP 02

Build the reflected XSS lure

Using a web proxy such as Burp Suite, the attacker crafts a URL or request parameter that causes unsanitized input to be reflected into a response. This is straightforward technically, but only becomes useful if the target application exposes the vulnerable code path and reflects the payload in an executable browser context.
Conditions required:
  • Vulnerable parameter/path is reachable
  • Reflected payload lands in a browser-executable context
Where this breaks in practice:
  • The issue is reflected, not stored, so there is no durable foothold
  • Payload effectiveness depends on exact page context and browser parsing
Detection/coverage: DAST can sometimes catch this if the vulnerable endpoint is covered; many authenticated/admin-adjacent code paths are missed by generic web scans.
STEP 03

Social-engineer a victim into clicking

The attacker then needs a live victim to load the crafted URL, typically via phishing, chat, support tickets, or comment spam. Campaign tooling such as GoPhish or commodity phishing kits is enough here; the browser is the execution environment, not the server.
Conditions required:
  • Victim user clicks the lure or visits a crafted page
  • Victim has an active browser session against the target site or can reach it
Where this breaks in practice:
  • User interaction required is the decisive brake
  • Modern email security, browser protections, and user awareness training disrupt this step
  • If only low-privilege users click, business impact drops sharply
Detection/coverage: Email gateways, browser isolation, secure web gateways, and phishing telemetry are more likely to catch this stage than vulnerability scanners.
STEP 04

Abuse the victim browser session

Once executed, the JavaScript can perform actions in the victim's browser context, steal non-HttpOnly data, trigger administrative actions, or stage follow-on phishing. Frameworks like BeEF or custom JavaScript can weaponize the session, but the impact is still bounded by the victim's privileges and browser/session controls.
Conditions required:
  • Payload executes in the victim browser
  • Victim has useful privileges in WordPress
Where this breaks in practice:
  • Impact is usually limited to the victim session rather than direct server-side code execution
  • HttpOnly cookies, CSP, nonce validation, and re-auth flows reduce post-XSS leverage
  • No evidence of active exploitation or KEV inclusion
Detection/coverage: WAFs may block noisy payloads, but reflected XSS often slips past signature-only controls. Browser telemetry and WordPress audit logs can expose suspicious admin actions after the fact.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo confirmed active exploitation found in primary-source review; not in CISA KEV.
Proof-of-concept availabilityNo widely indexed public PoC located in primary-source search. This lowers urgency, but confidence is only LOW-to-MEDIUM because simple reflected XSS payloads are trivial to recreate.
EPSS0.00219 (~0.219%), consistent with a low near-term exploitation probability signal.
KEV / CISA enrichmentOpenCVE shows KEV: no and CISA ADP SSVC values of Exploitation: none, Automatable: no, Technical Impact: partial.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:L — remote, unauthenticated, but click-required and only low CIA impact.
Affected versionsAll versions through 1.1 are affected.
Fixed versionNo official patched version published. Patchstack and Wordfence both mark it effectively unpatched; WordPress.org closed the plugin on 2025-03-24 for a security issue.
Exposure / prevalenceWordfence lists the plugin as Removed, with roughly 3,297 downloads and 60 active installs. That is a very small exposed population compared with enterprise-priority WordPress plugin bugs.
Disclosure / reportingPublicly disclosed 2025-04-01; researcher credited as johska via Patchstack.
Scanner coverage realityInventory-based detection is stronger than perimeter scanning here. Many enterprise scanners will miss abandoned niche plugins unless WordPress plugin enumeration or filesystem inspection is enabled.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (4.8/10)

The single most important brake is mandatory user interaction: this bug does nothing until someone loads a crafted link, which pushes it out of the emergency lane. The second decisive factor is tiny exposure—this is a removed, ancient plugin with a very small active install base, so the reachable population is narrow even before phishing friction is applied.

HIGH Downgrade from vendor HIGH due to user-interaction and narrow exposure population
MEDIUM Assessment that there is no active exploitation / no public PoC of note
HIGH Affected version range and lack of official patch

Why this verdict

  • Start at 7.1 HIGH: the CNA scored it as unauthenticated remote reflected XSS, which is fair in CVSS terms.
  • Downward adjustment for attacker position: exploitation is remote and unauthenticated, but it requires victim browser interaction. That implies a phishing or lure stage that modern email security, browser controls, and user behavior often stop.
  • Downward adjustment for reachability: the product is a removed niche plugin with about 60 active installs reported by Wordfence, so the exposed population is tiny relative to mainstream enterprise web software.
  • Downward adjustment for blast radius: this is session/context abuse, not direct server-side RCE. Impact depends heavily on who clicks and what their WordPress role can do.
  • Downward adjustment for threat evidence: no KEV listing, EPSS is low, and no strong public exploitation signal was found.

Why not higher?

There is no evidence of active exploitation, no KEV listing, and no sign this is being weaponized at scale. More importantly, the chain still hinges on a victim click and then on the victim having useful WordPress privileges, which is materially weaker than a pre-auth server-side bug.

Why not lower?

It is still unauthenticated remote input reaching script execution in a browser, and if an administrator clicks, the attacker may pivot into meaningful site actions. The plugin is also unpatched/removed, so affected installs do not have a clean vendor-upgrade path and need direct operator action.

05 · Compensating Control

What to do — in priority order.

  1. Remove the plugin — If wp-bookmarks exists anywhere, remove it and replace the functionality with a maintained alternative. Because this verdict is MEDIUM, there is no mitigation SLA — go straight to the 365-day remediation window; in practice, abandoned plugins should be eliminated far sooner during normal hygiene work.
  2. Block risky plugin paths at the edge — If immediate removal is delayed, add temporary WAF or reverse-proxy rules for any known wp-bookmarks routes and suspicious reflected-input patterns. This is a stopgap only; for MEDIUM there is no mitigation SLA, but the control reduces opportunistic drive-by exploitation until the plugin is removed.
  3. Hunt by filesystem and inventory — Search fleets for /wp-content/plugins/wp-bookmarks/ and correlate with external site ownership so you can identify the handful of real exposures fast. This is the highest-ROI move for a 10,000-host estate because internet scanning will not reliably find every abandoned plugin.
  4. Protect admin sessions — Enforce MFA on WordPress admin accounts, limit administrator count, and prefer re-auth for sensitive actions where possible. These controls do not fix XSS, but they reduce the value of a compromised browser session while you clean out the plugin.
What doesn't work
  • Blindly trusting network vulnerability scans — they often miss niche or removed WordPress plugins unless plugin enumeration or host inspection is enabled.
  • MFA alone — helpful for account takeover risk, but it does not prevent malicious JavaScript from acting inside an already-authenticated browser session.
  • Relying on a future vendor patch — there is no official fixed version published, and the plugin has already been closed from WordPress.org.
06 · Verification

Crowdsourced verification payload.

Run this on the target WordPress host or on a mounted backup of the webroot. Invoke it as bash check-wp-bookmarks-cve-2025-31431.sh /var/www/html with read access to the WordPress files; root is not required unless your webroot permissions are restrictive.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-wp-bookmarks-cve-2025-31431.sh
# Purpose: Detect whether WordPress plugin wp-bookmarks is installed and vulnerable to CVE-2025-31431.
# Usage: bash check-wp-bookmarks-cve-2025-31431.sh /path/to/wordpress
# Exit codes:
#   0 = PATCHED (plugin absent or version > 1.1)
#   1 = VULNERABLE (plugin present and version <= 1.1)
#   2 = UNKNOWN (cannot determine)

set -u

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

PLUGIN_DIR="$WP_ROOT/wp-content/plugins/wp-bookmarks"
MAIN_FILE=""
VERSION=""

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

# Try likely main plugin files first.
for f in "$PLUGIN_DIR/wp-bookmarks.php" "$PLUGIN_DIR/index.php"; do
  if [[ -f "$f" ]]; then
    MAIN_FILE="$f"
    break
  fi
done

# Fallback: search first-level PHP files for a plugin header or version string.
if [[ -z "$MAIN_FILE" ]]; then
  while IFS= read -r -d '' f; do
    if grep -qiE '^[[:space:]]*Version:[[:space:]]*[0-9]' "$f"; then
      MAIN_FILE="$f"
      break
    fi
  done < <(find "$PLUGIN_DIR" -maxdepth 1 -type f -name '*.php' -print0 2>/dev/null)
fi

# Try readme.txt first, then plugin main file.
if [[ -f "$PLUGIN_DIR/readme.txt" ]]; then
  VERSION=$(grep -iE '^(Stable tag|Version):' "$PLUGIN_DIR/readme.txt" | head -n1 | sed -E 's/^[^:]+:[[:space:]]*//' | tr -d '\r')
fi

if [[ -z "$VERSION" && -n "$MAIN_FILE" && -f "$MAIN_FILE" ]]; then
  VERSION=$(grep -iE '^[[:space:]]*Version:[[:space:]]*' "$MAIN_FILE" | head -n1 | sed -E 's/^[^:]+:[[:space:]]*//' | tr -d '\r')
fi

if [[ -z "$VERSION" ]]; then
  echo "UNKNOWN: wp-bookmarks directory exists but version could not be determined"
  exit 2
fi

# Normalize version string to first token.
VERSION=$(echo "$VERSION" | awk '{print $1}')

# Compare versions using sort -V.
lowest=$(printf '%s\n%s\n' "$VERSION" "1.1" | sort -V | head -n1)
if [[ "$lowest" == "$VERSION" && "$VERSION" != "1.1+" ]]; then
  # VERSION <= 1.1
  echo "VULNERABLE: wp-bookmarks version $VERSION detected at $PLUGIN_DIR"
  exit 1
fi

echo "PATCHED: wp-bookmarks version $VERSION is greater than 1.1"
exit 0
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not treat this like a fleet-wide fire drill. Use inventory or host-side checks to find any WordPress instances still carrying wp-bookmarks, remove or replace the plugin, and document any business exception. For a MEDIUM verdict there is noisgate mitigation SLAno mitigation SLA — go straight to the 365-day remediation window — but because there is no vendor patch and the plugin was removed for a security issue, the practical move is to clean it out during the next normal web-platform maintenance cycle rather than let an abandoned plugin sit until the far edge of the noisgate remediation SLA.

Sources

  1. NVD CVE-2025-31431
  2. Patchstack advisory
  3. Wordfence vulnerability record
  4. Wordfence plugin metadata
  5. WordPress.org plugin page
  6. OpenCVE record
  7. CISA weekly vulnerability bulletin (week of 2025-03-31)
  8. CISA Known Exploited Vulnerabilities Catalog
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.