bug: SBOM writers discard license expressions longer than 100 characters
- Langage dominant
- Rust
- Étoiles
- 471
- Forks
- 27
- Merge moyen
- 17 h 14 min
- PR mergées (30 j)
- 5
Description
## Description
Both SBOM writers discard any license expression longer than 100 characters and emit `NOASSERTION` in its place. The direct scan resolves the license correctly, so the loss happens only on the way into a generated document.
The cap has no basis in the specification. SPDX 2.3 places no length limit on a license expression, and neither does CycloneDX. The effect is worst on the packages most likely to carry compliance risk, because an expression is long precisely when a package aggregates many licensed components. On a stock `fedora:41` root filesystem, `libgomp` has a 744 character expression containing `GPL-3.0-or-later`, and the SBOM records it as `NOASSERTION`.
## Steps to Reproduce
Any scan source reproduces it. The smallest case is a single npm dependency:
```sh
mkdir -p app/node_modules/longlic
echo '{"name":"app","version":"1.0.0","dependencies":{"longlic":"1.0.0"}}' > app/package.json
echo '{"name":"longlic","version":"1.0.0","license":"MIT AND Apache-2.0 AND BSD-3-Clause AND ISC AND Zlib AND MPL-2.0 AND GPL-2.0-or-later AND LGPL-2.1-or-later AND CC0-1.0"}' > app/node_modules/longlic/package.json
feluda --path app --json # license resolves correctly, 119 characters
feluda sbom spdx --path app --output s.json
grep licenseDeclared s.json # NOASSERTION
```
Observed on a `fedora:41` root filesystem via `--filesystem`, on a Debian package via a `copyright` file, and on the npm case above, so it is independent of the scan source.
## Root cause
The length test in the structural constraint block of `convert_to_spdx_license_expression`, at src/sbom/spdx.rs:161:
https://github.com/anistark/feluda/blob/2e0d5d5/src/sbom/spdx.rs#L160-L166
The correlation is exact. Across the 124 packages of a `fedora:41` root filesystem, every expression over 100 characters was replaced with `NOASSERTION` and every expression under it was preserved. The shortest one dropped was 116 characters, the longest one kept was 96, and no other rule in the function fired for any of them.
CycloneDX is affected through the same path, because it converts from the SPDX document rather than from `LicenseInfo`:
https://github.com/anistark/feluda/blob/2e0d5d5/src/sbom/cyclonedx.rs#L225-L226
It records `{"license": {"name": "NOASSERTION"}}` for the same components.
## Environment
- feluda 1.15.0, commit 2e0d5d5
- Reproduced on macOS 15.3, and independent of platform since the check is a plain string length test
## Additional Context
Introduced in c5cb0ba (#163), which added the character validation and structural checks around it. The other rules in that function guard against genuinely malformed or unsafe input, so this is specifically about the arbitrary length bound rather than the validation as a whole.
Two things worth deciding alongside a fix:
- Whether a long but structurally valid expression should ever be discarded, given that the same function already rejects forbidden characters and template patterns separately.
- Whether an expression that genuinely cannot be represented should fall back to `LicenseRef-feluda-*` with the text in `hasExtractedLicensingInfos`, which is the mechanism the SBOM ingest enrichment already uses for free-form registry titles, rather than to `NOASSERTION`.
## Acceptance criteria
- A structurally valid license expression of any length survives into both `spdx` and `cyclonedx` output.
- The 14 packages of a stock `fedora:41` root filesystem that currently report `NOASSERTION` carry their real expressions.
- `feluda sbom validate` still passes with zero errors on the result.
- A regression test covers an expression over 100 characters.
Guide de contribution
Ouvrir le guide de contribution
Évaluation
Cette issue n'a pas encore été évaluée.