Repository navigation
Description
Hi @goneall :) Hope you are doing well and having fun on all your adventures!
I came across some validation discrepancies (errors?) when comparing validation output between spdx-tools pyhon, java and the plain text spec. I am seeing the Verify command reports documents as "This SPDX Document is valid." even when they violate several normative MUST requirements of the SPDX 2.3 spec. The equivalent Python spdx-tools validator flags the same documents as invalid, so the two reference implementations disagree.
Specifically, Verify with the latest java release does not seem to enforce:
- The document's SPDXID MUST be SPDXRef-DOCUMENT (§6.3)
- Element ID uniqueness (i.e. the document identifier collides with a package identifier and is not reported) (§7.2)
- documentNamespace MUST be an absolute URI (RFC-3986). (§6.5)
Reproduction 1 — non-URI documentNamespace (§6.5):
{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"x","documentNamespace":"not-a-uri","creationInfo":{"creators":["Tool: t"],"created":"1970-01-01T00:00:00Z"},"packages":[{"name":"a","SPDXID":"SPDXRef-a","downloadLocation":"NOASSERTION","filesAnalyzed":false}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relationshipType":"DESCRIBES","relatedSpdxElement":"SPDXRef-a"}]}
$ java -jar tools-java-2.0.7-jar-with-dependencies.jar Verify b-namespace.spdx.json
This SPDX Document is valid.
Reproduction 2 — document SPDXID is not SPDXRef-DOCUMENT and duplicates a package ID (§6.3 + uniqueness):
{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-a","name":"x","documentNamespace":"https://example.com/C","creationInfo":{"creators":["Tool: t"],"created":"1970-01-01T00:00:00Z"},"packages":[{"name":"a","SPDXID":"SPDXRef-a","downloadLocation":"NOASSERTION","filesAnalyzed":false}],"relationships":[{"spdxElementId":"SPDXRef-a","relationshipType":"DESCRIBES","relatedSpdxElement":"SPDXRef-a"}]}
$ java -jar tools-java-2.0.7-jar-with-dependencies.jar Verify c-dup-doc-pkg.spdx.json
This SPDX Document is valid.
Both documents should be reported as invalid. The 2.3 spec requires:
§6.3 SPDX identifier field — the document SPDXID value MUST be SPDXRef-DOCUMENT: https://spdx.github.io/spdx-spec/v2.3/document-creation-information/#63-spdx-identifier-field
§6.5 SPDX document namespace — MUST be a unique absolute URI with no fragment: https://spdx.github.io/spdx-spec/v2.3/document-creation-information/#65-spdx-document-namespace-field
§7.2 / element identifiers — each SPDXID MUST be unique within the document: https://spdx.github.io/spdx-spec/v2.3/package-information/#72-package-spdx-identifier-field
Running the python tools on the same files seems to yield more expected results:
b-namespace.spdx.json -> INVALID: document_namespace must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: not-a-uri
c-dup-doc-pkg.spdx.json -> INVALID: spdx_id must be SPDXRef-DOCUMENT, but is: SPDXRef-a
every spdx_id must be unique within the document, but found duplicates: ['SPDXRef-a']
It's been a while so totally recognize this could be user error but wanted to open this here in case others run into it.
Activity
goneall commentedon Aug 20, 2026
Thanks @rnjudge for the detailed issue! Not checking the document ID is a new issue. I think checking for valid URI has been fixed, but not yet release - I'll double check to make sure.
tommyquak commentedon Nov 1, 2026
@goneall I'd like to work on this - could you assign it to me?
I reproduced both cases with 2.0.7. Two notes from reading the code:
JacksonDeSerializerskips theSPDXIDfield (it's inSKIPPED_PROPERTIES) and always creates the document asSPDXRef-DOCUMENT, soSpdxDocument.verify()never sees the original value. Would you prefer the check in the Jackson store when deserializing, or somewhere else?SpdxDocument._verify()(spdx-java-model-2_X) usesnew java.net.URI(...), which accepts relative values likenot-a-uri. It's unchanged on master, so I don't think it's fixed yet. CheckingisAbsolute()and no fragment would cover §6.5.I'd start with those two and leave duplicate IDs for a follow-up, unless you'd like them together.
goneall commentedon Nov 1, 2026
Thanks @tommyquak
Really good question - it would need to be checked before or during deserialization since the verify function is run against the deserialized model. The deserialize function could return a warning, but that would break the interface contract. We could maintain a list of warnings in the
JacksonDeSerializerand add a function to return that to the tools-java Verify code. A simpler, and perfectly acceptable, approach would be to just specifically check for this in the tools-java Verify code. Either approach works for me.Thanks for the analysis - agree with the approach to fix
Sounds like a good plan