Private
Public Access
Play video attachments inline, with an expand option (#65)
A video file previously rendered as a generic downloadable file card, same as any other attachment. The file-serve endpoint forces Content-Disposition: attachment for every upload as an XSS mitigation (a same-origin-served .html/.svg executing script), which also meant a <video> tag pointed at it couldn't play -- the browser would just try to download it. Carve out a strict, server-side allowlist (video/mp4, video/webm, video/ogg -- deliberately not "every video/* type") that skips the forced download, the same reasoning MessageImage's own endpoint already relies on: these are content types a browser only ever interprets as media, never as something that could execute script. Anything else, including other video formats like .mov, still forces a download exactly as before. On the frontend, a video attachment with one of those content types renders as an inline <video controls> instead of the generic file card, with a hover-revealed expand button that calls the browser's native Fullscreen API on the video element directly rather than building a second lightbox component. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,19 @@ ALLOWED_IMAGE_CONTENT_TYPES: dict[str, tuple[str, str]] = {
|
||||
"image/webp": (".webp", "WEBP"),
|
||||
}
|
||||
|
||||
# #65: browser-natively-playable video formats -- used to decide whether a
|
||||
# stored MessageFile gets served inline (a <video> tag can actually play
|
||||
# it) or forced to download like every other non-image attachment (see
|
||||
# rooms.py's file-serve endpoint). Deliberately a strict allowlist, not
|
||||
# "every video/* type": .mov (video/quicktime) has spotty <video> support
|
||||
# outside Safari, and more importantly this is the one thing standing
|
||||
# between "serve with the browser trusting our declared Content-Type" and
|
||||
# reopening the same-origin-script-execution risk Content-Disposition:
|
||||
# attachment exists to close off for arbitrary uploads -- it must only
|
||||
# ever contain types a <video> tag renders as media, never as something
|
||||
# that could execute script.
|
||||
INLINE_SAFE_VIDEO_CONTENT_TYPES = frozenset({"video/mp4", "video/webm", "video/ogg"})
|
||||
|
||||
|
||||
class UploadTooLargeError(Exception):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user