CVE-2026-2554

WCFM – Frontend Manager for WooCommerce along with Bookings Subscription Listings Compatible <= 6.7.25 - Authenticated (Vendor+) Insecure Direct Object Reference to Arbitrary User Deletion

highAuthorization Bypass Through User-Controlled Key
8.1
CVSS Score
8.1
CVSS Score
high
Severity
6.7.26
Patched in
2d
Time to patch

Description

The WCFM – Frontend Manager for WooCommerce along with Bookings Subscription Listings Compatible plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 6.7.25 via the 'wcfm_delete_wcfm_customer' due to missing validation on the 'customerid' user controlled key. This makes it possible for authenticated attackers, with Vendor-level access and above, to delete arbitrary users, including Administrators.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=6.7.25
PublishedMay 1, 2026
Last updatedMay 2, 2026
Affected pluginwc-frontend-manager

What Changed in the Fix

Changes introduced in v6.7.26

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan provides a structured approach for an automated security agent to verify CVE-2026-2554, an Insecure Direct Object Reference (IDOR) vulnerability in the "WCFM – Frontend Manager for WooCommerce" plugin. --- ### 1. Vulnerability Summary The WCFM plugin (up to 6.7.25) contains an I…

Show full research plan

This research plan provides a structured approach for an automated security agent to verify CVE-2026-2554, an Insecure Direct Object Reference (IDOR) vulnerability in the "WCFM – Frontend Manager for WooCommerce" plugin.


1. Vulnerability Summary

The WCFM plugin (up to 6.7.25) contains an IDOR vulnerability in the wcfm_delete_wcfm_customer AJAX action. While the function performs a capability check to ensure the requester is at least a Vendor, it fails to validate if the Vendor has any legitimate association with the user ID provided in the customerid parameter. Consequently, an authenticated Vendor can delete any user on the system, including Administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: delete_wcfm_customer
  • Method: POST
  • Vulnerable Parameter: customerid
  • Authentication: Required (Vendor role or higher)
  • Nonce Action: wcfm_ajax_nonce
  • Nonce Parameter: wcfm_ajax_nonce

3. Code Flow

  1. Entry Point: The AJAX action wp_ajax_delete_wcfm_customer is registered in core/class-wcfm-customer.php (line 64) and mapped to the method WCFM_Customer::wcfm_delete_wcfm_customer.
  2. Nonce Verification: The method calls check_ajax_referer( 'wcfm_ajax_nonce', 'wcfm_ajax_nonce', false ). If valid, execution continues.
  3. Authorization Check: The method checks if the current user has capabilities: manage_woocommerce, wcfm_vendor, seller, or vendor.
  4. Parameter Extraction: It retrieves $customerid = absint( $_POST['customerid'] ).
  5. The Sink: It calls wp_delete_user( $customerid ). Crucially, there is no check (IDOR) to ensure $customerid belongs to the vendor's store or is not an administrator.

4. Nonce Acquisition Strategy

WCFM localizes its AJAX nonces for use in the frontend dashboard. The nonce for wcfm_ajax_nonce is typically stored in a global JavaScript object.

  1. Identify Trigger Page: The WCFM Customers page (/wcfm-customers/ or the WCFM Dashboard) enqueues the necessary scripts.
  2. Access as Vendor: Log in to the test environment with a user assigned the wcfm_vendor role.
  3. Navigation: Navigate to the WCFM Dashboard or any page where the plugin's core JS is loaded.
  4. Extraction: Use browser_eval to extract the nonce from the wcfm_params object (standard in WCFM).
    • JS Command: window.wcfm_params?.wcfm_ajax_nonce
  5. Fallback: If wcfm_params is not found, check wcfm_customers_screen_manage or search the page source for wcfm_ajax_nonce.

5. Exploitation Strategy

The exploit involves sending a crafted POST request to admin-ajax.php as a Vendor.

Step-by-Step:

  1. Identify Target: Determine the User ID of the Administrator to be deleted (usually ID 1).
  2. Formulate Request:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body Parameters:
      • action: delete_wcfm_customer
      • customerid: [TARGET_ADMIN_ID]
      • wcfm_ajax_nonce: [EXTRACTED_NONCE]

Expected Payload Example:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Cookie: [VENDOR_COOKIES]

action=delete_wcfm_customer&customerid=1&wcfm_ajax_nonce=a1b2c3d4e5

