Edoardo Ottavianelli

Security Researcher and Open Source Developer. Passionate about Computing, Nature and cooking.

Contact me


Author: Edoardo Ottavianelli

In this post I will go through CVE-2023-24769: the description, replication of the vulnerability and POC.

changedetection.io is an Open-source Python based platform notifying users about changes of public and private websites. It can be self-hosted (I have this solution installed locally on my second machine, a lightweight laptop) or it's possible to let them host your website change monitor solution paying a monthly subscription (link to the GitHub repo). From the GitHub description we can read:
"The best and simplest self-hosted free open source website change detection, monitor and notification service. Restock Monitor, change detection. Designed for simplicity - the main goal is to simply monitor which websites had a text change for free. Free Open source web page change detection, Restock Monitoring, Visualping and Apify alternative.".

Honestly I have to admit it's really a fantastic product, I have it installed locally and it's just amazing. All the promises are kept: it's simple, fast, intuitive and effective.
  • It supports 85 different notification systems (I use my Telegram bot)
  • It's possible to use a headless browser and monitor visual changes (instead of pure text)
  • It's possible to select specific changes to be monitored (through regular expressions)
  • It's possible to import multiple URLs as a list
  • Open source, fast and effective support (my security issue fixed and closed in less than a day)
  • Many more pros
changedetection cve

Description of the vulnerability

When adding a new URL to monitor, it's possible to add a URL having the protocol javascript, this leads to a Cross Site Scripting vulnerability. Even if partially blocked by modern browsers (I'm using Chrome v110.*..), the attack is still possible if the victim uses CTRL + click to open the link.
The payload used to prove the vulnerability is javascript:alert(document.domain). As suggested by changedectection.io maintainer (@dgtlmoon), the best solution was to block the URLs with protocols not in this list: HTTP, HTTPS, FTP, FILE. These are the only protocols allowed. Note that file:// protocol is not used anymore because it can leads to security vulnerabilities as well (file:///etc/passwd easy peasy).
I've opened an issue in GitHub issue tracker (https://github.com/dgtlmoon/changedetection.io/issues/1358) and after few hours the maintainer provided a patch (https://github.com/dgtlmoon/changedetection.io/pull/1359).

This attack can be carried out also using the Import feature:
Note that as stated in the GitHub issue, there wasn't a single way to exploit the vulnerability: an attacker could
  • Deploy a changedetection.io instance locally
  • Create a vulnerable watch with the payload specified above
  • Click on share the watch and get a link like this: https://changedetection.io/share/LpbICKx5Rbca
  • Use that link for phishing purposes

This is the code patching the vuln:

# Allowable protocols, protects against javascript: etc
# file:// is further checked by ALLOW_FILE_URI

def is_safe_url(test_url):
    # See https://github.com/dgtlmoon/changedetection.io/issues/1358
    # Remove 'source:' prefix so we dont get 'source:javascript:' etc
    # 'source:' is a valid way to tell us to return the source
    r = re.compile(re.escape('source:'), re.IGNORECASE)
    test_url = r.sub('', test_url)
    pattern = re.compile(os.getenv('SAFE_PROTOCOL_REGEX', SAFE_PROTOCOL_REGEX), re.IGNORECASE)
    if not pattern.match(test_url.strip()):
        return False
    return True
With this patch the problem is now fixed.

Replication of the vulnerability

  • Go to the main page
  • Under Add a new change detection watch add as URL javascript:alert(document.domain)
  • Click Watch
  • A new row is added under the websites watched
  • Click CTRL + click with mouse on the link taking to a new tab
  • Javascript payload is executed
changedetection cve poc


See the Youtube Video POC at the top of the page.