From a6888cd3012c6a8450184edbff1ca3ce50f68911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Prpi=C4=8D?= Date: Fri, 30 Aug 2024 14:59:20 -0400 Subject: [PATCH] Support multiple purl identifiers in product_identification_helper This allows a vendor to specify multiple purl identifiers for a single component (present as a product version branch in the product tree). Multiple purls may identify the same component but point to different locations from where that component may be available. Thus, it is mandatory that if multiple purls are present in a single product_identification_helper object, they must only differ in their qualifiers. Otherwise they should be set up as different product tree branches. --- csaf_2.1/json_schema/csaf_json_schema.json | 21 +++++--- csaf_2.1/prose/edit/etc/bind.txt | 1 + .../edit/etc/section-display-to-label.json | 2 +- .../edit/etc/section-label-to-display.json | 8 +-- csaf_2.1/prose/edit/src/guidance-on-size.md | 12 +++-- ...a-elements-01-defs-03-full-product-name.md | 16 +++--- .../prose/edit/src/tests-01-mndtr-13-purl.md | 10 ++-- .../src/tests-01-mndtr-38-purl-qualifiers.md | 51 +++++++++++++++++++ ...oasis_csaf_tc-csaf_2_1-2024-6-1-13-01.json | 6 ++- 9 files changed, 99 insertions(+), 28 deletions(-) create mode 100644 csaf_2.1/prose/edit/src/tests-01-mndtr-38-purl-qualifiers.md diff --git a/csaf_2.1/json_schema/csaf_json_schema.json b/csaf_2.1/json_schema/csaf_json_schema.json index ec1d90fa..7b160720 100644 --- a/csaf_2.1/json_schema/csaf_json_schema.json +++ b/csaf_2.1/json_schema/csaf_json_schema.json @@ -247,13 +247,20 @@ "minLength": 1 } }, - "purl": { - "title": "package URL representation", - "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\\.\\-\\+]*\\/.+", - "minLength": 7 + "purls": { + "title": "List of package URLs", + "description": "Contains a list of package URLs (purl).", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "title": "package URL representation", + "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\\.\\-\\+]*/.+", + "minLength": 7 + } }, "sbom_urls": { "title": "List of SBOM URLs", diff --git a/csaf_2.1/prose/edit/etc/bind.txt b/csaf_2.1/prose/edit/etc/bind.txt index 79e12724..458f4c31 100644 --- a/csaf_2.1/prose/edit/etc/bind.txt +++ b/csaf_2.1/prose/edit/etc/bind.txt @@ -67,6 +67,7 @@ tests-01-mndtr-33-multiple-flags-with-vex-justification-codes-per-product.md tests-01-mndtr-34-branches-recursion-depth.md tests-01-mndtr-35-contradicting-remediations.md tests-01-mndtr-36-contradicting-product-status-remediation-combination.md +tests-01-mndtr-38-tests-01-mndtr-38-purl-qualifiers.md tests-02-optional.md tests-03-informative.md distributing.md diff --git a/csaf_2.1/prose/edit/etc/section-display-to-label.json b/csaf_2.1/prose/edit/etc/section-display-to-label.json index e28c2a37..1633d1e4 100644 --- a/csaf_2.1/prose/edit/etc/section-display-to-label.json +++ b/csaf_2.1/prose/edit/etc/section-display-to-label.json @@ -30,7 +30,7 @@ "3.1.3.3.1": "full-product-name-type-product-identification-helper-cpe", "3.1.3.3.2": "full-product-name-type-product-identification-helper-hashes", "3.1.3.3.3": "full-product-name-type-product-identification-helper-model-numbers", - "3.1.3.3.4": "full-product-name-type-product-identification-helper-purl", + "3.1.3.3.4": "full-product-name-type-product-identification-helper-purls", "3.1.3.3.5": "full-product-name-type-product-identification-helper-sbom-urls", "3.1.3.3.6": "full-product-name-type-product-identification-helper-serial-numbers", "3.1.3.3.7": "full-product-name-type-product-identification-helper-skus", diff --git a/csaf_2.1/prose/edit/etc/section-label-to-display.json b/csaf_2.1/prose/edit/etc/section-label-to-display.json index 6a6e3918..345691b7 100644 --- a/csaf_2.1/prose/edit/etc/section-label-to-display.json +++ b/csaf_2.1/prose/edit/etc/section-label-to-display.json @@ -105,7 +105,7 @@ "full-product-name-type-product-identification-helper-generic-uris": "3.1.3.3.8", "full-product-name-type-product-identification-helper-hashes": "3.1.3.3.2", "full-product-name-type-product-identification-helper-model-numbers": "3.1.3.3.3", - "full-product-name-type-product-identification-helper-purl": "3.1.3.3.4", + "full-product-name-type-product-identification-helper-purls": "3.1.3.3.4", "full-product-name-type-product-identification-helper-sbom-urls": "3.1.3.3.5", "full-product-name-type-product-identification-helper-serial-numbers": "3.1.3.3.6", "full-product-name-type-product-identification-helper-skus": "3.1.3.3.7", @@ -256,9 +256,9 @@ "vulnerabilities-property-ids": "3.2.4.6", "vulnerabilities-property-involvements": "3.2.4.7", "vulnerabilities-property-metrics": "3.2.4.8", - "vulnerabilities-property-metrics-content": "3.2.4.8.1", - "vulnerabilities-property-metrics-products": "3.2.4.8.2", - "vulnerabilities-property-metrics-source": "3.2.4.8.3", + "vulnerabilities-property-metrics-content": "3.2.4.8.1", + "vulnerabilities-property-metrics-products": "3.2.4.8.2", + "vulnerabilities-property-metrics-source": "3.2.4.8.3", "vulnerabilities-property-notes": "3.2.4.9", "vulnerabilities-property-product-status": "3.2.4.10", "vulnerabilities-property-references": "3.2.4.11", diff --git a/csaf_2.1/prose/edit/src/guidance-on-size.md b/csaf_2.1/prose/edit/src/guidance-on-size.md index 8cfead21..20180061 100644 --- a/csaf_2.1/prose/edit/src/guidance-on-size.md +++ b/csaf_2.1/prose/edit/src/guidance-on-size.md @@ -59,18 +59,22 @@ An array SHOULD NOT have more than: * `/product_tree/branches[]/product/product_identification_helper/hashes[]/file_hashes` * `/product_tree/branches[]/product/product_identification_helper/sbom_urls` * `/product_tree/branches[]/product/product_identification_helper/x_generic_uris` + * `/product_tree/branches[]/product/product_identification_helper/purls` * `/product_tree/branches[](/branches[])*/product/product_identification_helper/hashes` * `/product_tree/branches[](/branches[])*/product/product_identification_helper/hashes[]/file_hashes` * `/product_tree/branches[](/branches[])*/product/product_identification_helper/sbom_urls` * `/product_tree/branches[](/branches[])*/product/product_identification_helper/x_generic_uris` + * `/product_tree/branches[](/branches[])*/product/product_identification_helper/purls` * `/product_tree/full_product_names[]/product_identification_helper/hashes` * `/product_tree/full_product_names[]/product_identification_helper/hashes[]/file_hashes` * `/product_tree/full_product_names[]/product_identification_helper/sbom_urls` * `/product_tree/full_product_names[]/product_identification_helper/x_generic_uris` + * `/product_tree/full_product_names[]/product_identification_helper/purls` * `/product_tree/relationships[]/full_product_name/product_identification_helper/hashes` * `/product_tree/relationships[]/full_product_name/product_identification_helper/hashes[]/file_hashes` * `/product_tree/relationships[]/full_product_name/product_identification_helper/sbom_urls` * `/product_tree/relationships[]/full_product_name/product_identification_helper/x_generic_uris` + * `/product_tree/relationships[]/full_product_name/product_identification_helper/purls[]` * `/vulnerabilities[]/acknowledgments` * `/vulnerabilities[]/acknowledgments[]/names` * `/vulnerabilities[]/acknowledgments[]/urls` @@ -228,14 +232,14 @@ A string SHOULD NOT have a length greater than: * `/document/references[]/summary` * `/document/tracking/revision_history[]/summary` * `/product_tree/branches[]/product/product_identification_helper/cpe` - * `/product_tree/branches[]/product/product_identification_helper/purl` + * `/product_tree/branches[]/product/product_identification_helper/purls[]` * `/product_tree/branches[](/branches[])*/product/product_identification_helper/cpe` - * `/product_tree/branches[](/branches[])*/product/product_identification_helper/purl` + * `/product_tree/branches[](/branches[])*/product/product_identification_helper/purls[]` * `/product_tree/full_product_names[]/product_identification_helper/cpe` - * `/product_tree/full_product_names[]/product_identification_helper/purl` + * `/product_tree/full_product_names[]/product_identification_helper/purls[]` * `/product_tree/product_groups[]/summary` * `/product_tree/relationships[]/full_product_name/product_identification_helper/cpe` - * `/product_tree/relationships[]/full_product_name/product_identification_helper/purl` + * `/product_tree/relationships[]/full_product_name/product_identification_helper/purls[]` * `/vulnerabilities[]/acknowledgments[]/summary` * `/vulnerabilities[]/involvements[]/summary` * `/vulnerabilities[]/references[]/summary` 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 170f46c4..8214f31d 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 @@ -41,7 +41,7 @@ Product ID (`product_id`) holds a value of type Product ID (`product_id_t`). Helper to identify the product (`product_identification_helper`) of value type `object` provides in its properties at least one method which aids in identifying the product in an asset database. -Of the given eight properties `cpe`, `hashes`, `model_numbers`, `purl`, `sbom_urls`, `serial_numbers`, `skus`, +Of the given eight properties `cpe`, `hashes`, `model_numbers`, `purls`, `sbom_urls`, `serial_numbers`, `skus`, and `x_generic_uris`, one is mandatory. ``` @@ -57,7 +57,7 @@ and `x_generic_uris`, one is mandatory. "model_numbers": { // ... }, - "purl": { + "purls": { // ... }, "sbom_urls": { @@ -240,9 +240,10 @@ Two `*` MUST NOT follow each other. IC25T060ATCS05-0 ``` -##### Full Product Name Type - Product Identification Helper - purl +##### Full Product Name Type - Product Identification Helper - purls -The package URL (purl) representation (`purl`) is a `string` of 7 or more characters with `pattern` (regular expression): +List of purls (`purls`) of value type `array` with 1 or more items contains a list of package URL (purl) identifiers. +A purl is a `string` of 7 or more characters that meets the criteria of `pattern` (regular expression): ``` ^pkg:[A-Za-z\\.\\-\\+][A-Za-z0-9\\.\\-\\+]*\\/.+ @@ -253,8 +254,11 @@ The package URL (purl) representation (`purl`) is a `string` of 7 or more charac > CSAF uses only the canonical form of purl to conform with section 3.3 of [cite](#RFC3986). > Therefore, URLs starting with `pkg://` are considered invalid. -This package URL (purl) attribute refers to a method for reliably identifying and locating software packages external to this specification. -See [cite](#PURL) for details. +A package URL (purl) attribute refers to a method for reliably identifying and locating software packages external to this specification. +See [cite](#PURL) for details. Multiple purls can be specified to allow for identifiers to locate identical components in different locations. + +If multiple purls are specified, they SHALL only differ in their qualifiers. Otherwise, separate product branches +should be used to differentiate between the components. ##### Full Product Name Type - Product Identification Helper - SBOM URLs diff --git a/csaf_2.1/prose/edit/src/tests-01-mndtr-13-purl.md b/csaf_2.1/prose/edit/src/tests-01-mndtr-13-purl.md index 79262fca..52dc37a9 100644 --- a/csaf_2.1/prose/edit/src/tests-01-mndtr-13-purl.md +++ b/csaf_2.1/prose/edit/src/tests-01-mndtr-13-purl.md @@ -5,9 +5,9 @@ It MUST be tested that given purl is valid. The relevant paths for this test are: ``` - /product_tree/branches[](/branches[])*/product/product_identification_helper/purl - /product_tree/full_product_names[]/product_identification_helper/purl - /product_tree/relationships[]/full_product_name/product_identification_helper/purl + /product_tree/branches[](/branches[])*/product/product_identification_helper/purls[] + /product_tree/full_product_names[]/product_identification_helper/purls[] + /product_tree/relationships[]/full_product_name/product_identification_helper/purls[] ``` *Example 1 (which fails the test):* @@ -19,7 +19,9 @@ The relevant paths for this test are: "name": "Product A", "product_id": "CSAFPID-9080700", "product_identification_helper": { - "purl": "pkg:maven/@1.3.4" + "purls": [ + "pkg:maven/@1.3.4" + ] } } ] diff --git a/csaf_2.1/prose/edit/src/tests-01-mndtr-38-purl-qualifiers.md b/csaf_2.1/prose/edit/src/tests-01-mndtr-38-purl-qualifiers.md new file mode 100644 index 00000000..1549175e --- /dev/null +++ b/csaf_2.1/prose/edit/src/tests-01-mndtr-38-purl-qualifiers.md @@ -0,0 +1,51 @@ +### PURL Qualifiers + +It MUST be tested that when multiple purls are used in a single `product_identification_helper` object, they only +differ in their qualifiers. + +The relevant paths for this test are: + +``` + /product_tree/branches[](/branches[])*/product/product_identification_helper/purls[] + /product_tree/full_product_names[]/product_identification_helper/purls[] + /product_tree/relationships[]/full_product_name/product_identification_helper/purls[] +``` + +*Example 1 (which fails the test):* + +``` + "product_tree": { + "full_product_names": [ + { + "name": "Product A", + "product_id": "CSAFPID-9080700", + "product_identification_helper": { + "purls": [ + "pkg:maven/org.example.blue/logging@1.3.4", + "pkg:maven/org.example.blue/audit@1.3.4" + ] + } + } + ] + } +``` +> The two purls differ in the name component. + +*Example 2 (which passes the test):* + +``` + "product_tree": { + "full_product_names": [ + { + "name": "Product A", + "product_id": "CSAFPID-9080700", + "product_identification_helper": { + "purls": [ + "pkg:maven/org.example.blue/logging@1.3.4?repository_url=https://registry.example.org", + "pkg:maven/org.example.blue/logging@1.3.4?repository_url=https://index.example.org" + ] + } + } + ] + } +``` diff --git a/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-13-01.json b/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-13-01.json index 9f6892ca..6170c853 100644 --- a/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-13-01.json +++ b/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-13-01.json @@ -35,9 +35,11 @@ "name": "Product A", "product_id": "CSAFPID-9080700", "product_identification_helper": { - "purl": "pkg:maven/@1.3.4" + "purls": [ + "pkg:maven/@1.3.4" + ] } } ] } -} \ No newline at end of file +}