From 1a34209bb026f0bfb8a18abeb907f6aa7c937877 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Mon, 1 Jun 2026 14:26:46 +0200 Subject: [PATCH] fix(06.2): CR-06 RFC 5987-encode Content-Disposition filename to prevent header injection --- backend/api/documents.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/api/documents.py b/backend/api/documents.py index 97ed572..907c648 100644 --- a/backend/api/documents.py +++ b/backend/api/documents.py @@ -21,6 +21,7 @@ to all handlers. The doc.user_id=None guard in /confirm is a Wave 2 placeholder. """ from __future__ import annotations +import urllib.parse import uuid from pathlib import Path from typing import Optional @@ -786,9 +787,10 @@ async def stream_document_content( ) from exc file_size = len(file_bytes) + safe_name = urllib.parse.quote(doc.filename, safe='') headers = { "content-type": doc.content_type, - "content-disposition": f'inline; filename="{doc.filename}"', + "content-disposition": f"inline; filename*=UTF-8''{safe_name}", "accept-ranges": "bytes", "content-length": str(file_size), }