GitHub Advisoryadvisory · PyPI
GHSA-8whx-v8qq-pq64 changedetection.io has Reflected XSS in its RSS Tag Error Response
MEDIUM
Official page ↗
- Aliases
- CVE-2026-29038
- Ecosystem
- PyPI
- Packages
- changedetection.io
- Severity
- Moderate
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Weaknesses
- CWE-79
- Reviewed
- 2026-03-04
Affected packages
• PyPI changedetection.io: < 0.54.4 → fixed in 0.54.4
Description
A reflected cross-site scripting (XSS) vulnerability was identified in the `/rss/tag/` endpoint of changedetection.io. The `tag_uuid` 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: ` HTML tag on the homepage without authentication:
1. Attacker visits the target's homepage (if unauthenticated) and extracts the RSS token from the `` tag
2. Crafts a malicious URL:
```
http://target:5000/rss/tag/?token=EXTRACTED_TOKEN
```
3. Sends the link to a victim who has an active session on the changedetection.io instance
4. When the victim clicks the link, the server responds with:
```
Tag with UUID not found
```
5. The browser renders the `` tag, the `onerror` fires, and JavaScript executes in the victim's session context
Proof of Concept
Request
```http
GET /rss/tag/%3Cimg%20src%3Dx%20onerror%3Dalert(document.domain)%3E?token=60b83b06df98b24c66367bc3d233105b HTTP/1.1
Host: localhost:5000
```
Response
```http
HTTP/1.1 404 NOT FOUND
Content-Type: text/html; charset=utf-8
Tag with UUID not found
```
The XSS payload is reflected unescaped in an HTML response. The browser executes `alert(document.domain)` and displays "localhost", confirming JavaScript execution.
Tested on: changedetection.io v0.54.1 (Docker, localhost, Feb 25, 2026)
https://github.com/user-attachments/assets/6db07f6a-6df8-48a7-a597-9f39dfa1bb29
Impact
• Session cookie theft via `document.cookie` exfiltration
• Account takeover if session cookies lack the `HttpOnly` flag
• Phishing via crafted links that appear to originate from a trusted changedetection.io instance
• Low exploitation barrier - the RSS token is obtainable without authentication from the homepage `` tag
• Widespread exposure - prior scanning of internet-facing instances (during CVE-2026-27645 research) identified 500+ publicly accessible deployments
Suggested Fix
Escape the `tag_uuid` parameter before reflecting it in the response, or set the `Content-Type` to `text/plain`:
Option A: HTML Escape (Recommended)
```python
from markupsafe import escape
if not tag:
return f"Tag with UUID {escape(tag_uuid)} not found", 404
```
Option B: Set Content-Type to text/plain
```python
from flask import make_response
if not tag:
resp = make_response(f"Tag with UUID {tag_uuid} not found", 404)
resp.headers['Content-Type'] = 'text/plain; charset=utf-8'
return resp
```
Credits
• Roberto Nunes (@Akokonunes) - Reporter
• neo-ai-engineer (@neo-ai-engineer) - Reporter
References
• Related advisory: GHSA-mw8m-398g-h89w (CVE-2026-27645)
• Vulnerable source: tag.py @ 1d72716
Related
Alias · CVE (1)
- CVE-2026-29038 changedetection.io is a free open source web page change detection tool. vulnerability
Weakness · CWE (1)
- CWE-79 Improper Neutralization of Input During Web Page Generation weakness
References
- https://github.com/dgtlmoon/changedetection.io/security/advisories/GHSA-8whx-v8qq-pq64 web
- https://github.com/dgtlmoon/changedetection.io/security/advisories/GHSA-mw8m-398g-h89w web
- https://nvd.nist.gov/vuln/detail/CVE-2026-29038 advisory
- https://github.com/dgtlmoon/changedetection.io/commit/ec7d56f85d1e9690fca7cb4711c1fb20dffec780 web
- https://github.com/dgtlmoon/changedetection.io package
- https://github.com/dgtlmoon/changedetection.io/releases/tag/0.54.4 web