Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
19 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
The /static/<group/<filename route accepts group="..", which causes sendfromdirectory("static/..", filename) to execute. This moves the base directory up to /app/changedetectionio, enabling unauthenticated local file read of application source files (e.g., flaskapp.py). Severity is low information disclosure (C:L). Details The vulnerable code is in changedetectionio/flaskapp.py inside staticcontent(): The group sanitization allows dots, so group=".." passes validation. This results in sendfromdirectory("static/..", filename), effectively shifting the base directory to /app/changedetectionio and allowing reads of files in that directory. The route is unauthenticated, so any user can retrieve source files without logging in. 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. PoC 1) Start an…
Recommended action: Upgrade to 0.53.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Details The vulnerability is caused by trusting attacker-controlled snapshot paths restored from backup files. The vulnerable flow starts in the backup restore logic. When a backup ZIP is restored, the application extracts the archive and copies each restored watch UUID directory directly into the live datastore using shutil.copytree(entry.path, dstdir). This preserves attacker-controlled files inside the restored watch directory, including history.txt. Relevant code: - changedetectionio/blueprint/backups/restore.py - changedetectionio/blueprint/backups/restore.py After restore, the application parses history.txt in the watch history property. This is the core trust-boundary issue. Relevant code: - changedetectionio/model/Watch.py - changedetectionio/model/Watch.py - changedetectionio/model/Watch.py The relevant logic is effectively: This has the following security consequence: - If the history.txt value is only a filename, it is resolved safely under self.datadir. - If the value…
Recommended action: Upgrade to 0.55.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
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): Incorrect order (13 vulnerable routes): POC 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…
Recommended action: Upgrade to 0.54.8 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
ChangeDetection.io versions prior to 0.54.7 contain a protection bypass vulnerability in the SafeXPath3Parser implementation that allows attackers to read arbitrary local files by using unblocked XPath 3.0/3.1 functions such as json-doc() and similar file-access primitives. Attackers can exploit the incomplete blocklist of dangerous XPath functions to access sensitive data from the local filesystem.
Recommended action: Upgrade to 0.54.7 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The jq: and jqraw: include filter expressions allow use of the jq env builtin, which reads all process environment variables and stores them as the watch snapshot. An authenticated user (or unauthenticated user when no password is set, the default) can leak sensitive environment variables including SALTEDPASS, PLAYWRIGHTDRIVERURL, HTTPPROXY, and any secrets passed as env vars to the container. Details Vulnerable file: changedetectionio/htmltools.py, lines 380-388 User-supplied jq filter expressions are compiled and executed without restricting dangerous jq builtins: The form validator at forms.py:670-673 only checks that the expression compiles (jq.compile(input)) — it does not block dangerous functions. The jq env builtin reads all process environment variables regardless of the input data, returning a dictionary of every env var in the server process. PoC Step 1 — Create a watch for any JSON endpoint with jqraw:env as the include filter: If no password or API key is set…
Recommended action: Upgrade to 0.54.7 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A Zip Slip vulnerability in the backup restore functionality allows arbitrary file overwrite via path traversal in uploaded ZIP archives. Details A Zip Slip vulnerability in the backup restore functionality allows arbitrary file overwrite via path traversal in uploaded ZIP archives. The application uses zipfile.extractall() without validating entry paths, allowing ../ sequences to escape the extraction directory. Vulnerable Code (lines 50-53): The extractall() function preserves the relative paths stored within the ZIP archive. When a malicious ZIP contains entries with ../ path traversal sequences, these files are extracted outside the intended directory. | Path in ZIP | Target File | Impact | | --- | --- | --- | | ../secret.txt | Flask secret key | Session forgery, auth bypass | | ../changedetection.json | App settings | Disable password, inject backdoor | | ../url-watches.json | Watch index | Inject malicious watches | | ../{uuid}/watch.json | Watch config | Modify any…
Recommended action: Upgrade to 0.54.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
- The changedetection.io application allows users to specify XPath expressions as content filters via the includefilters field. These XPath expressions are processed using the elementpath library which implements XPath 3.0/3.1 specification. - XPath 3.0 includes the unparsed-text() function which can read arbitrary files from the filesystem. The application does not validate or sanitize XPath expressions to block dangerous functions, allowing an attacker to read any file accessible to the application process. Data Flow Affected Code File: changedetectionio/htmltools.py Function: xpathfilter() Lines: 187-220 Validation (forms.py): Details - Navigate to the http://ewn9c0k01ghh7f588a7mij4y1w6iz8gb.tryneoai.com:5000/ instance - Create a new watch with any valid URL (e.g., https://example.com) - Edit the watch and set the "CSS/JSONPath/JQ/XPath Filters" field to: - Save and trigger a recheck - View the preview/snapshot - the file contents will be displayed <img width="2800"…
Recommended action: Upgrade to 0.54.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A reflected cross-site scripting (XSS) vulnerability was identified in the /rss/tag/ endpoint of changedetection.io. The taguuid path parameter is reflected directly in the HTTP response body without HTML escaping. Since Flask returns text/html by default for plain string responses, the browser parses and executes injected JavaScript. This vulnerability persists in version 0.54.1, which patched the related XSS in /rss/watch/ (CVE-2026-27645 / GHSA-mw8m-398g-h89w) but did not address the identical pattern in the tag RSS endpoint. Package - Ecosystem: pip - Package: changedetection.io - Affected versions: <= 0.54.1 - Patched versions: (none yet) Severity Moderate - CVSS 6.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N Details File: changedetectionio/blueprint/rss/tag.py Line: 36 Source: tag.py @ 1d72716 The taguuid parameter from the URL path is interpolated into the response body using an f-string with no escaping: Flask's default Content-Type for plain string responses is text/html;…
Recommended action: Upgrade to 0.54.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Changedetection.io is vulnerable to Server-Side Request Forgery (SSRF) because the URL validation function issafevalidurl() does not validate the resolved IP address of watch URLs against private, loopback, or link-local address ranges. An authenticated user (or any user when no password is configured, which is the default) can add a watch for internal network URLs such as: - http://169.254.169.254 - http://10.0.0.1/ - http://127.0.0.1/ The application fetches these URLs server-side, stores the response content, and makes it viewable through the web UI — enabling full data exfiltration from internal services. This is particularly severe because: - The fetched content is stored and viewable - this is not a blind SSRF - Watches are fetched periodically - creating a persistent SSRF that continuously accesses internal resources - By default, no password is set - the web UI is accessible without authentication - Self-hosted deployments typically run on cloud infrastructure where…
Recommended action: Upgrade to 0.54.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Three security vulnerabilities were identified in changedetection.io through source code review and live validation against a locally deployed Docker instance. All vulnerabilities were confirmed exploitable on the latest version (0.53.6) it was additionally validated at scale against 500 internet-facing instances discovered via FOFA search engine, producing 5K+ confirmed detections using a custom Nuclei template, demonstrating widespread real-world impact. The RSS single-watch endpoint reflects the UUID path parameter directly in the HTTP response body without HTML escaping. Since Flask returns text/html by default for plain string responses, the browser parses and executes injected JavaScript. Details File: changedetectionio/blueprint/rss/singlewatch.py (lines ~45 and ~50) The UUID parameter from the URL path is interpolated into the response body using an f-string with no escaping: Line ~45 Line ~50 Attack Vector The attack requires a valid RSS access token, which is a…
Recommended action: Upgrade to 0.53.7 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A Stored Cross Site Scripting is present in the changedetection.io Watch update API due to unsufficient security checks. Details Tested on changedetection.io version v0.50.24 When a user tries to add an unsafe URL as a Watch in the changedetection.io UI, the action is blocked with the error message "Watch protocol is not permitted by SAFEPROTOCOLREGEX or incorrect URL format". This is catched by the function validateurl(testurl). When instead the Watch API is used, this check is not performed resulting in unsafe URLs added as Watch. PoC Update an existing watch with an unsafe URL Impact Two scenarios are possibile: 1. An attacker can insert a new watch with an arbitrary URL which really points to a web page. Once the HTML content is retrieved, the attacker updates the URL with a JavaScript payload. 2. An attacker substitutes the URL in an existing watch with a new URL that is in reality a JavaScript payload. When the user clicks on Preview and then on the malicious link, the…
Recommended action: Upgrade to 0.50.34 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact XSS - Errors in filters from website page change detection watches were not being filtered. Patches 0.50.4
Recommended action: Upgrade to 0.50.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Improper input validation in the application can allow attackers to perform local file read (LFR) or path traversal attacks. These vulnerabilities occur when user input is used to construct file paths without adequate sanitization or validation. For example, using file:../../../etc/passwd or file: ///etc/passwd can bypass weak validations and allow unauthorized access to sensitive files. Even though this has been addressed in previous patch, it is still insufficient. Details The check in this line of code is insufficient. The attacker can still bypass this by using: -file:../../../../etc/passwd -file: ///etc/passwd (with space before /) PoC - Open up a changedetection.io instance with a webdriver configured. - Create a new watch with file:../../../../etc/passwd. - Check the watch preview. - The contents of /etc/passwd should pop out. Screenshots
Recommended action: Upgrade to 0.48.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The validation for the file URI scheme falls short, and results in an attacker being able to read any file on the system. This issue only affects instances with a webdriver enabled, and ALLOWFILEURI false or not defined. Details The check used for URL protocol, issafeurl, allows file: as a URL scheme: https://github.com/dgtlmoon/changedetection.io/blob/e0abf0b50507a8a3d0c1d8522ab23519b3e4cdf4/changedetectionio/model/Watch.py#L11-L13 It later checks if local files are permitted, but one of the preconditions for the check is that the URL starts with file://. The issue comes with the fact that the file URI scheme is not required to have double slashes. A valid file URI must therefore begin with either file:/path (no hostname), file:///path (empty hostname), or file://hostname/path. — Wikipedia https://github.com/dgtlmoon/changedetection.io/blob/e0abf0b50507a8a3d0c1d8522ab23519b3e4cdf4/changedetectionio/processors/init.py#L37-L41 PoC 1. Open up a changedetection.io instance with…
Recommended action: Upgrade to 0.47.6 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
When a WebDriver is used to fetch files source:file:///etc/passwd can be used to retrieve local system files, where the more traditional file:///etc/passwd gets blocked Details The root cause is the payload source:file:///etc/passwdpasses the regex here and also passes the check here where a traditional file:///etc/passwd would get blocked PoC CL-ChangeDetection.io Path Travsersal-311024-181039.pdf Impact It depends on where the webdriver is deployed but generally this is a high impact vulnerability
Recommended action: Upgrade to 0.47.5 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
A Server Side Template Injection in changedetection.io caused by usage of unsafe functions of Jinja2 allows Remote Command Execution on the server host. Details changedetection.io version: 0.45.20 ``` docker images REPOSITORY TAG IMAGE ID CREATED SIZE dgtlmoon/changedetection.io latest 53529c2e69f1 44 hours ago 423MB ``` The vulnerability is caused by the usage of vulnerable functions of Jinja2 template engine. ```python from jinja2 import Environment, BaseLoader ... Get the notification body from datastore jinja2_env = Environment(loader=BaseLoader) n_body = jinja2_env.from_string(n_object.get('notification_body', '')).render(notification_parameters) n_title = jinja2_env.from_string(n_object.get('notification_title', '')).render(notification_parameters) ``` PoC 1. Create/Edit a URL watch item 2. Under *Notifications* tab insert this payload: ```python {{ self.init.globals.builtins.import('os').popen('id').read() }} ``` !Screenshot from…
Recommended action: Upgrade to 0.45.21 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Input in parameter notificationurls is not processed resulting in javascript execution in the application Details changedetection.io version: v0.45.21 https://github.com/dgtlmoon/changedetection.io/blob/0.45.21/changedetectionio/forms.py#L226 PoC Setting ADD Notification URL List Requests Impact A reflected XSS vulnerability happens when the user input from a URL or POST data is reflected on the page without being stored, thus allowing the attacker to inject malicious content
Recommended action: Upgrade to 0.45.22 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
API endpoint /api/v1/watch/<uuid/history can be accessed by any unauthorized user. Details WatchHistory resource does not have @auth.checktoken annotation, which means it can be accessed without providing x-api-key header. https://github.com/dgtlmoon/changedetection.io/blob/9510345e01ea8e308c339163d8e8b030ce5ac7f1/changedetectionio/api/apiv1.py#L129-L156 PoC 1. Get list of watch with x-api-key: 2. Call for history of snapshots without x-api-key. Expected - 401/403 error. Actual - list of snapshots is listed. Impact Anybody can check one's watch history. However, because unauthorized party first needs to know watch UUID, and the watch history endpoint itself returns only paths to the snapshot on the server, an impact on users' data privacy is minimal.
Recommended action: Upgrade to 0.45.13 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Changedetection.io before 0.40.2 was discovered to contain a stored cross-site scripting (XSS) vulnerability in the main page. This vulnerability allows attackers to execute arbitrary web scripts or HTML via a crafted payload injected into the URL parameter under the "Add a new change detection watch" function.
Recommended action: Upgrade to 0.40.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.