fix(backgrounds): enforce max file size for unsplash downloads

Check Content-Length and use io.LimitReader to prevent OOM from
unexpectedly large unsplash responses before buffering into memory.
This commit is contained in:
kolaente
2026-02-04 19:37:50 +01:00
parent 41b511b322
commit 19f6e4b7c9

View File

@@ -280,11 +280,22 @@ func (p *Provider) Set(s *xorm.Session, image *background.Image, project *models
}
log.Debugf("Pinged unsplash download endpoint for photo %s", image.ID)
// Buffer the response body so we have a seekable reader for S3 uploads
bodyBytes, err := io.ReadAll(resp.Body)
// Enforce max file size to prevent OOM from unexpectedly large responses
maxSize := int64(config.GetMaxFileSizeInMBytes() * 1024 * 1024)
if resp.ContentLength > maxSize {
return files.ErrFileIsTooLarge{Size: uint64(resp.ContentLength)}
}
// Buffer the response body so we have a seekable reader for S3 uploads.
// Use LimitReader as a safety net in case Content-Length was missing or inaccurate.
limitedReader := io.LimitReader(resp.Body, maxSize+1)
bodyBytes, err := io.ReadAll(limitedReader)
if err != nil {
return err
}
if int64(len(bodyBytes)) > maxSize {
return files.ErrFileIsTooLarge{Size: uint64(len(bodyBytes))}
}
// Save it as a file in vikunja
file, err := files.Create(bytes.NewReader(bodyBytes), "", uint64(len(bodyBytes)), auth)