KamoCRM

Imaging proxy forces a download for anything that isn't a safe raster or a stream

FixMediaService
Shipped
September 23, 2026 at 10:10 AM UTC
Author
Kamo
Commit
d8971bc

GET/HEAD **************** always answered with the client-declared Content-Type from upload, no Content-Disposition, no X-Content-Type-Options and no CSP. ChatAttachmentService's upload allow-list admits image/* including image/svg+xml, and an SVG document can carry a <script> - so an attachment stored as image/svg+xml and opened by URL ran as the response's own document, on kamo-internal's host where the *** cookie is httpOnly:false (prod already held three SVG chat attachments). The chat bubble's own <img> already refuses to inline SVG **************** so this was only reachable by opening the attachment's URL directly, not through the normal chat view - but the URL is exactly what a "download"/"open" affordance on a non-image attachment chip has to link to. The endpoint now always sends X-Content-Type-Options: nosniff and a restrictive Content-Security-Policy (default-src 'none'; sandbox; ...), and adds Content-Disposition: attachment for anything outside a small allow-list of raster image types plus audio/* and video/* (which Range-stream through this same endpoint and must stay inline to keep playing). Nothing in the allow-list changed - SVG, PDF and any other document-shaped upload still succeed, they just can no longer render as a page when someone opens the attachment's URL. kamo-internal's own relay of this route **************** only forwards **************** so it currently strips these new headers back out before they reach a browser - flagged for the coordinator to fix on that side; this commit is the mediaservice half. Covered by ImagingProxyContentSecurityTest (mutation-checked: reverting the new header block turns all four assertions red).

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing