spdx-3-model
spdx-3-model copied to clipboard
ExternalIdentifier based on its ExternalIdentifierType
From ExternalIdentifierType:
[implicit] identifier must be valid based on its ExternalIdentifierType.
Suggested SHACL shapes:
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix spdxcore: <https://spdx.org/rdf/3.0.1/terms/Core/> .
@prefix spdxextidtype: <https://spdx.org/rdf/3.0.1/terms/Core/ExternalIdentifierType/> .
spdxcore:ExternalIdentifierStringByTypeShape
a sh:NodeShape ;
sh:targetClass spdxcore:ExternalIdentifier ;
sh:or (
[
sh:property [
sh:path spdxcore:externalIdentifierType ;
sh:or (
[
sh:hasValue spdxextidtype:cpe22 ;
]
[
sh:hasValue spdxextidtype:cpe23 ;
]
) ;
] ;
sh:property [
sh:path spdxcore:identifier ;
sh:pattern "^([c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9._\\-~%]*){0,6})|(cpe:2\\.3:[aho*\\-](:(((\\?*|\\*?)([a-zA-Z0-9\\-._]|(\\\\[\\\\*?!\"#$%&'()+,/:;<=>@\\[\\]\\^`{|}~]))+(\\?*|\\*?))|[*\\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[*\\-]))(:(((\\?*|\\*?)([a-zA-Z0-9\\-._]|(\\\\[\\\\*?!\"#$%&'()+,/:;<=>@\\[\\]\\^`{|}~]))+(\\?*|\\*?))|[*\\-])){4})$" ;
] ;
]
[
sh:property [
sh:path spdxcore:externalIdentifierType ;
sh:hasValue spdxextidtype:cve ;
] ;
sh:property [
sh:path spdxcore:identifier ;
sh:pattern "^CVE-[0-9]{4}-[0-9]{4,19}$" ;
] ;
]
[
sh:property [
sh:path spdxcore:externalIdentifierType ;
sh:hasValue spdxextidtype:email ;
] ;
sh:property [
sh:path spdxcore:identifier ;
sh:maxLength 320 ;
sh:pattern "^(?=[^@]{1,64}@)[a-zA-Z0-9!#$%&'*+\\-/=?^_`{|}~]+(\\.[a-zA-Z0-9!#$%&'*+\\-/=?^_`{|}~]+)*@[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)*$" ;
] ;
]
[
sh:property [
sh:path spdxcore:externalIdentifierType ;
sh:hasValue spdxextidtype:gitoid ;
] ;
sh:property [
sh:path spdxcore:identifier ;
sh:pattern "^gitoid:(blob|tree|commit|tag):(sha1:[a-f0-9]{40}|sha256:[a-f0-9]{64})$" ;
] ;
]
[
sh:property [
sh:path spdxcore:externalIdentifierType ;
sh:hasValue spdxextidtype:swhid ;
] ;
sh:property [
sh:path spdxcore:identifier ;
sh:pattern "^swh:1:(snp|rel|rev|dir|cnt):[a-f0-9]{40}(;(origin=[^;]+|visit=swh:1:(snp|rel|rev|dir|cnt):[a-f0-9]{40}|anchor=swh:1:(snp|rel|rev|dir|cnt):[a-f0-9]{40}|path=[^;]+|lines=\\d+(-\\d+)?|bytes=\\d+(-\\d+)?))*$" ;
] ;
]
) ;
sh:message "ExternalIdentifier must have a valid identifier for its externalIdentifierType." .
Test data:
@prefix ex: <http://example.org/ns#> .
@prefix spdxcore: <https://spdx.org/rdf/3.0.1/terms/Core/> .
@prefix spdxextidtype: <https://spdx.org/rdf/3.0.1/terms/Core/ExternalIdentifierType/> .
ex:ValidCpe
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:cpe22 ;
spdxcore:identifier "cpe:2.3:o:microsoft:windows_vista:6.0:sp1:-:-:home_premium:-:x64:-" .
ex:InvalidCpe
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:cpe22 ;
spdxcore:identifier "cpe:2.3:o:microsoft:windows_vista:6. 0:sp1:-:-:home_premium:-:x64:-" .
ex:ValidCve
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:cve ;
spdxcore:identifier "CVE-2020-12345" .
ex:InvalidCve
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:cve ;
spdxcore:identifier "CRE-202-12345" .
ex:ValidEmail
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:email ;
spdxcore:identifier "[email protected]" .
ex:InvalidEmail
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:email ;
spdxcore:identifier "aaa@b_b.ccc" .
ex:ValidGitoid
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:gitoid ;
spdxcore:identifier "gitoid:blob:sha1:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64" .
ex:InvalidGitoid
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:gitoid ;
spdxcore:identifier "gitoid:blob:sha9:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64" .
ex:ValidSwhid
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:swhid ;
spdxcore:identifier "swh:1:snp:c7c108084bc0bf3d81436bf980b46e98bd338453" .
ex:InvalidSwhid
a spdxcore:ExternalIdentifier ;
spdxcore:externalIdentifierType spdxextidtype:swhid ;
spdxcore:identifier "swh:1:c7c108084bc0bf3d81436bf980b46e98bd338453" .
Test script: https://raw.githubusercontent.com/condots/dots/refs/heads/main/scripts/shacl/test.py
Test results:
----------------------------------------------------------------------------------------------------
Severity: sh:Violation
Source Shape: spdxcore:ExternalIdentifierStringByTypeShape
Focus Node: ex:InvalidCve
Value Node: ex:InvalidCve
Result Path: None
Message: ExternalIdentifier must have a valid identifier for its externalIdentifierType.
----------------------------------------------------------------------------------------------------
Severity: sh:Violation
Source Shape: spdxcore:ExternalIdentifierStringByTypeShape
Focus Node: ex:InvalidSwhid
Value Node: ex:InvalidSwhid
Result Path: None
Message: ExternalIdentifier must have a valid identifier for its externalIdentifierType.
----------------------------------------------------------------------------------------------------
Severity: sh:Violation
Source Shape: spdxcore:ExternalIdentifierStringByTypeShape
Focus Node: ex:InvalidCpe
Value Node: ex:InvalidCpe
Result Path: None
Message: ExternalIdentifier must have a valid identifier for its externalIdentifierType.
----------------------------------------------------------------------------------------------------
Severity: sh:Violation
Source Shape: spdxcore:ExternalIdentifierStringByTypeShape
Focus Node: ex:InvalidGitoid
Value Node: ex:InvalidGitoid
Result Path: None
Message: ExternalIdentifier must have a valid identifier for its externalIdentifierType.
----------------------------------------------------------------------------------------------------
Severity: sh:Violation
Source Shape: spdxcore:ExternalIdentifierStringByTypeShape
Focus Node: ex:InvalidEmail
Value Node: ex:InvalidEmail
Result Path: None
Message: ExternalIdentifier must have a valid identifier for its externalIdentifierType.
----------------------------------------------------------------------------------------------------
Found 5 SHACL violations!
Pattern sources:
- cpe22 and cpe23 (copied): https://github.com/CVEProject/cve-schema/blob/main/schema/CVE_Record_Format.json
- cve (copied): https://github.com/CVEProject/cve-schema/blob/main/schema/CVE_Record_Format.json
- gitoid (based on): https://www.iana.org/assignments/uri-schemes/prov/gitoid
- swhid (based on): https://www.swhid.org/specification/v1.1/4.Syntax/
- email: Constructed based on RFC 3696. The full spec allows for much more complex addresses, including quotes and comments. But I don't think anyone supports them and it would require a much more complex regex to validate it. BTW, this rule also validates the length of each of the parts in the address.
Why aren't CVSS identifiers includes?