CVE-2026-2600

ElementsKit Elementor Addons and Templates <= 3.7.9 - Authenticated (Contributor+) Stored Cross-Site Scripting via Simple Tab Widget

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.8.0
Patched in
1d
Time to patch

Description

The ElementsKit Elementor Addons and Templates plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'ekit_tab_title' parameter in the Simple Tab widget in all versions up to, and including, 3.7.9 due to insufficient input sanitization and output escaping on user supplied attributes. 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.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=3.7.9
PublishedApril 3, 2026
Last updatedApril 4, 2026
Affected pluginelementskit-lite

What Changed in the Fix

Changes introduced in v3.8.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Vulnerability Research Plan: CVE-2026-2600 - ElementsKit Stored XSS via Simple Tab Widget ## 1. Vulnerability Summary The **ElementsKit Elementor Addons and Templates** plugin (versions <= 3.7.9) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the **Simple Tab*…

Show full research plan

Vulnerability Research Plan: CVE-2026-2600 - ElementsKit Stored XSS via Simple Tab Widget

1. Vulnerability Summary

The ElementsKit Elementor Addons and Templates plugin (versions <= 3.7.9) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists in the Simple Tab widget (often referred to as the "Tab" widget in the UI). Specifically, the ekit_tab_title parameter, which stores the title of a tab item, is not properly sanitized upon input or escaped upon output. This allows an authenticated attacker with Contributor-level permissions (who can edit posts via Elementor) to inject malicious JavaScript into a page. The script executes whenever a user (including administrators) views the affected page.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: elementor_ajax (used by the Elementor editor to save widget data)
  • Sub-Action: save_builder_data
  • Vulnerable Parameter: ekit_tab_title (within the settings object of an elementskit-tab widget)
  • Required Authentication: Contributor or higher.
  • Preconditions:
    • The ElementsKit Lite plugin is active.
    • The Elementor plugin is active.
    • The attacker has a Contributor account and can edit a post/page using the Elementor editor.

