CVE-2026-27074

Shortcoder — Create Shortcodes for Anything <= 6.5.1 - Authenticated (Contributor+) Stored Cross-Site Scripting

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

Description

The Shortcoder — Create Shortcodes for Anything plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 6.5.1 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<=6.5.1
PublishedJanuary 9, 2026
Last updatedMarch 6, 2026
Affected pluginshortcoder

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **Shortcoder — Create Shortcodes for Anything** plugin (version <= 6.5.1). ## 1. Vulnerability Summary The "Shortcoder" plugin allows users to create custom shortcodes containing HTML, JavaScri…

Show full research plan

This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the Shortcoder — Create Shortcodes for Anything plugin (version <= 6.5.1).

1. Vulnerability Summary

The "Shortcoder" plugin allows users to create custom shortcodes containing HTML, JavaScript, and CSS. The vulnerability exists because the plugin fails to sanitize or escape the content of these custom shortcodes when they are saved by a user with Contributor permissions or higher. While Administrators are expected to have unfiltered_html capabilities, Contributors are not. The plugin incorrectly permits Contributors to save arbitrary scripts within a shortcode definition, which then executes in the context of any user (including Administrators) who views a page where the shortcode is deployed.

2. Attack Vector Analysis

  • Endpoint: WordPress Admin Post Save (/wp-admin/post.php) or the Plugin's AJAX Save handler.
  • Vulnerable Parameter: content (the shortcode body) or a specific meta field like sc_content (inferred).
  • Authentication Level: Authenticated, Contributor-level access (PR:L).
  • Preconditions: The "Shortcoder" plugin must be configured to allow Contributors to manage shortcodes, or the plugin must fail to check capabilities on its custom post type shortcoder.

3. Code Flow (Inferred)

  1. Entry Point: A Contributor user navigates to the "Shortcoder" menu and creates a new shortcode or edits an existing one.
  2. Request: The user submits the form. This triggers either a standard wp-admin/post.php request (if using the Custom Post Type logic) or an AJAX request to admin-ajax.php with action=shortcoder_save (inferred).
  3. Validation: The plugin performs a nonce check but fails to check if the current user has the unfiltered_html capability before saving the shortcode content.
  4. Sink: The raw input is saved into the database (either as post_content or post_meta).
  5. Execution: When a page containing [sc name="my-xss-shortcode"] is rendered, the plugin retrieves the raw content from the database and echoes it to the page without using wp_kses_post() or esc_html().

4. Nonce Acquisition Strategy

To save a shortcode, we need a valid WordPress nonce associated with the shortcode editor.

  1. Identify Shortcode Editor: The plugin uses a Custom Post Type named shortcoder.
  2. Create Page for Context: Use WP-CLI to ensure the editor is accessible.
  3. Navigate and Extract:
    • Navigate to /wp-admin/post-new.php?post_type=shortcoder using browser_navigate.
    • Use browser_eval to extract the nonce from the hidden input field.
    • Variable Name: document.querySelector('#_wpnonce')?.value (Standard WordPress post nonce).

5. Exploitation Strategy

Step 1: Login and Nonce Extraction

  • Action: Log in as a Contributor.
  • URL: /wp-admin/post-new.php?post_type=shortcoder
  • Tool: browser_navigate followed by browser_eval.
  • JS to Execute: document.querySelector('#_wpnonce').value

Step 2: Inject Stored XSS Payload

  • Action: Send a POST request to save a new shortcode containing the XSS payload.
  • Tool: http_request
  • URL: http://localhost:8080/wp-admin/post.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Payload Parameters:
    action=editpost
    post_type=shortcoder
    post_title=Exploit
    content=<script>alert(document.domain);</script>
    _wpnonce=[EXTRACTED_NONCE]
    
    (Note: If the plugin uses a custom meta field for the shortcode body instead of content, the parameter may be sc_content or shortcode_content (inferred)).

Step 3: Deploy the Shortcode

  • Action: Create a regular WordPress post and embed the shortcode created in Step 2.
  • Tool: http_request or wp-cli.
  • Shortcode Syntax: [sc name="Exploit"]

Step 4: Trigger and Verify

  • Action: Access the post created in Step 3 as an Administrator.
  • Outcome: An alert box should appear, proving the script execution.

6. Test Data Setup

  1. User: Create a user with the contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Plugin Setup: Ensure the "Shortcoder" plugin is active.
  3. Page Creation: Create a placeholder post where the shortcode will be placed.
    • wp post create --post_title="Victim Page" --post_status=publish --post_content='[sc name="Exploit"]'

7. Expected Results

  • The POST request to /wp-admin/post.php should return a 302 Found redirect, indicating successful post creation.
  • When navigating to the "Victim Page", the HTML source code should contain the raw <script>alert(document.domain);</script> tag.
  • The browser should execute the JavaScript alert.

8. Verification Steps

  1. Check Database: Verify the payload is stored in the wp_posts table for the shortcoder post type.
    • wp db query "SELECT post_content FROM wp_posts WHERE post_type='shortcoder' AND post_title='Exploit'"
  2. Verify Frontend Output: Use http_request to fetch the victim page and check for the payload.
    • Look for the specific script string in the response body.

9. Alternative Approaches

  • AJAX Endpoint: If the standard post.php save is blocked or not used, look for an AJAX handler registered via wp_ajax_shortcoder_save or wp_ajax_sc_save.
  • Shortcode Parameters: If the shortcode definition itself is sanitized, try injecting the payload through a shortcode attribute if the definition uses that attribute unescaped:
    • Definition: <div>%%myattr%%</div>
    • Usage: [sc name="test" myattr="<script>alert(1)</script>"]
  • Capability Bypass: Check if the plugin has a settings page (e.g., /wp-admin/admin.php?page=shortcoder-settings) that allows setting the "Minimum capability to create shortcodes". If this can be modified by a lower user, it's a separate escalation.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Shortcoder plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) because it fails to sanitize or escape the content of custom shortcodes during creation and display. This allows authenticated attackers with Contributor-level permissions to inject malicious JavaScript into shortcodes, which then executes in the browser of any user who views a page containing the shortcode.

Security Fix

--- a/includes/shortcoder-shortcode-renderer.php
+++ b/includes/shortcoder-shortcode-renderer.php
@@ -45,5 +45,5 @@
-echo $shortcode_content;
+if (current_user_can('unfiltered_html')) {
+    echo $shortcode_content;
+} else {
+    echo wp_kses_post($shortcode_content);
+}

Exploit Outline

To exploit this vulnerability, an attacker with Contributor-level access follows these steps: 1. Log in to the WordPress dashboard and navigate to the 'Shortcoder' section to create a new shortcode. 2. In the shortcode content editor, enter a malicious JavaScript payload such as '<script>alert(document.cookie)</script>'. 3. Save the shortcode and note its name (e.g., [sc name="xss-payload"]). 4. Create a new post or use an existing one to embed the shortcode: [sc name="xss-payload"]. 5. Once an administrator or any other user views the post containing the embedded shortcode, the stored JavaScript payload will execute in their browser context, potentially allowing for session hijacking or unauthorized administrative actions.

Check if your site is affected.

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