The vulnerability is a classic stored Cross-Site Scripting (XSS) issue. The analysis of the patch commit 3d5a544ea674cfce517adcd498877a8d760d0931 reveals the root cause. The changedetectionio/model/Watch.py file contained the vulnerable function compile_error_texts. This function is responsible for preparing error messages for display. Before the patch, it used Markup from Flask/Jinja2, which explicitly marks a string as safe for HTML rendering. This means if a user could inject content into an error message (e.g., by providing a syntactically incorrect filter), they could include malicious JavaScript. This error message would then be stored and later rendered on the watch overview page.
The patch addresses this in two key places:
- In
changedetectionio/model/Watch.py, the use of Markup within compile_error_texts is replaced by a call to a new, safer function, safe_jinja.render_fully_escaped. This new function ensures that the error content is always HTML-escaped before being returned.
- In the template
changedetectionio/blueprint/watchlist/templates/watch-overview.html, the |safe filter is removed from the call to watch.compile_error_texts. This acts as a defense-in-depth measure, ensuring that even if the function returned unsafe HTML, the template engine would escape it by default.
Therefore, the function changedetectionio.model.Watch.compile_error_texts is the primary vulnerable function, as it was responsible for processing the potentially malicious input and failing to sanitize it correctly.