From ea78e871479acf99b4fcef48d7633be34c7d4d74 Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 4 Feb 2026 19:47:59 +0100 Subject: [PATCH] fix(dump): limit copy size to prevent decompression bombs Use io.CopyN with a max size limit when extracting files from zip archives during restore to prevent potential DoS via decompression bombs. --- pkg/modules/dump/restore.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/modules/dump/restore.go b/pkg/modules/dump/restore.go index 637a8717e..e4fbec4e3 100644 --- a/pkg/modules/dump/restore.go +++ b/pkg/modules/dump/restore.go @@ -32,6 +32,7 @@ import ( "github.com/hashicorp/go-version" + "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/files" "code.vikunja.io/api/pkg/initialize" @@ -212,9 +213,15 @@ func restoreFile(id int64, zipFile *zip.File) error { _ = os.Remove(tmpFile.Name()) }() - if _, err := io.Copy(tmpFile, fc); err != nil { + // Limit copy size to prevent decompression bombs + maxSize := config.GetMaxFileSizeInMBytes() * 1024 * 1024 + written, err := io.CopyN(tmpFile, fc, int64(maxSize)+1) // #nosec G115 -- maxSize is configured, not user input + if err != nil && !errors.Is(err, io.EOF) { return fmt.Errorf("could not copy to temp file: %w", err) } + if uint64(written) > maxSize { + return files.ErrFileIsTooLarge{Size: uint64(written)} + } if _, err := tmpFile.Seek(0, io.SeekStart); err != nil { return fmt.Errorf("could not seek temp file: %w", err)