fix(api,frontend): isolate active share files and allowlist link schemes
This commit is contained in:
@@ -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
|
||||
),
|
||||
|
||||
@@ -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('"', "_")
|
||||
|
||||
Reference in New Issue
Block a user