fix(api,frontend): isolate active share files and allowlist link schemes

This commit is contained in:
hh
2026-08-29 12:52:54 +02:00
parent 0399145791
commit c832513e5c
10 changed files with 75 additions and 16 deletions
+8 -1
View File
@@ -9,6 +9,7 @@ from fastapi.responses import FileResponse, PlainTextResponse
from utils.files import (
content_disposition,
counts_as_download,
is_active_mime,
is_inline_mime,
resolve_mime,
)
@@ -20,7 +21,12 @@ router = APIRouter(tags=["files"], route_class=DishkaRoute)
_GONE = "This link is no longer available.\n"
_MISSING = "Not found.\n"
_NO_STORE = {"Cache-Control": "private, no-store", "X-Robots-Tag": "noindex, nofollow"}
_NO_STORE = {
"Cache-Control": "private, no-store",
"X-Robots-Tag": "noindex, nofollow",
"X-Content-Type-Options": "nosniff",
}
_SANDBOX = {"Content-Security-Policy": "sandbox"}
def _client_ip(request: Request) -> str | None:
@@ -76,6 +82,7 @@ async def _serve(
media_type=mime,
headers={
**_NO_STORE,
**(_SANDBOX if is_active_mime(mime) else {}),
"Content-Disposition": content_disposition(
row["file_name"], attachment=attachment
),
+11
View File
@@ -67,6 +67,13 @@ _GENERIC_MIMES = {
_INLINE_MIME_PREFIXES = ("image/", "video/", "audio/", "text/")
_INLINE_MIMES = {"application/pdf", "application/json"}
_ACTIVE_MIMES = {
"text/html",
"application/xhtml+xml",
"image/svg+xml",
"text/xml",
"application/xml",
}
_PREVIEW_AGENTS = (
"telegrambot",
@@ -202,6 +209,10 @@ def is_inline_mime(mime: str | None) -> bool:
return mime in _INLINE_MIMES or mime.startswith(_INLINE_MIME_PREFIXES)
def is_active_mime(mime: str | None) -> bool:
return bool(mime) and mime.split(";", 1)[0].strip().lower() in _ACTIVE_MIMES
def content_disposition(file_name: str, *, attachment: bool) -> str:
kind = "attachment" if attachment else "inline"
ascii_name = file_name.encode("ascii", "replace").decode("ascii").replace('"', "_")