Harden security controls from REPORT findings
This commit is contained in:
@@ -14,7 +14,7 @@ from fastapi.responses import FileResponse, Response, StreamingResponse
|
||||
from sqlalchemy import or_, func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.config import get_settings
|
||||
from app.core.config import get_settings, is_inline_preview_mime_type_safe
|
||||
from app.db.base import get_session
|
||||
from app.models.document import Document, DocumentStatus
|
||||
from app.schemas.documents import (
|
||||
@@ -448,14 +448,22 @@ def download_document(document_id: UUID, session: Session = Depends(get_session)
|
||||
|
||||
@router.get("/{document_id}/preview")
|
||||
def preview_document(document_id: UUID, session: Session = Depends(get_session)) -> FileResponse:
|
||||
"""Streams the original document inline when browser rendering is supported."""
|
||||
"""Streams trusted-safe MIME types inline and forces attachment for active script-capable types."""
|
||||
|
||||
document = session.execute(select(Document).where(Document.id == document_id)).scalar_one_or_none()
|
||||
if document is None:
|
||||
raise HTTPException(status_code=404, detail="Document not found")
|
||||
|
||||
original_path = absolute_path(document.stored_relative_path)
|
||||
return FileResponse(path=original_path, media_type=document.mime_type)
|
||||
common_headers = {"X-Content-Type-Options": "nosniff"}
|
||||
if not is_inline_preview_mime_type_safe(document.mime_type):
|
||||
return FileResponse(
|
||||
path=original_path,
|
||||
filename=document.original_filename,
|
||||
media_type="application/octet-stream",
|
||||
headers=common_headers,
|
||||
)
|
||||
return FileResponse(path=original_path, media_type=document.mime_type, headers=common_headers)
|
||||
|
||||
|
||||
@router.get("/{document_id}/thumbnail")
|
||||
|
||||
Reference in New Issue
Block a user