Post

CVE-2026-11855: Unauthenticated Stored XSS in Simple Membership

Technical analysis of CVE-2026-11855, an unauthenticated stored cross-site scripting vulnerability in the Simple Membership WordPress plugin.

CVE-2026-11855: Unauthenticated Stored XSS in Simple Membership

CVE-2026-11855: Unauthenticated Stored XSS in Simple Membership

Overview

I discovered an unauthenticated stored cross-site scripting vulnerability in the Simple Membership WordPress plugin.

The vulnerability affects Simple Membership versions earlier than 4.7.5 and has been assigned:

  • CVE: CVE-2026-11855
  • Vulnerability type: Unauthenticated Stored Cross-Site Scripting
  • CWE: CWE-79
  • CVSS: 8.8 — High
  • Fixed version: 4.7.5
  • WPVDB ID: 217cb606-a0f2-4427-9262-cfe1cc90474e
  • Original Researcher: Duy Tran
  • Submitter: Duy Tran
  • Verification status: Verified

Summary

The Simple Membership plugin processes Stripe webhook requests through a publicly accessible endpoint.

In the affected version, the Stripe webhook signing secret is not generated automatically during installation and remains empty by default after plugin activation.

When no signing secret is configured, the webhook processing path accepts externally supplied webhook metadata without first confirming that the request originated from Stripe.

An unauthenticated attacker can therefore submit a forged webhook payload containing an attacker-controlled Stripe API version value.

The supplied value is stored in the WordPress database and subsequently rendered inside an administrator-facing notice without sufficient output encoding.

When an administrator opens the WordPress dashboard, the stored value is interpreted as HTML by the browser. This allows attacker-controlled JavaScript to execute automatically in the administrator’s browser context.

Expected Behavior

Webhook metadata should only be trusted after the authenticity and integrity of the webhook request have been verified.

Values originating from external webhook payloads should also be safely encoded immediately before being rendered inside administrator-facing HTML.

Actual Behavior

An unauthenticated attacker can submit a forged Stripe webhook payload that causes attacker-controlled data to be stored by WordPress.

The stored value is later included in an administrator notice without adequate output encoding.

Consequently, arbitrary JavaScript can execute when an authenticated administrator loads the WordPress dashboard.

Vulnerability Chain

The vulnerability results from the combination of two security failures.

1. Missing webhook authenticity verification

The plugin supports verification of Stripe webhook signatures when a signing secret has been configured.

However, the signing secret is empty in the default installation state.

In this state, the affected webhook path processes attacker-controlled requests without establishing that they were generated by Stripe.

This exposes externally supplied webhook metadata to the plugin’s internal processing logic.

2. Unsafe rendering of stored webhook data

An attacker-controlled value extracted from the webhook payload is stored in a WordPress option.

The stored value is later inserted into an administrative notice.

Because the value is not safely encoded for its final HTML output context, browser markup can be injected into the notice.

3. Automatic administrator-side execution

The malicious value is persistent.

The attacker does not need to convince the administrator to open an attacker-controlled URL or click a separate link.

The injected content is rendered when an administrator visits the affected WordPress administration page, causing the browser to execute the stored JavaScript in the context of the authenticated WordPress session.

Trust-Boundary Analysis

The vulnerable data flow can be summarized as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Unauthenticated Internet Request
            |
            v
Public Stripe Webhook Handler
            |
            v
Unverified Webhook Metadata
            |
            v
Persistent WordPress Option
            |
            v
Administrator Notice
            |
            v
JavaScript Execution in Administrator Context

The primary trust-boundary violation occurs when unauthenticated, externally supplied webhook metadata is accepted as trusted application state without cryptographic verification.

A second trust-boundary violation occurs when that stored value is rendered into an HTML document without context-appropriate output encoding.

Impact

Successful exploitation allows an unauthenticated attacker to execute arbitrary JavaScript in the browser of a logged-in WordPress administrator.

Depending on the administrator’s active session and installed components, attacker-controlled JavaScript may be able to:

  • Read administrative pages accessible to the current user
  • Obtain WordPress nonces exposed in dashboard pages
  • Submit privileged requests using the administrator’s authenticated session
  • Modify plugin or site configuration
  • Create or modify users when the required authorization tokens are available
  • Install or modify executable site content through available administrative functionality
  • Establish persistent administrative access through a chained attack