6. Test Data Setup

  1. Target User: Ensure an Administrator user exists (e.g., username admin_target, ID 1).
  2. Attacker User: Create a user with the role wcfm_vendor (e.g., username malicious_vendor).
  3. Plugin Setup:
    • Install and activate WooCommerce.
    • Install and activate WCFM – Frontend Manager for WooCommerce version 6.7.25.
    • (Optional) Run the WCFM setup wizard if required to initialize vendor capabilities.
  4. Shortcode Page: If the dashboard is not automatically accessible, create a page with the WCFM dashboard shortcode:
    • wp post create --post_type=page --post_status=publish --post_content='[wcfm_dashboard]' --post_title='Dashboard'

7. Expected Results

  • Response Code: 200 OK
  • Response Body: A JSON string: {"status": true, "message": "Customer successfully deleted."}
  • System State: The user with ID [TARGET_ADMIN_ID] should be removed from the wp_users and wp_usermeta tables.

8. Verification Steps

  1. Check User Existence: Use WP-CLI to verify the target user is gone.
    • wp user get [TARGET_ADMIN_ID] --field=ID
    • Expectation: Error (User ID does not exist).
  2. Database Check: Directly query the users table.
    • wp db query "SELECT COUNT(*) FROM wp_users WHERE ID = [TARGET_ADMIN_ID]"
    • Expectation: 0.

9. Alternative Approaches

  • Reassignment Check: If wp_delete_user fails because of a lack of a reassign ID, the response might be {"status": false, ...}. However, wp_delete_user generally defaults to deleting the user's content if no reassign ID is provided.
  • REST API: Check if the WCFM REST API (if enabled) provides a similar deletion endpoint lacking authorization checks.
  • Role Elevation: If the vendor cannot delete an admin directly, try deleting a "Shop Manager" or another Vendor first to confirm the IDOR logic.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WCFM – Frontend Manager for WooCommerce plugin is vulnerable to an Insecure Direct Object Reference (IDOR) that allows authenticated Vendors to delete any user on the system. By manipulating the 'customerid' parameter in an AJAX request, an attacker can delete arbitrary users, including site Administrators, due to a lack of ownership or role validation.

Vulnerable Code

// core/class-wcfm-customer.php:64
add_action('wp_ajax_delete_wcfm_customer', array(&$this, 'wcfm_delete_wcfm_customer'));

---

// core/class-wcfm-customer.php (logic inferred from research plan analysis)
public function wcfm_delete_wcfm_customer() {
    global $WCFM, $WCFMmp;
    if ( ! check_ajax_referer( 'wcfm_ajax_nonce', 'wcfm_ajax_nonce', false ) ) {
        wp_die();
    }
    if ( !current_user_can( 'manage_woocommerce' ) && !current_user_can( 'wcfm_vendor' ) && !current_user_can( 'seller' ) && !current_user_can( 'vendor' ) ) {
        wp_send_json_error( esc_html__( 'You don&#8217;t have permission to do this.', 'woocommerce' ) );
        wp_die();
    }
    $customerid = absint( $_POST['customerid'] );
    if( $customerid ) {
        if( wp_delete_user( $customerid ) ) {
            echo '{"status": true, "message": "' . esc_html__( 'Customer successfully deleted.', 'wc-frontend-manager' ) . '"}';
        }
    }
    wp_die();
}

Security Fix

--- core/class-wcfm-customer.php
+++ core/class-wcfm-customer.php
@@ -520,6 +520,11 @@
 
 		$customerid = absint( $_POST['customerid'] );
 
+		if ( wcfm_is_vendor() && ! apply_filters( 'wcfm_is_vendor_customer', true, $customerid ) ) {
+			wp_send_json_error( esc_html__( 'You don&#8217;t have permission to do this.', 'woocommerce' ) );
+			wp_die();
+		}
+
 		if( $customerid ) {
 			if( wp_delete_user( $customerid ) ) {
 				echo '{"status": true, "message": "' . esc_html__( 'Customer successfully deleted.', 'wc-frontend-manager' ) . '"}';

Exploit Outline

To exploit this vulnerability, an attacker must have an account with the 'wcfm_vendor' role (or similar vendor-level access). 1. Log in to the WordPress site as a Vendor. 2. Navigate to the WCFM Dashboard to retrieve a valid AJAX nonce (stored in the global JavaScript object 'wcfm_params.wcfm_ajax_nonce'). 3. Send a POST request to the '/wp-admin/admin-ajax.php' endpoint with the following parameters: - action: delete_wcfm_customer - customerid: [The target User ID, such as 1 for the primary Administrator] - wcfm_ajax_nonce: [The retrieved nonce] 4. The plugin will verify that the requester has the 'vendor' capability and then immediately call wp_delete_user() on the provided ID without checking if that user is actually a customer associated with the vendor or if the user is an administrator.

Check if your site is affected.

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