Each ecosystem stores license data differently. npm, Cargo, NuGet and Composer use manifest fields that accept SPDX style values. Python is moving to a validated License-Expression field. Maven uses free text names in the POM. Go has no field, so tools read license files. Know which signal you are reading before you trust it.
The comparison
| Ecosystem | Where the license lives | Structured? | Watch for |
|---|---|---|---|
| npm | license field in package.json | SPDX id, expression, SEE LICENSE IN, UNLICENSED | Deprecated licenses array |
| Python | License-Expression, legacy License and classifiers | New field validated, legacy free text | Mixed old and new packages |
| Maven | licenses element in the POM | Free text name, recommended SPDX | Many spellings, inherited from parent |
| Cargo | license or license-file in Cargo.toml | SPDX 2.3 expression | Custom terms in license-file |
| NuGet | license element in the nuspec | SPDX expression or file | Deprecated licenseUrl |
| Composer | license field in composer.json | String or array, array means choice | proprietary, missing field |
| Go | LICENSE style files | No field, heuristic detection | Edited text, odd file names |
What to do with this
The pattern is clear: where authors give a structured value, scanning is reliable and fast. Where they do not, you need file reading and human review. A good process uses the manifest value first, flags every legacy or free text case as lower confidence, and reads the file when the result matters.
Rules that work across all of them
- Read the exact version you ship, not the latest page.
- Treat a missing value as unknown.
- Parse operators. OR is a choice, AND is a requirement, WITH adds an exception.
- Keep the license text for custom values.
- Normalize names to SPDX before applying policy. See normalizing license names.
- Record your decision against the package and version.
For each ecosystem there is a deeper post: see NuGet, Composer, Cargo, Go and Maven.
Try it yourself
Click through it at your own pace, or open it full screen.
Look at the ecosystems represented in the inventory and think about which license signal each one provides.
Safeguard scans dependencies across ecosystems and builds SBOMs. Try a free scan.
Quick check
Which ecosystem has no license field?
Go. Tools find licenses by reading license files and matching their text.
Does a Composer array mean AND?
No. It means a choice between the listed licenses.
Sources
- npm Docs, package.json: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#license
- PEP 639: https://peps.python.org/pep-0639/
- Apache Maven, POM Reference: https://maven.apache.org/pom.html#Licenses
- The Cargo Book, manifest: https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields
- Microsoft Learn, nuspec reference: https://learn.microsoft.com/en-us/nuget/reference/nuspec#license
- Composer documentation, schema: https://getcomposer.org/doc/04-schema.md#license
- Go package discovery site, license policy: https://pkg.go.dev/license-policy
Last reviewed: 19 October 2026.