A high-severity SSRF vulnerability (CVSS 8.6) was disclosed on February 25, 2026 in changedetection.io, a popular open-source tool for monitoring web page changes. The bug is a textbook example of a failed allowlist/denylist approach to URL validation — and the default unauthenticated configuration makes it exploitable by anyone with network access to the instance.
What is changedetection.io?#
changedetection.io is a self-hosted service that watches URLs for content changes and alerts you when something changes. It’s commonly used by developers, researchers, and sysadmins to monitor pages, APIs, and dashboards. The tool fetches URLs on your behalf — which is exactly the trust relationship SSRF attacks exploit.
The Vulnerability#
The root cause lives in the is_safe_valid_url() function. Before versions prior to 0.54.1, the function validated the syntax of submitted watch URLs but did not resolve the hostname to its actual IP address and check whether that IP fell within private, loopback, or link-local ranges:
127.0.0.0/8— loopback10.0.0.0/8,172.16.0.0/12,192.168.0.0/16— RFC 1918 private ranges169.254.0.0/16— link-local (notably: AWS/GCP/Azure instance metadata)
In practical terms, the application would accept a URL like http://169.254.169.254/latest/meta-data/ or http://internal-service.corp/api/secrets, fetch it server-side, and surface the response in the change-detection UI.
Attack Scenario#
- An attacker navigates to a changedetection.io instance (no credentials needed on a default install — password protection is opt-in).
- They add a new “watch” entry with a URL pointing at an internal resource: e.g., the AWS instance metadata endpoint at
http://169.254.169.254/latest/meta-data/iam/security-credentials/. - changedetection.io dutifully fetches the URL from the server’s network context and stores the response.
- The attacker views the change history and reads the exfiltrated content — including IAM credential material.
On AWS, a successful hit on the metadata service can return temporary AccessKeyId, SecretAccessKey, and Token values for the instance’s IAM role, enabling full cloud account pivot depending on what permissions that role carries.
Why Default Installs Are Especially Exposed#
The changedetection.io documentation notes that password protection must be explicitly enabled. Many self-hosted deployments — particularly homelab and small-team setups — run with no authentication. This collapses the attacker’s requirement from “authenticated user” to “anyone who can reach the port,” which for cloud-hosted instances often means the public internet.
Remediation#
Upgrade to changedetection.io 0.54.1 or later. The fix adds IP resolution and range-checking to is_safe_valid_url() so that URLs resolving to private or loopback addresses are rejected before a fetch is attempted.
If you can’t upgrade immediately:
- Enable password protection.
- Restrict access to the instance at the network level (firewall, VPN, reverse proxy auth).
- If running on AWS/GCP/Azure, consider blocking instance metadata access from the container via IMDSv2 enforcement or network policy (though this is a mitigation for the consequence, not the vulnerability itself).
The Broader Pattern#
This bug follows a pattern that shows up constantly in SSRF disclosures: validating the string representation of a URL without resolving and checking the actual destination IP. DNS can be your enemy here — an attacker can register a domain that resolves to 127.0.0.1 (DNS rebinding is a related variant), or simply submit a bare IP that passes a regex check but falls in a private range.
The reliable fix is to:
- Resolve the hostname to an IP address at validation time.
- Check that IP against a denylist of private/loopback/link-local ranges (or better, an allowlist of expected destinations).
- Re-resolve (or pin the IP) at fetch time to prevent DNS rebinding between validation and request.
changedetection.io’s 0.54.1 fix addresses steps 1 and 2. Step 3 (TOCTOU between DNS resolution and the actual fetch) is the harder problem that most URL validators leave unaddressed.
If you’re auditing your own applications for similar issues, look for any code path that accepts a user-supplied URL and fetches it server-side — file imports, webhooks, preview generators, favicon fetchers, and change monitors are all common culprits.
Sources: