From 135e0d2dc729a136b5ae1b3efdb089ad5b5c070c Mon Sep 17 00:00:00 2001 From: fen Date: Fri, 16 Oct 2026 16:52:29 -0500 Subject: [PATCH] Reject malformed multipart burn_after_reads with 400 handleCreatePasteMultipart silently dropped non-numeric burn_after_reads values (err == nil guard), so burn_after_reads=abc created a 201 paste with NO burn budget. Now returns 400 with the error+code shape ({'code':'burn_invalid'}) matching the JSON path, where an invalid value fails unmarshal into the int field. An empty value stays 'unset' like the JSON path's omitempty. Verified live: burn_after_reads=abc -> 400 burn_invalid; =2 -> 201. --- internal/api/attachments.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/internal/api/attachments.go b/internal/api/attachments.go index 862f544..6bdb31b 100644 --- a/internal/api/attachments.go +++ b/internal/api/attachments.go @@ -186,9 +186,18 @@ func (a *apiServer) handleCreatePasteMultipart(w http.ResponseWriter, r *http.Re case "burn_after_read": p.BurnAfterRead = v == "true" || v == "1" || v == "on" case "burn_after_reads": - if n, err := strconv.Atoi(v); err == nil { - p.BurnAfterReads = &n + if v == "" { // absent value: unset, like the JSON path's omitempty + continue } + n, err := strconv.Atoi(v) + if err != nil { + // malformed burn_after_reads is a 400, not a silently-dropped + // budget: same 400-with-code shape the JSON path uses for + // invalid values (which fail unmarshal into the int field). + writeErrCode(w, 400, "burn_invalid", "burn_after_reads must be a positive number") + return + } + p.BurnAfterReads = &n } }