spdx-3-model icon indicating copy to clipboard operation
spdx-3-model copied to clipboard

ExternalIdentifier based on its ExternalIdentifierType

Open ilans opened this issue 10 months ago • 2 comments

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!

ilans avatar Mar 06 '25 02:03 ilans

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.

ilans avatar Mar 06 '25 02:03 ilans

Why aren't CVSS identifiers includes?

ilans avatar Mar 06 '25 02:03 ilans