From 4da4bf69ca404132763bb5142e084191f91153b6 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 15 Jul 2025 13:21:48 +0200 Subject: [PATCH] fix(background): validate unsupported formats and show error message (#1123) --- pkg/modules/background/handler/background.go | 27 +++++++++++++ pkg/modules/background/handler/errors.go | 42 ++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 pkg/modules/background/handler/errors.go diff --git a/pkg/modules/background/handler/background.go b/pkg/modules/background/handler/background.go index acf3cbf88..c89253474 100644 --- a/pkg/modules/background/handler/background.go +++ b/pkg/modules/background/handler/background.go @@ -52,6 +52,15 @@ import ( "xorm.io/xorm" ) +var allowedImageMimes = []string{ + "image/jpeg", + "image/png", + "image/gif", + "image/bmp", + "image/tiff", + "image/webp", +} + // BackgroundProvider represents a thing which holds a background provider // Lets us get a new fresh provider every time we need one. type BackgroundProvider struct { @@ -202,6 +211,17 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error { _ = s.Rollback() return c.JSON(http.StatusBadRequest, models.Message{Message: "Uploaded file is no image."}) } + supported := false + for _, m := range allowedImageMimes { + if mime.Is(m) { + supported = true + break + } + } + if !supported { + _ = s.Rollback() + return c.JSON(http.StatusBadRequest, models.Message{Message: "Unsupported image format. Allowed: " + strings.Join(allowedImageMimes, ",")}) + } err = SaveBackgroundFile(s, auth, project, srcf, file.Filename, uint64(file.Size)) if err != nil { @@ -209,6 +229,9 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error { if files.IsErrFileIsTooLarge(err) { return echo.ErrBadRequest } + if IsErrFileUnsupportedImageFormat(err) { + return c.JSON(http.StatusBadRequest, models.Message{Message: "Unsupported image format. Allowed: " + strings.Join(allowedImageMimes, ",")}) + } return handler.HandleHTTPError(err) } @@ -228,9 +251,13 @@ func (bp *BackgroundProvider) UploadBackground(c echo.Context) error { } func SaveBackgroundFile(s *xorm.Session, auth web.Auth, project *models.Project, srcf io.ReadSeeker, filename string, filesize uint64) (err error) { + mime, _ := mimetype.DetectReader(srcf) _, _ = srcf.Seek(0, io.SeekStart) src, err := imaging.Decode(srcf) if err != nil { + if strings.Contains(err.Error(), "unknown format") { + return ErrFileUnsupportedImageFormat{Mime: mime.String()} + } return err } diff --git a/pkg/modules/background/handler/errors.go b/pkg/modules/background/handler/errors.go new file mode 100644 index 000000000..beaf46657 --- /dev/null +++ b/pkg/modules/background/handler/errors.go @@ -0,0 +1,42 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-present Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package handler + +import ( + "errors" + "fmt" +) + +// ErrFileUnsupportedImageFormat defines an error where an uploaded image format is not supported +// by the imaging library +// +// This is returned when decoding the image fails because the format is unknown. +type ErrFileUnsupportedImageFormat struct { + Mime string +} + +// Error is the error implementation of ErrFileUnsupportedImageFormat +func (err ErrFileUnsupportedImageFormat) Error() string { + return fmt.Sprintf("file is not a supported image format [Mime: %s]", err.Mime) +} + +// IsErrFileUnsupportedImageFormat checks if an error is ErrFileUnsupportedImageFormat +func IsErrFileUnsupportedImageFormat(err error) bool { + var errFileUnsupportedImageFormat ErrFileUnsupportedImageFormat + ok := errors.As(err, &errFileUnsupportedImageFormat) + return ok +}