← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-6898 · CWE-269 · Disclosed 2026-05-23

The Wishlist Member plugin for WordPress is vulnerable to unauthorized modification of data due to a…

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

This is a front-desk badge printer that will issue a master key if any paying guest presses the right button

CVE-2026-6898 is a missing capability check in WishListMember3_Hooks::generate_api_key in WishList Member for WordPress. Affected versions are all releases up to and including 3.30.1; the fix is reported by Patchstack as 3.31.0. The vulnerable path lets an authenticated low-privilege user hit the wlm3_generate_api_key AJAX action, replace the plugin's REST API secret, and then use that new secret to create an administrator-capable membership level and an arbitrary admin user.

The vendor-style 8.8 HIGH score gets the *impact* right but overstates the *reach*. This is not unauthenticated remote code execution against every public WordPress site; it needs a valid account first and a commercial plugin with a relatively small exposed footprint. But because this is a membership plugin, the Subscriber prerequisite is materially weaker than it sounds in many real deployments, so this stays HIGH instead of dropping to medium.

"This is not internet-wide spray-and-pray, but on a real membership site one cheap subscriber can become admin."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land a Subscriber account

The attacker first needs any authenticated WordPress account that can reach admin-ajax.php. On WishList Member deployments, that often means self-registration, cheap trial access, reused credentials, or a previously compromised customer account rather than a full initial breach. Tooling is pedestrian: Burp Suite, curl, or credential-stuffing kits are enough.
Conditions required:
  • WishList Member is installed and vulnerable (<= 3.30.1)
  • Attacker has valid WordPress credentials at Subscriber level or above
  • The site exposes a member login or registration path
Where this breaks in practice:
  • No unauthenticated path
  • Closed-membership sites with manual approval block the easiest route
  • MFA or anti-automation on login raises cost
Detection/coverage: Most scanners catch this only by plugin version, not exploit simulation. Auth log telemetry, failed-login bursts, and unusual new subscriber creation are your best early signals.
STEP 02

Call wlm3_generate_api_key

Using a standard authenticated request to /wp-admin/admin-ajax.php, the attacker invokes the vulnerable AJAX action that ultimately reaches WishListMember3_Hooks::generate_api_key. Because the function lacks a capability check, the application treats a Subscriber like an administrator for this operation. The weaponized tools here are simple HTTP clients, not exploit frameworks.
Conditions required:
  • Authenticated session or valid cookies/nonces if required by the action wiring
  • Endpoint reachable at /wp-admin/admin-ajax.php
Where this breaks in practice:
  • A WAF or custom rule targeting the specific AJAX action can stop this cold
  • Some sites may layer extra access control around admin AJAX
  • Nonce handling can slow blind automation even if it does not fix the bug
Detection/coverage: Good WAFs and virtual patching products can key on action=wlm3_generate_api_key. Native WordPress logs usually do not give enough semantic detail unless request logging is already enabled.
STEP 03

Rotate the REST API secret

The immediate impact is not code execution; it is control of the plugin's REST trust anchor. Once the attacker generates or overwrites the REST API secret key, they can authenticate to WishList Member's API as if they were the site owner. That turns a low-privilege web account into an admin creation primitive.
Conditions required:
  • The AJAX action successfully updates or exposes the API secret
  • WishList Member REST API functionality is enabled as normal
Where this breaks in practice:
  • If API access is disabled or heavily filtered, the chain may stop here
  • Operators who rotate the secret quickly can invalidate attacker follow-on requests
Detection/coverage: Look for sudden API key regeneration, especially when performed by non-admin users or followed immediately by API calls from the same source IP.
STEP 04

Create an admin-mapped level and user

With the new secret, the attacker uses the WishList Member API 2.0 workflow to create a membership level mapped to the WordPress Administrator role and then registers a new user into it. From there, the attacker has durable admin access and can install plugins, edit themes, or drop persistence. Weaponized follow-on tooling becomes normal WordPress post-exploitation tradecraft.
Conditions required:
  • Attacker can reach the WishList Member API endpoints
  • API operations permit level creation and user registration
  • No secondary control blocks role assignment changes
Where this breaks in practice:
  • Change monitoring on roles, plugins, or newly created admins can contain blast radius
  • Some hardened sites disable plugin/theme editing from the dashboard
