Skip to content

fix(spdx): bound recursion depth when parsing license expressions - #3032

Merged
another-rex merged 2 commits into
google:mainfrom
Amey-Thakur:fix/spdx-recursion-depth-limit
Sep 2, 2026
Merged

another-rex merged 2 commits into
google:mainfrom
Amey-Thakur:fix/spdx-recursion-depth-limit

Conversation

@Amey-Thakur

Copy link
Copy Markdown
Contributor

Overview

Fixes #2993.

spdx.Satisfies parses SPDX license expressions with an unbounded recursive descent. License strings come from the metadata of scanned packages, so a crafted expression with deeply nested brackets recurses until the goroutine stack overflows, a fatal error that recover cannot catch.

Reopens #2995, which was closed when its source fork was deleted. The change is identical, rebased on current main. Thank you @another-rex for the go-ahead.

Details

The descent runs parseOr -> parseAnd -> parseExpression, and parseExpression recurses into parseOr on every ( with no bound. The fix:

  • a depth field on the tokens struct, incremented on each bracketed sub-expression and decremented on the way out
  • past maxDepth (1000), the parser returns an ordinary parse error instead of recursing

Real SPDX expressions nest only a few levels, so the ceiling rejects nothing legitimate. An over-nested expression now fails like any other invalid input rather than terminating the process. CWE-674.

Testing

  • TestSatisfies_DeeplyNested drives a 2,000,000-deep expression and asserts a parse error. It crashes with a fatal stack overflow without this change and passes with it.
  • go test ./internal/spdx/ passes; gofmt and go vet ./internal/spdx/ are clean.

Checklist

  • I have signed the Contributor License Agreement.
  • I have run the linter (gofmt, go vet) on the changed package.
  • I have run the unit tests for the changed package and all tests pass.
  • I have made my commits and PR title follow the Conventional Commits specification.

@codecov-commenter

codecov-commenter commented Sep 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.42%. Comparing base (d38ec03) to head (05d7b13).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3032      +/-   ##
==========================================
+ Coverage   79.41%   79.42%   +0.01%     
==========================================
  Files         118      118              
  Lines        8097     8101       +4     
==========================================
+ Hits         6430     6434       +4     
  Misses       1310     1310              
  Partials      357      357              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@another-rex
another-rex merged commit 1c93dc4 into google:main Sep 2, 2026
24 checks passed
@Amey-Thakur
Amey-Thakur deleted the fix/spdx-recursion-depth-limit branch September 6, 2026 01:35
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
osv-scanner 2.6.0

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre>### Features:

- [Feature #2888](google/osv-scanner#2888) Publish multi-arch (`linux/arm64`) image for `osv-scanner-action`.
- [Feature #3066](google/osv-scanner#3066) Configure retry policy with exponential backoff for transient gRPC errors in scalibr plugins.
- **Dependency scanning & lockfile improvements via `osv-scalibr`**:
  - Extract Git repository URLs and support local OSV tag matching for Git-based dependencies in JavaScript lockfiles (`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock`).
  - Assign `pkg:git` PURL type to Git commit-pinned dependencies across JS and Cargo lockfiles to avoid false positives against registry packages ([#2863](google/osv-scanner#2863)).
  - Retain packages without a version or PURL in SPDX output ([google/osv-scalibr#2375](google/osv-scalibr#2375)) and merge related packages based on lineage relationships.
- **New extractors and plugin support via `osv-scalibr`**:
  - Many additional filetypes are supported. These are not enabled by default yet, so if you need a particular new filetype, use `--experimental-plugins` flag. See ["Supported Inventory Types"](https://github.com/google/osv-scalibr/blob/3f6473abebb329f3e0dc7e9e0d9c91e0c6e51277/docs/supported_inventory_types.md) for the extractor name.

### Fixes:

- [Bug #3075](google/osv-scanner#3075) Ensure `results` property in JSON output is an empty array `[]` instead of `null` when scanning with `--allow-no-lockfiles` and no lockfiles are found.
- [Bug #3071](google/osv-scanner#3071) Preserve valid UTF-8 sequences when truncating multibyte text in vertical output.
- [Bug #2919](google/osv-scanner#2919) Add filter to show packages with license violations but no vulnerabilities in the HTML report.
- [Bug #3049](google/osv-scanner#3049) Keep filter dropdown checklist open when clicking options in the HTML report.
- [Bug #3023](google/osv-scanner#3023) Guard against panic on empty or whitespace-only license expressions in SPDX license evaluation.
- [Bug #3032](google/osv-scanner#3032) Bound recursion depth when parsing SPDX license expressions to prevent stack overflow on deeply nested expressions.
- [Bug #3061](google/osv-scanner#3061) Remove purl caching in scan filtering to avoid dropping SBOM packages without purls.
- [Bug #3063](google/osv-scanner#3063) Log plugin and enricher errors during container scans instead of failing silently.
- [Bug #2977](google/osv-scanner#2977) Return an error instead of aborting the process (`log.Fatalf`) when an `rlib` archive has no object file during Rust source analysis.
- [Bug #3083](google/osv-scanner#3083) Return a descriptive error from `DoContainerScan` when `ScannerActions.Image` is empty instead of panicking.
- **Fixes via `osv-scalibr`**:
  - Fix false-positive Go standard library matches for packages with module paths ending in `/go` (e.g. `pkg:golang/github.com/json-iterator/go`) ([#3017](google/osv-scanner#3017)).
  - Secure guided remediation file operations with `os.Root` to prevent path traversal attacks ([google/osv-scalibr#2363](google/osv-scalibr#2363)).
  - Prevent OOM and disk exhaustion issues with tar bombs during archive extraction.
  - Strip platform suffix from RubyGems versions in CycloneDX ([google/osv-scalibr#2313](google/osv-scalibr#2313)).
  - Ignore `.deps.json` files that don't have an object as their root in `dotnet/depsjson` extractor ([google/osv-scalibr#2423](google/osv-scalibr#2423)).

### Misc:

- Update `osv-scalibr` to `v0.5.3-0.20260911142458-3090dbb7aaa2` ([#3079](google/osv-scanner#3079)).
- Update Go to v1.27 and `golangci-lint` to v2.13 ([#3046](google/osv-scanner#3046)).
  - This now supports call analysis on go v1.27 projects.
- Update `google.golang.org/grpc` to v1.83.2 ([#3062](google/osv-scanner#3062)).

## New Contributors
* @summerpan688 made their first contribution in google/osv-scanner#2919
* @BenkiNew made their first contribution in google/osv-scanner#3038
* @Amey-Thakur made their first contribution in google/osv-scanner#3032
* @sl4x0 made their first contribution in google/osv-scanner#3023
* @shubhransh-gupta made their first contribution in google/osv-scanner#3049
* @kobihikri made their first contribution in google/osv-scanner#2977
* @skialpine made their first contribution in google/osv-scanner#2888
* @keeltrace made their first contribution in google/osv-scanner#3071
* @Muszic made their first contribution in google/osv-scanner#3083
* @knQzx made their first contribution in google/osv-scalibr#2313
* @micrictor made their first contribution in google/osv-scalibr#2047
* @srossross made their first contribution in google/osv-scalibr#2375

**Full Changelog**: https://github.com/google/osv-scanner/compare/v2.5.1...v2.6.0</pre>
  <p>View the full release notes at <a href="https://github.com/google/osv-scanner/releases/tag/v2.6.0">https://github.com/google/osv-scanner/releases/tag/v2.6.0</a>.</p>
</details>
<hr>

See merge request: Harmonybrew/homebrew-core!20195
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.

spdx.Satisfies: unbounded recursion causes uncatchable stack overflow on deeply nested license expressions

3 participants