From 8474b8eb02b9dd8cafb2f2b51c4eadc96927b536 Mon Sep 17 00:00:00 2001 From: fen Date: Thu, 17 Sep 2026 14:15:05 -0500 Subject: [PATCH] Cap attachment filenames at 128 chars server-side A 250-char multipart filename was accepted and echoed verbatim in Content-Disposition. SanitizeFilename already truncates; lower the cap from 255 to 128 so DB rows and header echoes stay bounded (#248). --- internal/store/attachment.go | 5 ++++- internal/store/blob_test.go | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/store/attachment.go b/internal/store/attachment.go index a944cb3..70981ab 100644 --- a/internal/store/attachment.go +++ b/internal/store/attachment.go @@ -26,7 +26,10 @@ type Attachment struct { SizeHuman string `json:"-"` // template-only: human-readable size } -const MaxFilenameLen = 255 +// MaxFilenameLen caps stored attachment filenames (bytes) to bound DB +// rows and Content-Disposition echoes. 128 keeps names readable while +// stopping filename-bloat abuse; longer names truncate. +const MaxFilenameLen = 128 // ErrFileTooLarge is returned when an attachment exceeds the per-file cap. var ErrFileTooLarge = errors.New("file too large") diff --git a/internal/store/blob_test.go b/internal/store/blob_test.go index 70a20c8..1eba5a7 100644 --- a/internal/store/blob_test.go +++ b/internal/store/blob_test.go @@ -105,4 +105,9 @@ func TestSanitizeFilename(t *testing.T) { if got := SanitizeFilename(long); len(got) != MaxFilenameLen { t.Errorf("long name len = %d want %d", len(got), MaxFilenameLen) } + // issue #248: a 250-char multipart filename must truncate to the cap + repro := strings.Repeat("b", 246) + ".txt" + if got := SanitizeFilename(repro); len(got) != MaxFilenameLen { + t.Errorf("repro name len = %d want %d", len(got), MaxFilenameLen) + } } -- 2.54.0