Detection/coverage: This is where defenders usually have the best shot: alert on new admin accounts, membership-level changes mapping to administrator, and plugin/theme installs shortly after member-logins.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo CISA KEV listing found, and I found no primary-source public exploitation bulletin for this exact CVE.
Proof-of-concept availabilityI found no exact public PoC for CVE-2026-6898; however, the exploit path is low-complexity and Patchstack/NVD describe the vulnerable AJAX action clearly enough that reproduction is straightforward.
EPSS0.00044 from the user-provided intel block, which is very low and consistent with a niche product plus authenticated-only reach.
KEV statusNot listed in the CISA Known Exploited Vulnerabilities Catalog.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — the crucial term is PR:L. On paper that is a major brake; on a membership plugin it is less comforting because low-privilege users are part of the product design.
Affected versionsAuthoritative CVE/NVD text says all versions up to and including 3.30.1 are affected.
Fixed versionPatchstack reports 3.31.0 as the patched version. Vendor release notes for 3.31.0 list security fixes, though they do not name this CVE explicitly.
Exposure footprintWebTechSurvey currently reports roughly 468 observed domains using WishList Member X, with 280 in the U.S. That is not tiny, but it is far from a mass-market WordPress plugin.
Disclosure timelineNVD published the CVE on 2026-05-23; Patchstack published its advisory on 2026-05-25.
Researcher / sourceNVD lists Wordfence as the source CNA. Patchstack credits researcher h0xilo on its advisory page.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (7.7/10)

The single most decisive factor is that this bug requires authenticated Subscriber access, which cuts out true internet-wide opportunistic exploitation. It still lands in HIGH because this is a membership plugin: on many affected sites, low-privilege member accounts are easy to obtain and the end state is full WordPress administrator takeover.

HIGH Affected version range and impact chain through REST API secret takeover
MEDIUM Patched version `3.31.0` based on Patchstack/vulnerability aggregation rather than an explicit vendor CVE mapping
MEDIUM Real-world prevalence and exploitability assumptions across mixed membership-site deployments

Why this verdict

  • Downgrade from 8.8: PR:L matters in the real world; the attacker needs a working account first, which is a meaningful prerequisite versus unauthenticated WordPress bugs.
  • Not a full downgrade to medium: this is a *membership* plugin, so Subscriber accounts are often normal business objects, not rare internal users. That weakens the usual comfort defenders take from PR:L.
  • Blast radius is total on a hit: once the REST API secret is rotated, the attacker can create an admin-capable membership level and arbitrary admin users, which is effectively site takeover.
  • Exposure is narrower than commodity WordPress bugs: observed public footprint is in the hundreds of domains, not hundreds of thousands, which caps campaign value and keeps the score below the vendor baseline.
  • Threat intel is quiet: no KEV entry, no exact public PoC located, and a very low EPSS all argue against pushing this into the top emergency tier today.

Why not higher?

This is not unauthenticated and not broadly applicable across the WordPress ecosystem; it only matters where WishList Member is installed and vulnerable. I also found no hard evidence of active exploitation or an exact public PoC for this CVE, which removes the biggest reason to score it as near-critical.

Why not lower?

On affected membership sites, the authentication requirement is often weak in practice because obtaining or creating a low-tier member account may be cheap, automated, or entirely expected. And once the bug is reached, the chain does not stop at data tampering; it ends in administrator creation and durable control of the site.

05 · Compensating Control

What to do — in priority order.

  1. Block the AJAX action — Deploy a WAF or reverse-proxy rule that denies requests to /wp-admin/admin-ajax.php when action=wlm3_generate_api_key. This is the cleanest temporary choke point and should be in place within 30 days if you cannot patch immediately.
  2. Freeze low-trust registrations — Disable open signup, free trials, or automated member onboarding on vulnerable sites until patched if the business can tolerate it. This attacks the most important prerequisite — a Subscriber account — and should be applied within 30 days where patching lags.
  3. Alert on admin creation and role-map drift — Add detections for new administrator users, membership-level changes mapped to admin, and API key regeneration events. This will not prevent exploitation, but it gives you the best chance of catching follow-on abuse within 30 days while patch rollout finishes.
  4. Constrain admin AJAX where possible — If member workflows do not require broad admin AJAX access, put path-based filtering or authenticated application proxy rules in front of /wp-admin/admin-ajax.php. Apply within 30 days on internet-facing membership sites that cannot be patched quickly.
  5. Cull stale subscribers — Remove dormant member accounts, especially trial, coupon, and abandoned-payment users. Reducing the pool of low-privilege accounts lowers the exploitable population and should be completed within 30 days for exposed sites.
