CVE-2026-12654 Overview
CVE-2026-12654 is an authorization bypass vulnerability in the Payment Plugins for Stripe WooCommerce plugin for WordPress. The flaw affects all versions up to and including 4.0.7. The plugin fails to properly verify that a caller is authorized to trigger order state changes through the Stripe webhook endpoint. Unauthenticated attackers can forge a charge.pending event with attacker-controlled metadata.order_id, metadata.gateway_id, and a charge object containing status=succeeded and captured=true. The forged event triggers payment_complete() and downstream fulfillment, marking arbitrary pending asynchronous WooCommerce orders as paid with an attacker-supplied transaction ID. The issue is classified under [CWE-862] Missing Authorization.
Critical Impact
Unauthenticated attackers can fraudulently mark pending WooCommerce orders as paid, triggering merchant fulfillment of goods and services without payment when the webhook secret is left unconfigured.
Affected Products
- Payment Plugins for Stripe WooCommerce plugin for WordPress, all versions up to and including 4.0.7
- WordPress installations running the woo-stripe-payment plugin with WooCommerce
- Merchant sites where webhook_secret_test or webhook_secret_live remains blank (plugin default state)
Discovery Timeline
- 2026-07-24 - CVE-2026-12654 published to NVD
- 2026-07-24 - Last updated in NVD database
Technical Details for CVE-2026-12654
Vulnerability Analysis
The vulnerability resides in the plugin's Stripe webhook controller and its handling of charge.pending events. The webhook endpoint accepts POST requests without enforcing signature validation when the merchant's webhook_secret_test or webhook_secret_live option is empty. This default configuration state persists until an administrator manually pastes a Stripe-issued whsec_ value into the plugin settings. An attacker constructs a JSON payload mimicking a legitimate Stripe charge.pending event and submits it directly to the site's webhook route. The plugin trusts the payload, parses attacker-controlled metadata.order_id and metadata.gateway_id, and treats the embedded status=succeeded and captured=true fields as authoritative. Order fulfillment logic then invokes payment_complete(), transitioning the order out of pending asynchronous status.
Root Cause
The root cause is missing authorization enforcement on the webhook endpoint, mapped to [CWE-862]. The plugin conditionally applies Stripe signature verification only when a webhook secret is configured. When the secret is blank, the code path skips verification entirely rather than rejecting the request. Trust is placed in unverified client-supplied JSON.
Attack Vector
Exploitation requires network access to the target site's webhook URL. No authentication or user interaction is needed. The attacker must know or enumerate valid pending order IDs, then POST a crafted charge.pending event to the plugin webhook route. Prerequisite conditions: the merchant has not configured a Stripe webhook secret, and asynchronous payment methods are in use. Once a non-empty whsec_ value is set, signature verification runs and forged requests are rejected.
See the Wordfence Vulnerability Report and the WordPress Stripe Webhook Functions source for technical details of the vulnerable handler.
Detection Methods for CVE-2026-12654
Indicators of Compromise
- Unexpected POST requests to the plugin webhook endpoint (typically /?wc-api=wc_stripe_webhook or similar) originating from IPs outside published Stripe webhook ranges.
- WooCommerce orders transitioning from pending to processing or completed without a corresponding entry in the Stripe Dashboard.
- Order transaction IDs that do not match any Stripe ch_ or pi_ identifier issued by the merchant account.
- Fulfillment activity on orders where the associated payment method is asynchronous but no Stripe balance transaction exists.
Detection Strategies
- Compare WooCommerce order transaction IDs against Stripe API records on a scheduled basis and alert on mismatches.
- Inspect web server access logs for POST requests to the Stripe webhook path with source IPs not in the Stripe webhook IP allowlist.
- Monitor plugin settings for a blank webhook_secret_test or webhook_secret_live value on production sites.
Monitoring Recommendations
- Enable WooCommerce order audit logging and ship events to a centralized log platform for correlation with Stripe webhook delivery logs.
- Alert on order status transitions occurring without a matching Stripe event ID in the plugin's webhook receive log.
- Track outbound fulfillment actions (shipping label creation, license issuance) tied to orders lacking verified Stripe payment intents.
How to Mitigate CVE-2026-12654
Immediate Actions Required
- Update the Payment Plugins for Stripe WooCommerce plugin to a version above 4.0.7 that includes the patch referenced in the WordPress Stripe Changeset.
- Configure a valid Stripe-issued webhook secret (whsec_ value) in both webhook_secret_test and webhook_secret_live plugin settings immediately, even before patching.
- Reconcile all recent pending and asynchronous WooCommerce orders against the Stripe Dashboard to identify fraudulent completions.
- Halt fulfillment on any suspicious orders until payment can be verified through the Stripe API directly.
Patch Information
The vendor has released a patched version of the woo-stripe-payment plugin. Refer to the Wordfence Vulnerability Report and the WordPress Stripe Changeset for the fixed release version and code diff.
Workarounds
- Configure webhook_secret_test and webhook_secret_live with valid Stripe whsec_ values; signature verification cannot be bypassed once a non-empty secret is set.
- Restrict access to the WordPress webhook endpoint at the web server or WAF layer, allowing only Stripe's published webhook IP ranges.
- Disable asynchronous Stripe payment methods on affected sites until the plugin is patched and the webhook secret is configured.
# Restrict Stripe webhook endpoint to Stripe IP ranges (nginx example)
location ~* /wc-api/wc_stripe_webhook {
allow 3.18.12.0/24;
allow 3.130.192.0/24;
allow 13.235.14.0/24;
allow 13.235.122.0/24;
allow 18.211.135.0/24;
allow 35.154.171.0/24;
allow 52.15.183.0/24;
allow 54.88.130.0/24;
allow 54.88.130.0/24;
allow 54.187.174.0/24;
allow 54.187.205.0/24;
allow 54.187.216.0/24;
deny all;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

