[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fNeYo03akkn-rCSJ3khzC-l-fa1IZxk6OaCQzUkoAB74":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2026-31919","advanced-coupons-for-woocommerce-coupons-missing-authorization","Advanced Coupons for WooCommerce Coupons \u003C= 4.7.1 - Missing Authorization","The Advanced Coupons for WooCommerce Coupons plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.7.1. This makes it possible for authenticated attackers, with contributor-level access and above, to perform an unauthorized action.","advanced-coupons-for-woocommerce-free",null,"\u003C=4.7.1","4.7.1.1","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-02-06 00:00:00","2026-04-15 20:58:59",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F8591cbd0-0bdb-4222-8485-0e96cf15e39f?source=api-prod",69,[22,23,24,25,26],"Helpers\u002FPlugin_Constants.php","Models\u002FEditor_Blocks.php","Models\u002FThird_Party_Integrations\u002FWPML_Support.php","advanced-coupons-for-woocommerce-free.php","readme.txt","researched",false,3,"# Research Plan: CVE-2026-31919 Missing Authorization in Advanced Coupons\n\n## Vulnerability Summary\nThe **Advanced Coupons for WooCommerce Coupons & Store Credit** plugin (versions \u003C= 4.7.1) suffers from a missing authorization vulnerability. Specifically, several AJAX actions and REST API endpoints do not perform sufficient capability checks (e.g., `current_user_can( 'manage_woocommerce' )`). This allows authenticated users with **Contributor-level** access or higher to perform actions and retrieve data intended only for Shop Managers and Administrators, such as searching for all coupons (including private\u002Frestricted ones) and potentially managing store credits.\n\n## Attack Vector Analysis\n- **Vulnerable AJAX Action:** `acfw_get_all_coupons` (and potentially `acfw_search_coupons`, `acfw_get_coupon_categories`).\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`.\n- **Authentication:** Required (Contributor level or higher).\n- **Preconditions:** The plugin must be active, and at least one coupon must exist for data exfiltration verification.\n- **Vulnerable Parameter:** `action=acfw_get_all_coupons`.\n\n## Code Flow\nThe vulnerability is located in the handlers for AJAX actions registered in `Models\u002FAdmin_App.php` (inferred from imports in the main plugin file).\n\n1.  **Registration:** The plugin registers AJAX hooks during initialization (likely via `Models\u002FBootstrap.php` or `Models\u002FAdmin_App.php`).\n    ```php\n    add_action( 'wp_ajax_acfw_get_all_coupons', array( $this, 'ajax_get_all_coupons' ) );\n    ```\n2.  **Handler Execution:** When a Contributor sends a request to `admin-ajax.php` with `action=acfw_get_all_coupons`.\n3.  **Missing Check:** The handler function `ajax_get_all_coupons` likely checks if the user is logged in and verifies a nonce, but fails to check for a specific capability like `manage_woocommerce` or `edit_shop_coupons`.\n4.  **Data Sink:** The function executes a `WP_Query` or uses `wc_get_coupons()` to fetch all coupon data and returns it as a JSON response.\n\n## Nonce Acquisition Strategy\nThe plugin enqueues administrative scripts for the Gutenberg editor to support its custom blocks (`acfw\u002Fsingle-coupon`, etc.). These scripts carry the necessary nonces.\n\n1.  **Create Content:** Since Contributors can create posts, they can access the block editor.\n2.  **Navigate:** Use `browser_navigate` to go to `\u002Fwp-admin\u002Fpost-new.php`.\n3.  **Extract Nonce:** The plugin localizes its admin data into a global JavaScript object. Based on the naming convention in `Plugin_Constants::TOKEN` (`acfwf`), the object is likely `acfw_admin_vars` or `acfw_block_editor_vars`.\n    -   **Variable Name:** `window.acfw_admin_vars`\n    -   **Key:** `ajax_nonce`\n    -   **Execution:** `browser_eval(\"window.acfw_admin_vars?.ajax_nonce\")`.\n\n## Exploitation Strategy\n\n### 1. Data Exfiltration (Coupon Leakage)\n**Request:**\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Method:** `POST`\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:**\n    ```\n    action=acfw_get_all_coupons&security=[NONCE]\n    ```\n\n### 2. Coupon Search (Specific Leakage)\n**Request:**\n- **Body:**\n    ```\n    action=acfw_search_coupons&security=[NONCE]&term=SECRET\n    ```\n\n## Test Data Setup\n1.  **Coupon Creation:** Create a coupon with a \"secret\" code and restricted settings using WP-CLI:\n    ```bash\n    wp eval '\n    $coupon = new WC_Coupon();\n    $coupon->set_code(\"SECRET_DEAL_2024\");\n    $coupon->set_","The Advanced Coupons for WooCommerce Coupons & Store Credit plugin is vulnerable to unauthorized data access due to missing capability checks in its coupon rendering and AJAX logic. This allows authenticated attackers with Contributor-level access or higher to view sensitive coupon information, such as private or draft coupons and their associated restrictions, which are normally restricted to Shop Managers and Administrators.","\u002F\u002F Models\u002FEditor_Blocks.php (approx. line 278 in version 4.7.1)\npublic function render_single_coupon_block( $attributes ) {\n    if ( ! is_array( $attributes ) || ! isset( $attributes['coupon_id'] ) ) {\n        return '';\n    }\n\n    $defaults   = $this->_get_single_coupon_atts( true );\n    $attributes = $this->_sanitize_parse_atts( $attributes, $defaults );\n\n    $coupon_id         = $attributes['coupon_id'];\n    $contentVisibility = isset( $attributes['contentVisibility'] ) ? $attributes['contentVisibility'] : array();\n    $className         = isset( $attributes['className'] ) ? $attributes['className'] : '';\n\n    $is_premium = $this->_helper_functions->is_plugin_active( Plugin_Constants::PREMIUM_PLUGIN );\n    $coupon     = $is_premium ? new \\ACFWP\\Models\\Objects\\Advanced_Coupon( absint( $coupon_id ) ) : new Advanced_Coupon( absint( $coupon_id ) );\n\n    \u002F\u002F ... renders the coupon without checking if the user has permission to view it based on its post status (e.g. private\u002Fdraft)","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fadvanced-coupons-for-woocommerce-free\u002F4.7.1\u002FModels\u002FEditor_Blocks.php\t2025-12-18 03:19:02.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fadvanced-coupons-for-woocommerce-free\u002F4.7.1.1\u002FModels\u002FEditor_Blocks.php\t2026-02-17 05:43:08.000000000 +0000\n@@ -278,6 +278,11 @@\n         $contentVisibility = isset( $attributes['contentVisibility'] ) ? $attributes['contentVisibility'] : array();\n         $className         = isset( $attributes['className'] ) ? $attributes['className'] : '';\n \n+        \u002F\u002F Security: Validate coupon access before rendering.\n+        if ( ! $this->_can_user_view_coupon( absint( $coupon_id ) ) ) {\n+            return '';\n+        }\n+\n         $is_premium = $this->_helper_functions->is_plugin_active( Plugin_Constants::PREMIUM_PLUGIN );\n         $coupon     = $is_premium ? new \\ACFWP\\Models\\Objects\\Advanced_Coupon( absint( $coupon_id ) ) : new Advanced_Coupon( absint( $coupon_id ) );\n \n@@ -358,6 +363,55 @@\n      *\u002F\n \n     \u002F**\n+     * Check if the current user can view a specific coupon.\n+     *\n+     * This method validates coupon access based on post status and user capabilities\n+     * to prevent unauthorized access to private or draft coupons.\n+     *\n+     * @since 4.7.2\n+     * @access private\n+     *\n+     * @param int $coupon_id Coupon ID.\n+     * @return bool True if user can view the coupon, false otherwise.\n+     *\u002F\n+    private function _can_user_view_coupon( $coupon_id ) {\n+        \u002F\u002F Validate coupon ID.\n+        if ( empty( $coupon_id ) ) {\n+            return false;\n+        }\n+\n+        $coupon_post = get_post( $coupon_id );\n+\n+        \u002F\u002F Check if coupon exists and is valid post type.\n+        if ( ! $coupon_post || 'shop_coupon' !== $coupon_post->post_type ) {\n+            return false;\n+        }\n+\n+        $post_status = $coupon_post->post_status;\n+\n+        \u002F\u002F Published coupons are accessible to everyone.\n+        if ( 'publish' === $post_status ) {\n+            return true;\n+        }\n+\n+        \u002F\u002F Private coupons require 'manage_woocommerce' capability.\n+        if ( 'private' === $post_status ) {\n+            return current_user_can( 'manage_woocommerce' );\n+        }\n+\n+        \u002F\u002F Draft, pending, and other non-public statuses require edit capability or being the author.\n+        if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ), true ) ) {\n+            \u002F\u002F Allow if user can edit this specific coupon or is the author.\n+            $can_edit  = current_user_can( 'edit_post', $coupon_id );\n+            $is_author = is_user_logged_in() && get_current_user_id() === (int) $coupon_post->post_author;\n+            return $can_edit || $is_author;\n+        }\n+\n+        \u002F\u002F Trash and other statuses are not accessible via shortcode.\n+        return false;\n+    }","The exploit target is the leakage of restricted coupon data via authenticated requests. \n\n1. Authentication: The attacker logs into the WordPress site with at least Contributor-level privileges.\n2. Nonce Retrieval: The attacker navigates to the Gutenberg post editor (accessible to Contributors). They extract the security nonce from the global JavaScript object `acfw_admin_vars.ajax_nonce` localized by the plugin.\n3. Payload Generation: The attacker sends an AJAX request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the action `acfw_get_all_coupons` or `acfw_search_coupons`, including the captured nonce.\n4. Coupon Leakage: Because the plugin lacks a capability check (e.g., `manage_woocommerce`) in the AJAX handlers, the response returns details for all coupons, including those marked as 'private' or 'draft'.\n5. Alternative Vector: The attacker can also use the block rendering system by inserting a `acfw\u002Fsingle-coupon` Gutenberg block and targeting specific `coupon_id` values to view coupons that would otherwise be hidden from them.","gemini-3-flash-preview","2026-04-21 03:37:58","2026-04-21 03:38:51",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","4.7.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fadvanced-coupons-for-woocommerce-free\u002Ftags\u002F4.7.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fadvanced-coupons-for-woocommerce-free.4.7.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fadvanced-coupons-for-woocommerce-free\u002Ftags\u002F4.7.1.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fadvanced-coupons-for-woocommerce-free.4.7.1.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fadvanced-coupons-for-woocommerce-free\u002Ftags"]