Skip to content

fix(scan): cap per-file allocation via MaxFileSize to prevent memory DoS#2924

Open
BiswajeetRay7 wants to merge 1 commit into
google:mainfrom
BiswajeetRay7:security/cap-file-size-dos
Open

fix(scan): cap per-file allocation via MaxFileSize to prevent memory DoS#2924
BiswajeetRay7 wants to merge 1 commit into
google:mainfrom
BiswajeetRay7:security/cap-file-size-dos

Conversation

@BiswajeetRay7

Copy link
Copy Markdown

Problem

Both filesystem scan (pkg/osvscanner/scan.go:240) and container image scan (pkg/osvscanner/osvscanner.go:321) construct scalibr.ScanConfig without MaxFileSize. scalibr documents 0 as "no limit" (osv-scalibr/extractor/filesystem/filesystem.go:114), so 20+ lockfile/manifest extractors that call io.ReadAll(input.Reader) can allocate arbitrarily large memory for attacker-supplied files.

Realistic attack sources:

  • Repo files up to 100 MB via standard git (or up to 2 GB via git-LFS with actions/checkout lfs: true)
  • Container image layer entries — no upper bound

On GitHub-hosted runners (7 GB RAM), a single ~2 GB package-lock.json or Cargo.lock can OOM-kill the scanner during JSON parse (JSON parsing typically allocates 3-5× file size).

Fix

  • Add defaultMaxFileSize = 512 * 1024 * 1024 (512 MiB) as a package-level constant, matching osv-scalibr's image-layer scanner MaxFileBytes default.
  • Wire it into both scalibr.ScanConfig sites.

Aligns with the JAR extractor's existing defaultMaxZipBytes pattern (osv-scalibr/extractor/filesystem/language/java/archive/archive.go:52) — extending the same safe-default philosophy to file-level ingestion.

Related

  • docs/migrating-from-scalibr.md:104 currently lists --max-file-size as "Not yet available". This change wires the default so the safeguard exists regardless of whether the CLI flag lands.
  • Related VRP report: https://issuetracker.google.com/issues/534007055

Testing

Existing test suite exercises files well under 512 MiB — no behavior change for real-world scans. Manual verify: repo with Cargo.lock >512 MiB is now skipped (as documented by filesystem.go:519-529 when maxFileSize > 0).

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant