From 56ec411cae34fab734e0db1f1f60f13803f40af3 Mon Sep 17 00:00:00 2001 From: Deluan Date: Mon, 7 Sep 2026 21:00:32 -0400 Subject: [PATCH] fix(jellyfin): return 400 for an avatar body that is not a decodable image The native endpoint answers 400 for the same input; only SetAvatar's resize was catching it here, which surfaced as 500. --- server/jellyfin/user_image.go | 7 +++++++ server/jellyfin/user_image_test.go | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/server/jellyfin/user_image.go b/server/jellyfin/user_image.go index 317082024..e4cbc43ba 100644 --- a/server/jellyfin/user_image.go +++ b/server/jellyfin/user_image.go @@ -2,6 +2,7 @@ package jellyfin import ( "bytes" + "image" "io" "net/http" "strings" @@ -140,6 +141,12 @@ func (api *Router) postUserImage(w http.ResponseWriter, r *http.Request) { return } + if _, _, err := image.DecodeConfig(bytes.NewReader(imgBytes)); err != nil { + log.Warn(ctx, "Jellyfin API: avatar upload rejected: not a valid image", "user", usr.UserName, err) + http.Error(w, "invalid image file", http.StatusBadRequest) + return + } + filename, err := api.imgUpload.SetAvatar(ctx, usr.ID, usr.UserName, usr.UploadedImagePath(), bytes.NewReader(imgBytes), ext) if err != nil { log.Error(ctx, "Jellyfin API: could not save avatar", "user", usr.UserName, err) diff --git a/server/jellyfin/user_image_test.go b/server/jellyfin/user_image_test.go index 816551d49..b2b8db5aa 100644 --- a/server/jellyfin/user_image_test.go +++ b/server/jellyfin/user_image_test.go @@ -202,6 +202,18 @@ var _ = Describe("POST /userimage and DELETE /userimage", func() { Expect(usr.UploadedImage).To(BeEmpty()) }) + It("rejects a body that is not a decodable image with 400", func() { + body := base64.StdEncoding.EncodeToString([]byte("this is not an image")) + r := authenticatedRequestWithBody("POST", "/userimage", strings.NewReader(body)) + r.Header.Set("Content-Type", "image/png") + w := httptest.NewRecorder() + router.ServeHTTP(w, r) + Expect(w.Code).To(Equal(http.StatusBadRequest)) + + usr, _ := ds.User(context.Background()).Get("u1") + Expect(usr.UploadedImage).To(BeEmpty()) + }) + It("rejects an unknown content type", func() { r := authenticatedRequestWithBody("POST", "/userimage", strings.NewReader("x")) r.Header.Set("Content-Type", "text/plain")