{"id":"CVE-2026-25527","aliases":["GHSA-9jj8-v89v-xjvw","PYSEC-2026-2124"],"url":"https://o3.security/vulnerability/CVE-2026-25527","summary":"changedetection.io vulnerable to unauthenticated static path traversal","details":"## Summary\nThe `/static/<group>/<filename>` route accepts `group=\"..\"`, which causes `send_from_directory(\"static/..\", filename)` to execute. This moves the base directory up to `/app/changedetectionio`, enabling **unauthenticated local file read** of application source files (e.g., `flask_app.py`). Severity is **low information disclosure (C:L)**.\n\n### Details\nThe vulnerable code is in `changedetectionio/flask_app.py` inside `static_content()`:\n\n```\ngroup = re.sub(r'[^\\w.-]+', '', group.lower())\nfilename = re.sub(r'[^\\w.-]+', '', filename.lower())\n...\nreturn send_from_directory(f\"static/{group}\", path=filename)\n```\n\nThe `group` sanitization allows dots, so `group=\"..\"` passes validation.  \nThis results in `send_from_directory(\"static/..\", filename)`, effectively shifting the base directory to `/app/changedetectionio` and allowing reads of files in that directory.  \nThe route is unauthenticated, so **any user can retrieve source files** without logging in.\n\n> Limitation: the route only matches `/static/<group>/<filename>` and rejects slashes inside `filename`, so it cannot traverse further to arbitrary system paths like `/etc/passwd`. It is limited to files inside the application package directory.\n\n### PoC\n1) Start an instance (example: Docker on port 5050)\n```\ndocker run -d --name cdio -p 127.0.0.1:5050:5000 -v cdio-data:/datastore cdio-local\n```\n\n2) Reproduce  \n**(URL-encoded traversal)**\n```\ncurl -i http://127.0.0.1:5050/static/%2e%2e/flask_app.py\n```\n\n**(curl path passthrough)**\n```\ncurl --path-as-is -i http://127.0.0.1:5050/static/../flask_app.py\n```\n\n3) Observe that the response body contains Python source code from `flask_app.py`.\n\n### Impact\n- **Vulnerability type:** Directory Traversal / Local File Read\n- **Affected users:** Anyone with network access (no authentication required)\n- **Scope:** Source files under `/app/changedetectionio`\n- **Security impact:** Internal logic exposure can aid further exploitation (Confidentiality: Low)","published":"2026-02-19T14:18:18.933Z","modified":"2026-08-12T03:51:12.438521827Z","cvss":{"score":5.3,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N"},"epss":{"score":0.0092,"percentile":0.586,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"changedetection-io","fixedVersion":"0.53.2"}],"fix":{"url":"https://github.com/dgtlmoon/changedetection.io/commit/9d38b4517364831889b5b0d7b3465fd060403fd4","label":"dgtlmoon/changedetection.io@9d38b45"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/25xxx/CVE-2026-25527.json"},{"type":"ADVISORY","url":"https://github.com/dgtlmoon/changedetection.io/security/advisories/GHSA-9jj8-v89v-xjvw"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-25527"},{"type":"FIX","url":"https://github.com/dgtlmoon/changedetection.io/commit/9d38b4517364831889b5b0d7b3465fd060403fd4"},{"type":"PACKAGE","url":"https://github.com/dgtlmoon/changedetection.io"},{"type":"WEB","url":"https://github.com/pypa/advisory-database/tree/main/vulns/changedetection-io/PYSEC-2026-2124.yaml"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:12.438521827Z"}}