What doesn't work
  • Relying on nonce checks alone does not solve a missing capability check; a valid low-privilege session can still be unauthorized for the action.
  • Generic EDR on the web server will not stop the initial privilege escalation because the exploit is an application-layer logic bug, not malware execution at first touch.
  • Blocking /wp-admin/ broadly does not necessarily help if legitimate member workflows already expose admin-ajax.php; many WordPress sites intentionally leave that path reachable.
06 · Verification

Crowdsourced verification payload.

Run this on the target WordPress host or a mounted web root from an auditor workstation. Invoke it as bash check_wlm_cve_2026_6898.sh /var/www/html and use a user that can read the WordPress files; root is not required unless filesystem permissions are tight.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_wlm_cve_2026_6898.sh
# Detects whether WishList Member for WordPress is vulnerable to CVE-2026-6898
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 1=vulnerable, 0=patched, 2=unknown

set -u

SAFE_VERSION="3.31.0"
WP_PATH="${1:-.}"
PLUGIN_SLUG="wishlist-member-x"
PLUGIN_DIR="$WP_PATH/wp-content/plugins/$PLUGIN_SLUG"

verlte() {
  [ "$1" = "$2" ] && return 0
  [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}

extract_version_from_file() {
  local f="$1"
  [ -f "$f" ] || return 1
  awk -F': *' '/^[[:space:]]*Version:[[:space:]]*/ {print $2; exit}' "$f" | tr -d '\r'
}

find_version() {
  local v=""

  if command -v wp >/dev/null 2>&1; then
    v=$(wp --path="$WP_PATH" plugin get "$PLUGIN_SLUG" --field=version 2>/dev/null | tr -d '\r')
    if [ -n "$v" ]; then
      printf '%s' "$v"
      return 0
    fi
  fi

  if [ ! -d "$PLUGIN_DIR" ]; then
    return 1
  fi

  for candidate in \
    "$PLUGIN_DIR/wishlist-member-x.php" \
    "$PLUGIN_DIR/wishlist-member.php" \
    "$PLUGIN_DIR/plugin.php" \
    "$PLUGIN_DIR/wlm.php" \
    "$PLUGIN_DIR/loader.php"
  do
    v=$(extract_version_from_file "$candidate")
    if [ -n "$v" ]; then
      printf '%s' "$v"
      return 0
    fi
  done

  v=$(grep -R -m1 -h -E '^[[:space:]]*Version:[[:space:]]*[0-9]+' "$PLUGIN_DIR" 2>/dev/null | head -n1 | sed -E 's/^[[:space:]]*Version:[[:space:]]*//; s/\r$//')
  if [ -n "$v" ]; then
    printf '%s' "$v"
    return 0
  fi

  return 1
}

VERSION="$(find_version)"
STATUS=$?

if [ $STATUS -ne 0 ] || [ -z "$VERSION" ]; then
  echo "UNKNOWN: Could not determine WishList Member version at $WP_PATH"
  exit 2
fi

if verlte "$VERSION" "3.30.1"; then
  echo "VULNERABLE: WishList Member version $VERSION is <= 3.30.1 (fixed in $SAFE_VERSION or later)"
  exit 1
fi

if verlte "$SAFE_VERSION" "$VERSION"; then
  echo "PATCHED: WishList Member version $VERSION is >= $SAFE_VERSION"
  exit 0
fi

echo "UNKNOWN: Detected version $VERSION but could not classify confidently"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: identify every internet-facing WordPress site running WishList Member <= 3.30.1, prioritize the ones that allow self-registration or have large subscriber populations, and put an interim block on the wlm3_generate_api_key AJAX action where patching is not immediate. For a HIGH verdict, the noisgate mitigation SLA is within 30 days for compensating controls, and the noisgate remediation SLA is within 180 days for the actual upgrade to 3.31.0 or later; in practice, anything public-facing with open member onboarding should be treated faster than the bare SLA because the auth prerequisite is weaker than normal on this product.

Sources

  1. NVD CVE-2026-6898
  2. Patchstack advisory for CVE-2026-6898
  3. WishList Member changelog index
  4. WishList Member 3.31.0 release notes
  5. CISA Known Exploited Vulnerabilities Catalog
  6. FIRST EPSS API documentation
  7. WebTechSurvey WishList Member X footprint
  8. CVE record page
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.