3. Code Flow

  1. Input: A user with Contributor access opens a post in the Elementor editor.
  2. Action: The user adds an "ElementsKit Tab" widget and sets a tab title.
  3. Transmission: Elementor sends a POST request to admin-ajax.php?action=elementor_ajax. The payload is a JSON string containing the widget's settings.
  4. Processing: The plugin (via Elementor's framework) saves these settings into the WordPress database as post metadata (_elementor_data).
  5. Vulnerable Parameter Path:
    • settings -> ekit_tab_items (repeater) -> ekit_tab_title.
  6. Rendering (Sink): When the page is viewed on the frontend, the widget's rendering function (likely in a file like widgets/tab/tab.php, though not provided in the snippet, this is standard ElementsKit architecture) iterates through the tab items.
  7. Output: The value of ekit_tab_title is echoed to the page without being passed through esc_html() or a restrictive wp_kses() call.

4. Nonce Acquisition Strategy

Elementor uses its own internal security nonce for AJAX operations. To successfully save builder data, we must obtain this nonce.

Acquisition Steps:

  1. Login: Authenticate as a Contributor.
  2. Access Editor: Create a new post or edit an existing one: wp-admin/post.php?post=POST_ID&action=elementor.
  3. Extract Nonce: The Elementor nonce is stored in a JavaScript object localized on the page.
  4. JS Variable: window.elementorCommonConfig.ajax.nonce or window.elementorConfig.ajax.nonce.
  5. Tool Usage: Use browser_navigate to open the editor and browser_eval to extract the nonce.
// Extraction payload
const nonce = window.elementorCommonConfig?.ajax?.nonce || window.elementorConfig?.ajax?.nonce;
return nonce;

5. Exploitation Strategy

The exploit involves sending a crafted Elementor AJAX request to update a post's content with a malicious ElementsKit Tab widget.

Step-by-Step Plan:

  1. Identify Post: Find a post ID that the Contributor can edit.
  2. Fetch Nonce: Navigate to the Elementor editor for that post and extract the nonce as described in Section 4.
  3. Craft Payload: Create a JSON payload for the elementor_ajax action.
    • action: elementor_ajax
    • _nonce: [EXTRACTED_NONCE]
    • actions: A JSON-encoded object containing the save_builder_data command.
  4. Malicious Widget Data:
    {
      "id": "malicious-tab-id",
      "elType": "widget",
      "widgetType": "elementskit-tab",
      "settings": {
        "ekit_tab_items": [
          {
            "ekit_tab_title": "<img src=x onerror=alert('CVE-2026-2600')>",
            "ekit_tab_content": "Standard Content"
          }
        ]
      }
    }
    
  5. HTTP Request:
    • Method: POST
    • URL: [TARGET_URL]/wp-admin/admin-ajax.php
    • Content-Type: application/x-www-form-urlencoded
    • Body:
      action=elementor_ajax&
      _nonce=[NONCE]&
      actions={"save_builder_data":{"post_id":"[POST_ID]","data":[{"id":"container-id","elType":"container","settings":[],"elements":[{"id":"malicious-tab-id","elType":"widget","widgetType":"elementskit-tab","settings":{"ekit_tab_items":[{"ekit_tab_title":"<img src=x onerror=alert('CVE-2026-2600')>","ekit_tab_content":"Content"}]}}]}]}}
      

6. Test Data Setup

  1. User: Create a user with the contributor role.
  2. Post: Create a post with post_status='publish' authored by the contributor.
  3. Plugin Config: Ensure elementskit-lite is active. In the ElementsKit dashboard, ensure the "Tab" widget is enabled (it is enabled by default in config/widget-list.php).

7. Expected Results

  • The HTTP request should return a 200 OK with a JSON body indicating success: {"success":true,"data":{...}}.
  • When navigating to the post URL on the frontend (e.g., /?p=[POST_ID]), an alert box with CVE-2026-2600 should appear.
  • The HTML source of the page should contain: <img src=x onerror=alert('CVE-2026-2600')>.

8. Verification Steps

  1. WP-CLI: Verify the meta value is stored in the database.
    wp post meta get [POST_ID] _elementor_data
    
  2. Check for Payload: Inspect the output of the CLI command for the presence of the <img src=x ...> string.
  3. Frontend Check: Use the browser_navigate tool to the frontend URL of the post and check for the execution of the alert.

9. Alternative Approaches

  • SVG Infiltration: If <script> or <img> tags are filtered by a WAF but wp_kses is used with the get_kses_array() from helpers/utils.php, note that svg and path tags are allowed in that list (Lines 163-176). An attacker might try injecting an SVG with an onload attribute if the kses call is present but misconfigured.
  • Style Injection: If the title is rendered inside a style attribute (unlikely for a title, but possible for styling tab headers), one could use expression() (old IE) or breakout techniques.
  • REST API: Check if the elementskit/v1/widget-builder endpoint (seen in config/module-list.php) allows modification of widget data without going through Elementor's standard AJAX. (Requires checking core/handler-api.php).
Research Findings
Static analysis — not yet PoC-verified

Summary

The ElementsKit Elementor Addons and Templates plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Simple Tab widget. Authenticated attackers with contributor-level permissions can inject malicious JavaScript into the 'ekit_tab_title' parameter, which is then executed in the context of any user viewing the affected page due to missing output escaping.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.7.9/config/module-list.php /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.8.0/config/module-list.php
--- /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.7.9/config/module-list.php	2026-02-03 09:00:52.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.8.0/config/module-list.php	2026-02-24 06:00:14.000000000 +0000
@@ -136,6 +136,12 @@
 					'title'             => 'Global Badge',
 					'attributes'        => array( 'new' ),
 				],
+				'scroll-reveal' => [
+					'slug'              => 'scroll-reveal',
+					'package'           => 'pro-disabled',
+					'title'             => 'Scroll Reveal',
+					'attributes'        => array( 'upcoming' ),
+				],
 			)
 		);
 	}
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.7.9/config/widget-list.php /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.8.0/config/widget-list.php
--- /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.7.9/config/widget-list.php	2026-02-03 09:00:52.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/elementskit-lite/3.8.0/config/widget-list.php	2026-02-24 06:00:14.000000000 +0000
@@ -277,282 +277,329 @@
 					'title'           => 'Advanced Accordion',
 					'package'         => 'pro-disabled',
 					'widget-category' => 'advanced', // advanced
+					'icon'            => 'ekit ekit-accordion',
 				),
 				'advanced-tab' => array(
 					'slug'            => 'advanced-tab',
 					'title'           => 'Advanced Tab',
 					'package'         => 'pro-disabled',
 					'widget-category' => 'advanced', // advanced
+					'icon'            => 'ekit ekit-tab',
 				),

Exploit Outline

To exploit this vulnerability, an attacker must have at least Contributor-level access to the WordPress site. The attacker performs the following steps: 1. Log in to the WordPress dashboard as a Contributor. 2. Access the Elementor editor for a post or page the user is authorized to edit. 3. Extract the required Elementor AJAX nonce from the localized JavaScript object `window.elementorCommonConfig.ajax.nonce`. 4. Craft a malicious JSON payload targeting the `elementor_ajax` endpoint with the `save_builder_data` action. 5. The payload includes an `elementskit-tab` widget containing a repeater item where the `ekit_tab_title` parameter is set to a malicious script, such as `<img src=x onerror=alert(document.domain)>`. 6. Send the crafted POST request to `/wp-admin/admin-ajax.php`. 7. Once saved, the script will execute in the browser of any user who navigates to the public URL of the modified post.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.