SPDX License Field Lint for package.json, pyproject.toml and Cargo.toml

Reads the licence field in the open manifest and names every deprecated SPDX id, invalid string, PEP 639 leftover and copyleft obligation - with the exact replacement text.

Get the complete version $29

This page is the working piece. The full pack has everything below.

Reads the licence field in the open manifest and names every deprecated SPDX id, invalid string, PEP 639 leftover and copyleft obligation - with the exact replacement text.

An open-source licence audit runs 40-160 hours and thousands to tens of thousands of dollars per program; commercial SCA licence-compliance subscriptions start around $1,500/year.

Buy the full version — $29
Want the full version?
Enter your email and we send the download link.
ENDEJAESPT

Find a tool

· ReadyStack

Worked example

Real numbers from this tool, line by line.

SPDX License Field Lint for package.json, pyproject.toml and Cargo.toml

Six lines in one manifest fail before the SBOM is even started - and if you publish to npm, PyPI, crates.io or Packagist from a team selling into the EU, they are probably in your repository right now.

Here is the manifest. Every line below is a real, current defect, not a style preference.

"license": "GPL-3.0"
"license": "Unlicense"
license = {text = "MIT"}
"License :: OSI Approved :: MIT License"
"license": "MIT/Apache-2.0"
"license": "SSPL-1.0"

GPL-3.0 has been a deprecated identifier since SPDX License List 3.0. It was deprecated precisely because people used it to mean "version 3 or any later version", which is not what it says. The current identifiers are GPL-3.0-only and GPL-3.0-or-later, and they mean different things. The same split applies to GPL-2.0, LGPL-2.1, LGPL-3.0, AGPL-3.0 and the whole GNU family.

Unlicense is not UNLICENSED. Unlicense is a public-domain dedication: it hands your source to everyone, permanently. UNLICENSED is what npm expects for proprietary code. The two strings differ by one letter and a capitalisation, and they are exact opposites.

license = {text = "MIT"} and License :: classifiers are PEP 639 leftovers. PEP 639 replaced both with a bare SPDX expression in project.license plus a separate license-files key. setuptools has been warning about the table form, and its deprecation notice put the end of support at 2026-02-18. If your build has started failing on a machine with a current setuptools, this is why.

MIT/Apache-2.0 is old npm syntax that was removed. SPDX expressions use uppercase operators: MIT OR Apache-2.0. A lowercase or invalidates the whole expression just as surely.

SSPL-1.0 is source-available, not open source. The OSI declined to approve it, Debian and Fedora exclude it, and its section 13 extends copyleft to your entire service-management stack if you offer the software as a service. BUSL-1.1, Elastic-2.0, RSALv2, the PolyForm family, FSL and Commons-Clause sit in the same box. A procurement policy that says "OSI-approved licences only" rejects every one of them.

Why the usual tools do not catch this

npm publish and setuptools check the one package you are publishing. They say nothing about the hundreds of manifests you consume, and neither of them flags a deprecated SPDX identifier - a deprecated id is still a *known* id, so it validates.

Asking a chatbot is worse than useless here, and predictably so. Most of the text these models learned from was written before SPDX List 3.0 and before PEP 639, so the modal answer is GPL-3.0 and License :: OSI Approved :: MIT License. The model is confidently reproducing the exact two defects you are trying to remove.

That matters more now than it did last year. The licence is a required field in an SBOM, and CRA obligations landed on 11 September 2026 for vulnerability and incident reporting, with the full technical-documentation and SBOM requirements arriving 11 December 2027. You cannot answer either one from a manifest whose licence column is UNKNOWN.

The extension

SPDX License Lint is a VS Code extension that reads the licence declarations in the file you have open - package.json, pyproject.toml, setup.cfg, Cargo.toml, composer.json, *.gemspec - and applies 73 rules covering deprecated SPDX identifiers, invalid strings, npm's removed array and object forms, SPDX expression syntax, PEP 639 migration, and the obligations each licence actually carries.

Every finding gives you the line number, the reason, and the exact replacement string. That part is free and it finishes the job for the file in front of you.

The full version is $29 once: it runs the same 73 rules over every manifest in the repository in one pass, exports the licence inventory as CSV, JSON or HTML for the SBOM licence column, and rewrites a wrong identifier in place so a repo full of GPL-3.0 becomes GPL-3.0-only without a hand edit per file. For comparison, an open-source licence audit runs 40-160 hours and thousands to tens of thousands of dollars per program.

It also runs as a single web page with no install, no account and no network call, so you can paste a manifest in and see the answer before deciding anything.

Questions people ask

What does SPDX License Lint actually do?

It reads the licence declarations in the manifest you have open - package.json, pyproject.toml, setup.cfg, Cargo.toml, composer.json or a gemspec - and applies 73 rules. Each finding gives you the line number, why it is wrong, and the exact SPDX string to write instead. It covers deprecated identifiers, invalid strings, npm's removed array and object forms, expression syntax, PEP 639 migration, and the obligations a licence carries.

Who is this for?

Maintainers and platform engineers who publish packages to npm, PyPI, crates.io or Packagist, and teams filling in the licence column of an SBOM for an enterprise or EU customer. It is aimed at anyone who has been asked which licences are in their repository and cannot answer from memory, and at Python projects whose builds started failing after the setuptools PEP 639 deprecation.

Why not just rely on npm, setuptools, or a chatbot?

npm publish and setuptools check only the one package you are publishing, never the hundreds you consume, and neither flags a deprecated SPDX identifier, because a deprecated id is still a known id and validates. A chatbot is worse: most of its training text predates SPDX List 3.0 and PEP 639, so it confidently answers GPL-3.0 and License :: OSI Approved ::, the exact two defects you are removing.

What is free and what needs a licence key?

Free covers the manifest you have open, against all 73 rules, with nothing held back and no watermark, time limit or usage cap. The $29 version changes the scale rather than the quality: it runs the same rules over every manifest in the repository at once, exports the licence inventory as CSV, JSON or HTML for your SBOM, and rewrites a wrong identifier in place across files.

What would this cost me otherwise?

An open-source licence audit runs 40 to 160 hours and thousands to tens of thousands of dollars per program, and commercial SCA licence-compliance subscriptions start around $1,500 per year. This extension is $29 once, with a 7-day full refund. It does not replace legal advice on obligations, but it removes the mechanical defects an auditor would bill you to find first.

Ask about this tool

One question, answered by the person who built it. Your email only if you want the answer sent.