Summary
ServeFile streams objects with a Content-Type taken from stored metadata, with no X-Content-Type-Options: nosniff and no Content-Disposition. Today this is mitigated for uploads/ because uploads are validated against an image allow-list — but the content-type stored for attachments/ objects is fully client-controlled (the presigned-POST policy sets it from body.Type with no allow-list). If the attachment-serving bug (#135) is fixed by simply allowing the attachments/ prefix, this becomes a stored-XSS vector (upload text/html or image/svg+xml, served inline, same-origin).
Severity
Medium (latent stored-XSS) — couple this fix with #135.
Affected code
api/internal/handler/upload.go:119-120 — sets Content-Type from info.ContentType and streams inline; no nosniff, no Content-Disposition.
api/internal/service/attachment.go:129 — presigned POST sets content-type from the client body.Type with no allow-list.
Suggested fix
When enabling attachments/ serving (#135): add X-Content-Type-Options: nosniff and Content-Disposition: attachment (or inline only for a strict image allow-list) on the serve response, and constrain attachment content-types server-side.
Summary
ServeFilestreams objects with aContent-Typetaken from stored metadata, with noX-Content-Type-Options: nosniffand noContent-Disposition. Today this is mitigated foruploads/because uploads are validated against an image allow-list — but the content-type stored forattachments/objects is fully client-controlled (the presigned-POST policy sets it frombody.Typewith no allow-list). If the attachment-serving bug (#135) is fixed by simply allowing theattachments/prefix, this becomes a stored-XSS vector (uploadtext/htmlorimage/svg+xml, served inline, same-origin).Severity
Medium (latent stored-XSS) — couple this fix with #135.
Affected code
api/internal/handler/upload.go:119-120— setsContent-Typefrominfo.ContentTypeand streams inline; nonosniff, noContent-Disposition.api/internal/service/attachment.go:129— presigned POST sets content-type from the clientbody.Typewith no allow-list.Suggested fix
When enabling
attachments/serving (#135): addX-Content-Type-Options: nosniffandContent-Disposition: attachment(orinlineonly for a strict image allow-list) on the serve response, and constrain attachment content-types server-side.