From ed7c5cfb947162b2d56c1a2ef2fe9dd4dca39f49 Mon Sep 17 00:00:00 2001 From: BiswajeetRay7 Date: Sun, 12 Jul 2026 18:21:54 -0400 Subject: [PATCH] fix(scan): cap per-file allocation via MaxFileSize to prevent memory DoS Both filesystem scan (scan.go) and container image scan (osvscanner.go) constructed scalibr.ScanConfig without MaxFileSize. scalibr documents 0 as 'no limit', so 20+ lockfile/manifest extractors that io.ReadAll on input.Reader could allocate arbitrarily large memory for attacker-supplied files (repo files up to 2 GB via git-LFS, or unbounded container-image layer entries). Add defaultMaxFileSize = 512 MiB matching the image-layer scanner's MaxFileBytes and pass it to both ScanConfig sites. This aligns with the JAR extractor's existing defaultMaxZipBytes pattern. Refs: docs/migrating-from-scalibr.md:104 lists --max-file-size as 'Not yet available'. This change wires the default so the safeguard exists regardless of the CLI flag. --- pkg/osvscanner/osvscanner.go | 8 ++++++++ pkg/osvscanner/scan.go | 1 + 2 files changed, 9 insertions(+) diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go index e3e86a81efc..b5c131eb73c 100644 --- a/pkg/osvscanner/osvscanner.go +++ b/pkg/osvscanner/osvscanner.go @@ -97,6 +97,13 @@ type TransitiveScanningActions struct { MavenRegistry string } +// defaultMaxFileSize caps per-file memory allocation for extractors. +// Rationale: 20+ lockfile extractors call io.ReadAll(input.Reader) with no +// per-parser limit; without a cap, a repository or container-image layer +// entry can allocate arbitrary memory during extraction. 512 MiB matches +// the image-layer scanner's MaxFileBytes default in osv-scalibr. +const defaultMaxFileSize = 512 * 1024 * 1024 + type ExternalAccessors struct { // Matchers VulnMatcher clientinterfaces.VulnerabilityMatcher @@ -323,6 +330,7 @@ func DoContainerScan(actions ScannerActions) (models.VulnerabilityResults, error Capabilities: capabilities, StoreAbsolutePath: true, ExplicitPlugins: true, + MaxFileSize: defaultMaxFileSize, }) if err != nil { return models.VulnerabilityResults{}, fmt.Errorf("failed to scan container image: %w", err) diff --git a/pkg/osvscanner/scan.go b/pkg/osvscanner/scan.go index f53fb572cab..fda1aec1f37 100644 --- a/pkg/osvscanner/scan.go +++ b/pkg/osvscanner/scan.go @@ -238,6 +238,7 @@ SBOMLoop: // For each root, run scalibr's scan() once. for root, paths := range rootMap { sr := scanner.Scan(context.Background(), &scalibr.ScanConfig{ + MaxFileSize: defaultMaxFileSize, Plugins: filteredPlugins, Capabilities: &capabilities, ScanRoots: fs.RealFSScanRoots(root),