From aa96725ae7d38f7b48e9d3fc45f2052140367114 Mon Sep 17 00:00:00 2001 From: bircni Date: Sat, 22 Aug 2026 02:11:29 +0200 Subject: [PATCH] fix(packages): limit Swift package manifests (#39025) Bound the number and aggregate size of Swift manifests retained from an uploaded archive. --- modules/packages/swift/metadata.go | 13 +++++++++++++ modules/packages/swift/metadata_test.go | 14 ++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/modules/packages/swift/metadata.go b/modules/packages/swift/metadata.go index 3f29675fb84..f9a517f9253 100644 --- a/modules/packages/swift/metadata.go +++ b/modules/packages/swift/metadata.go @@ -21,6 +21,7 @@ import ( var ( ErrMissingManifestFile = util.NewInvalidArgumentErrorf("Package.swift file is missing") ErrManifestFileTooLarge = util.NewInvalidArgumentErrorf("Package.swift file is too large") + ErrManifestFilesTooLarge = util.NewInvalidArgumentErrorf("Package.swift files are too large") ErrInvalidManifestVersion = util.NewInvalidArgumentErrorf("manifest version is invalid") manifestPattern = regexp.MustCompile(`\APackage(?:@swift-(\d+(?:\.\d+)?(?:\.\d+)?))?\.swift\z`) @@ -29,6 +30,8 @@ var ( const ( maxManifestFileSize = 128 * 1024 + maxManifestFiles = 64 + maxManifestSize = maxManifestFiles * maxManifestFileSize PropertyScope = "swift.scope" PropertyName = "swift.name" @@ -140,6 +143,16 @@ func ParsePackage(sr io.ReaderAt, size int64, mr io.Reader) (*Package, error) { manifestFiles = append(manifestFiles, file) } } + if len(manifestFiles) > maxManifestFiles { + return nil, ErrManifestFilesTooLarge + } + var manifestSize uint64 + for _, file := range manifestFiles { + manifestSize += file.UncompressedSize64 + } + if manifestSize > maxManifestSize { + return nil, ErrManifestFilesTooLarge + } for _, file := range manifestFiles { manifestMatch := manifestPattern.FindStringSubmatch(path.Base(file.Name)) diff --git a/modules/packages/swift/metadata_test.go b/modules/packages/swift/metadata_test.go index 93895a73fd7..d041d64f111 100644 --- a/modules/packages/swift/metadata_test.go +++ b/modules/packages/swift/metadata_test.go @@ -6,6 +6,7 @@ package swift import ( "archive/zip" "bytes" + "fmt" "strings" "testing" @@ -54,6 +55,19 @@ func TestParsePackage(t *testing.T) { assert.ErrorIs(t, err, ErrManifestFileTooLarge) }) + t.Run("TooManyManifestFiles", func(t *testing.T) { + entries := make([][2]string, 0, maxManifestFiles+1) + entries = append(entries, [2]string{"Package.swift", "// swift-tools-version:5.7"}) + for i := range maxManifestFiles { + entries = append(entries, [2]string{fmt.Sprintf("Package@swift-5.%d.swift", i), "// swift-tools-version:5.7"}) + } + + data := writeOrderedZipArchive(entries) + p, err := ParsePackage(bytes.NewReader(data.Bytes()), int64(data.Len()), nil) + assert.Nil(t, p) + assert.ErrorIs(t, err, ErrManifestFilesTooLarge) + }) + t.Run("WithoutMetadata", func(t *testing.T) { content1 := "// swift-tools-version:5.7\n//\n// Package.swift" content2 := "// swift-tools-version:5.6\n//\n// Package@swift-5.6.swift"