diff --git a/.github/workflows/csaf_2.1_cpe.yml b/.github/workflows/csaf_2.1_cpe.yml index c9fcf423..f5ca85f2 100644 --- a/.github/workflows/csaf_2.1_cpe.yml +++ b/.github/workflows/csaf_2.1_cpe.yml @@ -19,4 +19,6 @@ jobs: with: node-version: '20' - name: Perform CPE Dictionary Test - run: ./csaf_2.1/test/cpe/run_tests.sh + run: ./csaf_2.1/test/cpe/run_dictionary_tests.sh + - name: Perform CPE local examples Test + run: ./csaf_2.1/test/cpe/run_local_tests.sh diff --git a/csaf_2.1/json_schema/csaf_json_schema.json b/csaf_2.1/json_schema/csaf_json_schema.json index 1c42ccb5..b3888b31 100644 --- a/csaf_2.1/json_schema/csaf_json_schema.json +++ b/csaf_2.1/json_schema/csaf_json_schema.json @@ -159,7 +159,7 @@ "title": "Common Platform Enumeration representation", "description": "The Common Platform Enumeration (CPE) attribute refers to a method for naming platforms external to this specification.", "type": "string", - "pattern": "^(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})|([c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6})$", + "pattern": "^((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})|([c][pP][eE]:\\/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6}))$", "minLength": 5 }, "hashes": { @@ -251,7 +251,7 @@ "description": "The package URL (purl) attribute refers to a method for reliably identifying and locating software packages external to this specification.", "type": "string", "format": "uri", - "pattern": "^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*/.+", + "pattern": "^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*\\/.+", "minLength": 7 }, "sbom_urls": { diff --git a/csaf_2.1/prose/edit/src/conformance.md b/csaf_2.1/prose/edit/src/conformance.md index 38d6e639..cf2df483 100644 --- a/csaf_2.1/prose/edit/src/conformance.md +++ b/csaf_2.1/prose/edit/src/conformance.md @@ -502,7 +502,12 @@ Firstly, the program: Secondly, the program fulfills the following for all items of: +* type `/$defs/full_product_name_t/cpe`: If a CPE is invalid, the CSAF 2.0 to CSAF 2.1 converter SHOULD removed the invalid value and output a + warning that an invalid CPE was detected and removed. Such a warning MUST include the invalid CPE. > A tool MAY implement options to convert other Markdown formats to GitHub-flavoured Markdown. +> A tool MAY implement an additional, non-default option to output an invalid document that can be fixed afterwards. Solely in this case, any +> of the rules above MAY be ignored to avoid data loss. + ------- diff --git a/csaf_2.1/prose/edit/src/schema-elements-01-defs-03-full-product-name.md b/csaf_2.1/prose/edit/src/schema-elements-01-defs-03-full-product-name.md index 59690c97..9271d6b0 100644 --- a/csaf_2.1/prose/edit/src/schema-elements-01-defs-03-full-product-name.md +++ b/csaf_2.1/prose/edit/src/schema-elements-01-defs-03-full-product-name.md @@ -80,7 +80,7 @@ and `x_generic_uris`, one is mandatory. Common Platform Enumeration representation (`cpe`) of value type `string` of 5 or more characters with `pattern` (regular expression): ``` - ^(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})|([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})|([c][pP][eE]:\\/[AHOaho]?(:[A-Za-z0-9\\._\\-~%]*){0,6}))$ ``` The Common Platform Enumeration (CPE) attribute refers to a method for naming platforms external to this specification. @@ -243,7 +243,7 @@ Two `*` MUST NOT follow each other. The package URL (PURL) representation (`purl`) is a `string` of 7 or more characters with `pattern` (regular expression): ``` - ^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*/.+ + ^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*\\/.+ ``` > The given pattern does not completely evaluate whether a PURL is valid according to the [cite](#PURL) specification. diff --git a/csaf_2.1/test/cpe/data/invalid/cpe.txt b/csaf_2.1/test/cpe/data/invalid/cpe.txt new file mode 100644 index 00000000..f48cc39a --- /dev/null +++ b/csaf_2.1/test/cpe/data/invalid/cpe.txt @@ -0,0 +1,5 @@ +PREFIXcpe:/o:redhat:rhel_aus:7.6::server +cpe:/o:redhat:rhel_aus:7.6::server::SUFFIX +PREFIXcpe:2.3:a:admin_management_xtended_project:admin_management_xtended:0.8:*:*:*:*:wordpress:*:* +cpe:2.3:a:admin_management_xtended_project:admin_management_xtended:0.8:*:*:*:*:wordpress:*:*" +cpe:2.3:a:admin_management_xtended_project:admin_management_xtended:0.8:*:*:*:*:wordpress:*:** diff --git a/csaf_2.1/test/cpe/data/valid/cpe.txt b/csaf_2.1/test/cpe/data/valid/cpe.txt new file mode 100644 index 00000000..9a5d7be9 --- /dev/null +++ b/csaf_2.1/test/cpe/data/valid/cpe.txt @@ -0,0 +1,3 @@ +cpe:2.3:a:admin_management_xtended_project:admin_management_xtended:0.8:*:*:*:*:wordpress:*:*other* +cpe:2.3:a:admin_management_xtended_project:admin_management_xtended:0.8:*:*:*:*:wordpress:*:*other???? +cpe:/o:redhat:rhel_aus:7.6::server diff --git a/csaf_2.1/test/cpe/run_tests.sh b/csaf_2.1/test/cpe/run_dictionary_tests.sh similarity index 96% rename from csaf_2.1/test/cpe/run_tests.sh rename to csaf_2.1/test/cpe/run_dictionary_tests.sh index 8c6b7345..a8a84847 100755 --- a/csaf_2.1/test/cpe/run_tests.sh +++ b/csaf_2.1/test/cpe/run_dictionary_tests.sh @@ -20,7 +20,7 @@ get_dictionary() { prepare_23_dictionary() { # Get CPE 2.3 fields # Correctly decode special characters - grep '$//' \ + grep '$//' \ | sed -e 's/\\&/\\\&/g' \ | sed -e 's/\\"/\\"/g' \ > "$CPE".txt diff --git a/csaf_2.1/test/cpe/run_local_tests.sh b/csaf_2.1/test/cpe/run_local_tests.sh new file mode 100755 index 00000000..38f22480 --- /dev/null +++ b/csaf_2.1/test/cpe/run_local_tests.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +SCHEMA=csaf_2.1/json_schema/csaf_json_schema.json +VALIDATOR=csaf_2.1/test/cpe/test-regex.js +DATA_VALID=csaf_2.1/test/cpe/data/valid/cpe.txt +DATA_INVALID=csaf_2.1/test/cpe/data/invalid/cpe.txt + +FAIL=0 + +# go to root of git repository +cd "$(dirname "$0")"/../../.. || exit + + +validate() { + printf "Testing file %s against cpe regex from %s ... \n" "$1" "$SCHEMA" + if node "$VALIDATOR" "$SCHEMA" "$1" "$2"; then + printf "SUCCESS\n" + else + printf "FAILED\n" + FAIL=1 + fi + +} + +echo -n "Test conforming (not necessary existing) CPEs... " +DATA=$DATA_VALID +validate $DATA true +printf "done\n" + +echo -n "Test non-conforming CPEs... " +DATA=$DATA_INVALID +validate $DATA false +printf "done\n" + + +exit $FAIL diff --git a/csaf_2.1/test/cpe/test-regex.js b/csaf_2.1/test/cpe/test-regex.js index 567ba08e..98e4d2f9 100644 --- a/csaf_2.1/test/cpe/test-regex.js +++ b/csaf_2.1/test/cpe/test-regex.js @@ -10,15 +10,16 @@ const r = new RegExp(pattern) console.log('Current regex to test:', '\n', pattern) const cpeStr = fs.readFileSync(args[1], 'utf8').split('\n') +const assertion = !((args[2] ?? true) === "false") let failed = false cpeStr.forEach(element => { if (element.length > 0) { const result = (r.exec(element) != null) - failed = failed | !result - if (!result) { - console.log(result, '\t', element) + failed = failed | (result !== assertion) + if (result !== assertion) { + console.log(result,'but expected', assertion, '\t', element) } } });