The precise post-exploitation capabilities depend on the WordPress configuration, administrator privileges, available nonces, browser security controls, and installed plugins.

The vulnerability does not require the attacker to authenticate to WordPress.

Attack Preconditions

Exploitation requires the following conditions:

  1. A vulnerable Simple Membership version earlier than 4.7.5 is installed.
  2. The Stripe webhook signing secret is not configured.
  3. An attacker can access the public webhook processing endpoint.
  4. An administrator subsequently loads the affected WordPress administration interface.

The missing signing secret condition is particularly relevant because it occurs in the plugin’s default installation state unless the site administrator manually completes the Stripe webhook configuration.

Technical Validation

The issue was validated in a controlled local research environment using:

  • WordPress: 7.0
  • Simple Membership: 4.7.4
  • PHP: 7.4.27
  • Database: MariaDB 11
  • Attacker authentication: None
  • Victim role: Administrator

Testing confirmed that:

  1. A forged unauthenticated webhook request was accepted while the signing secret was empty.
  2. An attacker-controlled webhook value was stored persistently.
  3. The stored value reached an administrator-facing notice.
  4. The browser parsed the injected markup into the live DOM.
  5. JavaScript executed when the administrator loaded the WordPress dashboard.

Proof of Concept

The complete proof of concept is intentionally withheld during the coordinated disclosure period.

WPScan has scheduled publication of the public PoC for July 06, 2026, allowing additional time for site administrators to update vulnerable installations.

This section will be updated after the coordinated disclosure window ends.

Remediation

Administrators should update Simple Membership to version 4.7.5 or later.

As defense in depth, installations using Stripe should also:

  • Configure the Stripe webhook signing secret
  • Reject webhook requests when signature verification cannot be performed
  • Avoid treating the absence of a signing secret as permission to process unsigned requests
  • Escape all externally derived values at the point of HTML output
  • Remove any suspicious values already stored by the affected webhook workflow

Webhook authentication and output encoding address separate security boundaries. Both protections should be applied independently.

Secure Design Recommendations

Fail closed when webhook verification is unavailable

If a webhook signing secret is missing, malformed, or unavailable, the plugin should reject the incoming webhook rather than process it without authentication.

A missing security control should not silently downgrade the endpoint into an unauthenticated mode.

Verify signatures before parsing trusted metadata

Webhook authenticity should be established before any externally supplied fields are accepted as trusted application state.

Verification should include the raw request body and the provider-supplied signature header according to Stripe’s webhook verification procedure.

Escape at the output boundary

All stored values originating from webhook requests should continue to be treated as untrusted.

Values rendered as text inside administrator notices should be escaped for their exact HTML context immediately before output.

Input sanitization alone should not replace context-sensitive output encoding.

Avoid persisting unnecessary external values

Externally controlled webhook metadata should only be stored when required for a clearly defined application purpose.

Reducing unnecessary persistence also reduces the number of paths through which untrusted data may later reach sensitive output contexts.

Disclosure Timeline

DateEvent
2026Vulnerability discovered and reproduced in a controlled environment
2026Vulnerability submitted for coordinated disclosure
2026Issue independently verified
2026Simple Membership 4.7.5 released with a security fix
2026-06-15CVE-2026-11855 publicly disclosed
2026-06-15WPScan advisory published
2026-07-06Scheduled publication date for the public proof of concept

Additional dates may be added after the complete disclosure process concludes.

Research Credit

This vulnerability was independently discovered and reported by:

Duy Tran

  • Original Researcher: Duy Tran
  • Submitter: Duy Tran
  • Research focus: WordPress plugin security, application security, and vulnerability research

References

  • CVE-2026-11855
  • WPScan Vulnerability Database entry: 217cb606-a0f2-4427-9262-cfe1cc90474e
  • Simple Membership version 4.7.5
  • CWE-79: Improper Neutralization of Input During Web Page Generation

Responsible Disclosure Notice

The exploit request, executable payload, vulnerable source locations, and complete reproduction procedure have been withheld until the scheduled PoC publication date.

The information currently published is intended to document the vulnerability, credit the original research, explain the affected security boundaries, and encourage administrators to update without unnecessarily accelerating exploitation of unpatched systems.

This post is licensed under CC BY 4.0 by the author.