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 ee489a8e..b5a9329e 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)
}
}
});