Skip to content

[SECURITY] ServeFile sets no nosniff/Content-Disposition and serves client-controlled content-type (stored-XSS risk) #161

Description

@martian56

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.

Metadata

Metadata

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions