VYPR
High severity8.6NVD Advisory· Published Dec 27, 2024· Updated Apr 15, 2026

CVE-2024-56509

CVE-2024-56509

Description

changedetection.io is a free open source web page change detection, website watcher, restock monitor and notification service. 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. This vulnerability is fixed in 0.48.05.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
changedetection.ioPyPI
< 0.48.050.48.05

Patches

3
4419bc0e61d0

Fixing test for CVE-2024-56509 (#2864)

1 file changed · +15 8
  • changedetectionio/tests/test_security.py+15 8 modified
    @@ -69,22 +69,29 @@ def _runner_test_various_file_slash(client, file_uri):
         wait_for_all_checks(client)
         res = client.get(url_for("index"))
     
    +    substrings = [b"URLs with hostname components are not permitted", b"No connection adapters were found for"]
    +
    +
         # If it is enabled at test time
         if strtobool(os.getenv('ALLOW_FILE_URI', 'false')):
    -        # So it should permit it, but it should fall back to the 'requests' library giving an error
    -        # (but means it gets passed to playwright etc)
    -        assert b"URLs with hostname components are not permitted" in res.data
    -        assert b"_runner_test_various_file_slash" in res.data # Can read this file OK
    -    else:
    -        # Default should be here
    -        assert b'file:// type access is denied for security reasons.' in res.data
    +        if file_uri.startswith('file:///'):
    +            # This one should be the full qualified path to the file and should get the contents of this file
    +            res = client.get(
    +                url_for("preview_page", uuid="first"),
    +                follow_redirects=True
    +            )
    +            assert b'_runner_test_various_file_slash' in res.data
    +        else:
    +            # This will give some error from requests or if it went to chrome, will give some other error :-)
    +            assert any(s in res.data for s in substrings)
     
         res = client.get(url_for("form_delete", uuid="all"), follow_redirects=True)
         assert b'Deleted' in res.data
     
     def test_file_slash_access(client, live_server, measure_memory_usage):
         #live_server_setup(live_server)
    -    # file: is permitted by default, but it will be caught by ALLOW_FILE_URI
    +
    +    # file: is NOT permitted by default, so it will be caught by ALLOW_FILE_URI check
     
         test_file_path = os.path.abspath(__file__)
         _runner_test_various_file_slash(client, file_uri=f"file://{test_file_path}")
    
f7e9846c9b40

CVE-2024-56509 - Stricter file protocol checking pre-check ( Improper Input Validation Leading to LFR/Path Traversal when fetching file:.. )

2 files changed · +16 35
  • changedetectionio/processors/__init__.py+2 2 modified
    @@ -33,8 +33,8 @@ def call_browser(self, preferred_proxy_id=None):
     
             url = self.watch.link
     
    -        # Protect against file://, file:/ access, check the real "link" without any meta "source:" etc prepended.
    -        if re.search(r'^file:/', url.strip(), re.IGNORECASE):
    +        # Protect against file:, file:/, file:// access, check the real "link" without any meta "source:" etc prepended.
    +        if re.search(r'^file:', url.strip(), re.IGNORECASE):
                 if not strtobool(os.getenv('ALLOW_FILE_URI', 'false')):
                     raise Exception(
                         "file:// type access is denied for security reasons."
    
  • changedetectionio/tests/test_security.py+14 33 modified
    @@ -1,9 +1,7 @@
     import os
     
     from flask import url_for
    -from .util import set_original_response, set_modified_response, live_server_setup, wait_for_all_checks
    -import time
    -
    +from .util import live_server_setup, wait_for_all_checks
     from .. import strtobool
     
     
    @@ -61,54 +59,37 @@ def test_bad_access(client, live_server, measure_memory_usage):
         assert b'Watch protocol is not permitted by SAFE_PROTOCOL_REGEX' in res.data
     
     
    -def test_file_slashslash_access(client, live_server, measure_memory_usage):
    -    #live_server_setup(live_server)
    -
    -    test_file_path = os.path.abspath(__file__)
    +def _runner_test_various_file_slash(client, file_uri):
     
    -    # file:// is permitted by default, but it will be caught by ALLOW_FILE_URI
         client.post(
             url_for("form_quick_watch_add"),
    -        data={"url": f"file://{test_file_path}", "tags": ''},
    +        data={"url": file_uri, "tags": ''},
             follow_redirects=True
         )
         wait_for_all_checks(client)
         res = client.get(url_for("index"))
     
         # If it is enabled at test time
         if strtobool(os.getenv('ALLOW_FILE_URI', 'false')):
    -        res = client.get(
    -            url_for("preview_page", uuid="first"),
    -            follow_redirects=True
    -        )
    -
    -        assert b"test_file_slashslash_access" in res.data
    +        # So it should permit it, but it should fall back to the 'requests' library giving an error
    +        # (but means it gets passed to playwright etc)
    +        assert b"URLs with hostname components are not permitted" in res.data
    +        assert b"_runner_test_various_file_slash" in res.data # Can read this file OK
         else:
             # Default should be here
             assert b'file:// type access is denied for security reasons.' in res.data
     
    +    res = client.get(url_for("form_delete", uuid="all"), follow_redirects=True)
    +    assert b'Deleted' in res.data
    +
     def test_file_slash_access(client, live_server, measure_memory_usage):
         #live_server_setup(live_server)
    +    # file: is permitted by default, but it will be caught by ALLOW_FILE_URI
     
         test_file_path = os.path.abspath(__file__)
    -
    -    # file:// is permitted by default, but it will be caught by ALLOW_FILE_URI
    -    client.post(
    -        url_for("form_quick_watch_add"),
    -        data={"url": f"file:/{test_file_path}", "tags": ''},
    -        follow_redirects=True
    -    )
    -    wait_for_all_checks(client)
    -    res = client.get(url_for("index"))
    -
    -    # If it is enabled at test time
    -    if strtobool(os.getenv('ALLOW_FILE_URI', 'false')):
    -        # So it should permit it, but it should fall back to the 'requests' library giving an error
    -        # (but means it gets passed to playwright etc)
    -        assert b"URLs with hostname components are not permitted" in res.data
    -    else:
    -        # Default should be here
    -        assert b'file:// type access is denied for security reasons.' in res.data
    +    _runner_test_various_file_slash(client, file_uri=f"file://{test_file_path}")
    +    _runner_test_various_file_slash(client, file_uri=f"file:/{test_file_path}")
    +    _runner_test_various_file_slash(client, file_uri=f"file:{test_file_path}") # CVE-2024-56509
     
     def test_xss(client, live_server, measure_memory_usage):
         #live_server_setup(live_server)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.