fix: limit LDAP profile picture downloads to 2 MB

This commit is contained in:
Elias Schneider
2026-10-09 22:39:13 +02:00
parent 0ec6bfa191
commit d8ca4b6752
2 changed files with 43 additions and 2 deletions
+10 -2
View File
@@ -5,6 +5,7 @@ import (
"context"
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
"io"
"log/slog"
@@ -756,8 +757,15 @@ func (s *Service) saveProfilePicture(parentCtx context.Context, userId string, p
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
const maxProfilePictureSize int64 = 2 * 1024 * 1024 // 2MB
if res.ContentLength > maxProfilePictureSize {
return fmt.Errorf("profile picture must not exceed 2 MB")
}
data, err := io.ReadAll(utils.NewLimitReader(res.Body, maxProfilePictureSize+1))
if errors.Is(err, utils.ErrSizeExceeded) {
return fmt.Errorf("profile picture must not exceed 2 MB")
} else if err != nil {
return fmt.Errorf("failed to read profile picture: %w", err)
}
+33
View File
@@ -1,7 +1,9 @@
package ldapsync
import (
"bytes"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-ldap/ldap/v3"
@@ -45,6 +47,37 @@ func (c *fakeLDAPClient) Close() error {
return nil
}
func TestSaveProfilePictureRejectsOversizedDownload(t *testing.T) {
oversized := bytes.Repeat([]byte{0}, 2*1024*1024+1)
// Cover both a declared Content-Length and a chunked response that hides its size until it is read
tests := []struct {
name string
chunked bool
}{
{name: "content length", chunked: false},
{name: "chunked", chunked: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
if tt.chunked {
w.(http.Flusher).Flush()
}
_, _ = w.Write(oversized)
}))
t.Cleanup(server.Close)
svc := newService(Dependencies{HTTPClient: server.Client()})
err := svc.saveProfilePicture(t.Context(), "user-id", server.URL+"/picture.png")
require.ErrorContains(t, err, "must not exceed 2 MB")
})
}
}
func TestLdapServiceSyncAllReconcilesUsersAndGroups(t *testing.T) {
service, db := newTestLdapService(t, newFakeLDAPClient(
ldapSearchResult(