From 0cb32e8bcce499469a11ddf910173f913958adbd Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Fri, 9 May 2025 11:41:02 -0700 Subject: [PATCH 1/8] Add `artifactID`/`artifactType` to `affected` array The `affected` array is an array containing `product` objects, which must at minimum include an "identifier" (which may be a composite identifier composed of multiple fields) along with a set of version bounds or a default status. Products may also specify an assortment of additional fields which further constrain the applicability of the CVE to its intended target hardware or software. Previously, the set of identifiers available were: - A `vendor` and `product` - A `collectionURL` and `packageName` This commit adds support for a new pair of fields to support using OmniBOR Artifact IDs as identifiers in the `affected` array: - `artifactID`: The OmniBOR Artifact ID for an artifact. - `artifactType`: An enum indicating whether the `artifactID` is for an artifact to search in a file system for, or whether it's a build input to search against OmniBOR Input Manifests. The commit also adds data constraints to ensure this new identifier pair is not used alongside fields that don't make sense to use with OmniBOR, including the other identifier schemes, further decomposition information like `programFiles` or `programRoutines`, and version information. This work is submitted as an alternative formulation of the design proposed in the draft RFD on software identifiers [1], and as an alternative to the existing proposals for making the `cpeApplicability` structure generic [2] (instead of it being CPE-specific) and enhancing this new generic applicability structure with support for OmniBOR Artifact IDs [3]. If this change is accepted, then [2] and [3] should not be accepted. [1]: https://github.com/CVEProject/cve-schema/pull/407 [2]: https://github.com/CVEProject/cve-schema/pull/391 [3]: https://github.com/CVEProject/cve-schema/pull/396 Signed-off-by: Andrew Lilley Brinker --- schema/CVE_Record_Format.json | 40 ++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/schema/CVE_Record_Format.json b/schema/CVE_Record_Format.json index aaf5f5adb7c..f7940fbe2f7 100644 --- a/schema/CVE_Record_Format.json +++ b/schema/CVE_Record_Format.json @@ -110,7 +110,8 @@ { "anyOf": [ {"required": ["vendor", "product"]}, - {"required": ["collectionURL", "packageName"]} + {"required": ["collectionURL", "packageName"]}, + {"required": ["artifactID", "artifactType"]} ] }, { @@ -118,6 +119,28 @@ {"required": ["versions"]}, {"required": ["defaultStatus"]} ] + }, + { + "not": { + "allOf": [ + {"required": ["artifactID", "artifactType"]}, + { + "anyOf": [ + {"required": ["vendor"]}, + {"required": ["product"]}, + {"required": ["collectionURL"]}, + {"required": ["packageName"]}, + {"required": ["cpes"]}, + {"required": ["modules"]}, + {"required": ["programFiles"]}, + {"required": ["programRoutines"]}, + {"required": ["platforms"]}, + {"required": ["repo"]}, + {"required": ["versions"]} + ] + } + ] + } } ], "properties": { @@ -361,6 +384,21 @@ }, "additionalProperties": false } + }, + "artifactID": { + "type": "string", + "pattern": "^gitoid:blob:sha256:[0-9a-f]{64}$", + "description": "The OmniBOR Artifact ID of the artifact to be matched against.", + "examples": [ + "gitoid:blob:sha256:9f64df92367881be21e23567a31a8ce01994d98b69d28917b5c132ce32a8e6c8", + "gitoid:blob:sha256:09c825ac02df9150e4f93d12ba1da5d1ff5846c3e62503c814aa3a300c535772", + "gitoid:blob:sha256:230f3515d1306690815bd9c3da0d15d8b6fcf43894d17100eb44b6d329a92f61" + ] + }, + "artifactType": { + "type": "string", + "enum": ["artifact", "buildInput"], + "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'build_input' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." } } }, From 43f6221d8ea90887f85a7e2b495c85261e261436 Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Thu, 26 Jun 2025 14:21:23 -0700 Subject: [PATCH 2/8] feat: `artifactID` can't fulfill "identifier-like" Signed-off-by: Andrew Lilley Brinker --- schema/CVE_Record_Format.json | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/schema/CVE_Record_Format.json b/schema/CVE_Record_Format.json index f7940fbe2f7..4fe203e8d6f 100644 --- a/schema/CVE_Record_Format.json +++ b/schema/CVE_Record_Format.json @@ -110,8 +110,7 @@ { "anyOf": [ {"required": ["vendor", "product"]}, - {"required": ["collectionURL", "packageName"]}, - {"required": ["artifactID", "artifactType"]} + {"required": ["collectionURL", "packageName"]} ] }, { @@ -119,28 +118,6 @@ {"required": ["versions"]}, {"required": ["defaultStatus"]} ] - }, - { - "not": { - "allOf": [ - {"required": ["artifactID", "artifactType"]}, - { - "anyOf": [ - {"required": ["vendor"]}, - {"required": ["product"]}, - {"required": ["collectionURL"]}, - {"required": ["packageName"]}, - {"required": ["cpes"]}, - {"required": ["modules"]}, - {"required": ["programFiles"]}, - {"required": ["programRoutines"]}, - {"required": ["platforms"]}, - {"required": ["repo"]}, - {"required": ["versions"]} - ] - } - ] - } } ], "properties": { From 4f536a2518e7a4acc28c615798e49dc287169edd Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Thu, 26 Jun 2025 14:54:19 -0700 Subject: [PATCH 3/8] feat: Ensure `affected` has at least one coarse-grained ID Signed-off-by: Andrew Lilley Brinker --- schema/CVE_Record_Format.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/schema/CVE_Record_Format.json b/schema/CVE_Record_Format.json index 4fe203e8d6f..7bf031fb077 100644 --- a/schema/CVE_Record_Format.json +++ b/schema/CVE_Record_Format.json @@ -793,7 +793,13 @@ "type": "array", "description": "List of affected products.", "minItems": 1, - "items": {"$ref": "#/definitions/product"} + "items": {"$ref": "#/definitions/product"}, + "contains": { + "anyOf": [ + { "required": ["vendor", "product"] }, + { "required": ["collectionURL", "packageName"] } + ] + } }, "description": { "type": "object", From d5a9a1068fb6addb4d14190aaf3f6b856db5152e Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Thu, 17 Jul 2025 12:03:09 -0700 Subject: [PATCH 4/8] Add OmniBOR fields to cnaContainer advanced example Signed-off-by: Andrew Lilley Brinker --- schema/docs/cnaContainer-advanced-example.json | 7 +++++++ schema/docs/full-record-advanced-example.json | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/schema/docs/cnaContainer-advanced-example.json b/schema/docs/cnaContainer-advanced-example.json index bbafe4b2fbc..bed21a497c7 100644 --- a/schema/docs/cnaContainer-advanced-example.json +++ b/schema/docs/cnaContainer-advanced-example.json @@ -82,6 +82,13 @@ } ], "defaultStatus": "unaffected" + }, + { + "vendor": "Example.org", + "product": "Example Enterprise", + "artifactID": "gitoid:blob:sha256:fee53a18d32820613c0527aa79be5cb30173c823a9b448fa4817767cc84c6f03", + "artifactType": "artifact", + "defaultStatus": "affected" } ], "cpeApplicability": [ diff --git a/schema/docs/full-record-advanced-example.json b/schema/docs/full-record-advanced-example.json index c4722686c41..331a2ef3f87 100644 --- a/schema/docs/full-record-advanced-example.json +++ b/schema/docs/full-record-advanced-example.json @@ -95,6 +95,13 @@ } ], "defaultStatus": "unaffected" + }, + { + "vendor": "Example.org", + "product": "Example Enterprise", + "artifactID": "gitoid:blob:sha256:fee53a18d32820613c0527aa79be5cb30173c823a9b448fa4817767cc84c6f03", + "artifactType": "artifact", + "defaultStatus": "affected" } ], "cpeApplicability": [ @@ -162,7 +169,7 @@ "value": "OS-komand-injekta vundebleco parseFilename funkcio de example.php en la Web Administrado-Interfaco de Example.org Example Enterprise ĉe Windows, macOS kaj XT-4500 permesas al malproksimaj neaŭtentikigitaj atakantoj eskaladi privilegiojn.

Ĉi tiu afero efikas:
  • 1.0-versioj antaŭ 1.0.6
  • 2.1-versioj de 2.1.6 ĝis 2.1.9.
" } ] - } + } ], "metrics": [ { From b139cde0e2400b560f0acfcccc7f51e173ea539d Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Mon, 21 Jul 2025 11:36:23 -0700 Subject: [PATCH 5/8] feat: Update omnibor field names and constraints. Per QWG discussions on 7/10 and 7/17, this updates the names of the OmniBOR fields to use the word "omnibor" in them, and also updates the data constraints to ensure 1) that both OmniBOR fields are used together if used, and 2) that extra fields which do not make sense in the context of a fine-grained identifier are not mixed in. This also adds some descriptions and comments to make this part of the schema clearer to other contributors. Signed-off-by: Andrew Lilley Brinker --- schema/CVE_Record_Format.json | 39 ++++++- schema/docs/CVE_Record_Format_bundled.json | 103 +++++++++++++++++- ...VE_Record_Format_bundled_adpContainer.json | 103 +++++++++++++++++- ..._Format_bundled_cnaPublishedContainer.json | 103 +++++++++++++++++- ...d_Format_bundled_cnaRejectedContainer.json | 103 +++++++++++++++++- .../docs/cnaContainer-advanced-example.json | 4 +- schema/docs/full-record-advanced-example.json | 4 +- 7 files changed, 448 insertions(+), 11 deletions(-) diff --git a/schema/CVE_Record_Format.json b/schema/CVE_Record_Format.json index 7bf031fb077..f4d992e3354 100644 --- a/schema/CVE_Record_Format.json +++ b/schema/CVE_Record_Format.json @@ -108,16 +108,49 @@ "description": "Provides information about the set of products and services affected by this vulnerability.", "allOf": [ { + "description": "Require one 'identifier-like' set of fields", "anyOf": [ {"required": ["vendor", "product"]}, {"required": ["collectionURL", "packageName"]} ] }, { + "description": "Require one 'applicability' field", "anyOf": [ {"required": ["versions"]}, {"required": ["defaultStatus"]} ] + }, + { + "description": "If omniborArtifactID is used, require omniborArtifactType", + "dependentRequired": { + "omniborArtifactID": ["omniborArtifactType"] + } + }, + { + "description": "Disallow certain fields when used with a fine-grained identifier", + "not": { + "allOf": [ + { + "$comment": "The fine-grained identifier fields", + "anyOf": [ + {"required": ["omniborArtifactID"]} + ] + }, + { + "$comment": "Fields not to be used with fine-grained identifiers", + "anyOf": [ + {"required": ["cpes"]}, + {"required": ["modules"]}, + {"required": ["programFiles"]}, + {"required": ["programRoutines"]}, + {"required": ["platforms"]}, + {"required": ["repo"]}, + {"required": ["versions"]} + ] + } + ] + } } ], "properties": { @@ -278,7 +311,7 @@ "$ref": "#/definitions/uriType" }, "defaultStatus": { - "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both.", + "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both. When used alongside a fine-grained identifier such as omniborArtifactID, where no versions field will be used, defaultStatus is the status of the artifact identified by the identifier.", "$ref": "#/definitions/status" }, "versions": { @@ -362,7 +395,7 @@ "additionalProperties": false } }, - "artifactID": { + "omniborArtifactID": { "type": "string", "pattern": "^gitoid:blob:sha256:[0-9a-f]{64}$", "description": "The OmniBOR Artifact ID of the artifact to be matched against.", @@ -372,7 +405,7 @@ "gitoid:blob:sha256:230f3515d1306690815bd9c3da0d15d8b6fcf43894d17100eb44b6d329a92f61" ] }, - "artifactType": { + "omniborArtifactType": { "type": "string", "enum": ["artifact", "buildInput"], "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'build_input' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." diff --git a/schema/docs/CVE_Record_Format_bundled.json b/schema/docs/CVE_Record_Format_bundled.json index 5fff73a0131..e0308d2f8e1 100644 --- a/schema/docs/CVE_Record_Format_bundled.json +++ b/schema/docs/CVE_Record_Format_bundled.json @@ -138,6 +138,7 @@ "description": "Provides information about the set of products and services affected by this vulnerability.", "allOf": [ { + "description": "Require one 'identifier-like' set of fields", "anyOf": [ { "required": [ @@ -154,6 +155,7 @@ ] }, { + "description": "Require one 'applicability' field", "anyOf": [ { "required": [ @@ -166,6 +168,71 @@ ] } ] + }, + { + "description": "If omniborArtifactID is used, require omniborArtifactType", + "dependentRequired": { + "omniborArtifactID": [ + "omniborArtifactType" + ] + } + }, + { + "description": "Disallow certain fields when used with a fine-grained identifier", + "not": { + "allOf": [ + { + "$comment": "The fine-grained identifier fields", + "anyOf": [ + { + "required": [ + "omniborArtifactID" + ] + } + ] + }, + { + "$comment": "Fields not to be used with fine-grained identifiers", + "anyOf": [ + { + "required": [ + "cpes" + ] + }, + { + "required": [ + "modules" + ] + }, + { + "required": [ + "programFiles" + ] + }, + { + "required": [ + "programRoutines" + ] + }, + { + "required": [ + "platforms" + ] + }, + { + "required": [ + "repo" + ] + }, + { + "required": [ + "versions" + ] + } + ] + } + ] + } } ], "properties": { @@ -339,7 +406,7 @@ "$ref": "#/definitions/uriType" }, "defaultStatus": { - "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both.", + "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both. When used alongside a fine-grained identifier such as omniborArtifactID, where no versions field will be used, defaultStatus is the status of the artifact identified by the identifier.", "$ref": "#/definitions/status" }, "versions": { @@ -442,6 +509,24 @@ }, "additionalProperties": false } + }, + "omniborArtifactID": { + "type": "string", + "pattern": "^gitoid:blob:sha256:[0-9a-f]{64}$", + "description": "The OmniBOR Artifact ID of the artifact to be matched against.", + "examples": [ + "gitoid:blob:sha256:9f64df92367881be21e23567a31a8ce01994d98b69d28917b5c132ce32a8e6c8", + "gitoid:blob:sha256:09c825ac02df9150e4f93d12ba1da5d1ff5846c3e62503c814aa3a300c535772", + "gitoid:blob:sha256:230f3515d1306690815bd9c3da0d15d8b6fcf43894d17100eb44b6d329a92f61" + ] + }, + "omniborArtifactType": { + "type": "string", + "enum": [ + "artifact", + "buildInput" + ], + "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'build_input' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." } } }, @@ -866,6 +951,22 @@ "minItems": 1, "items": { "$ref": "#/definitions/product" + }, + "contains": { + "anyOf": [ + { + "required": [ + "vendor", + "product" + ] + }, + { + "required": [ + "collectionURL", + "packageName" + ] + } + ] } }, "description": { diff --git a/schema/docs/CVE_Record_Format_bundled_adpContainer.json b/schema/docs/CVE_Record_Format_bundled_adpContainer.json index 4a3b111577a..3e376170367 100644 --- a/schema/docs/CVE_Record_Format_bundled_adpContainer.json +++ b/schema/docs/CVE_Record_Format_bundled_adpContainer.json @@ -138,6 +138,7 @@ "description": "Provides information about the set of products and services affected by this vulnerability.", "allOf": [ { + "description": "Require one 'identifier-like' set of fields", "anyOf": [ { "required": [ @@ -154,6 +155,7 @@ ] }, { + "description": "Require one 'applicability' field", "anyOf": [ { "required": [ @@ -166,6 +168,71 @@ ] } ] + }, + { + "description": "If omniborArtifactID is used, require omniborArtifactType", + "dependentRequired": { + "omniborArtifactID": [ + "omniborArtifactType" + ] + } + }, + { + "description": "Disallow certain fields when used with a fine-grained identifier", + "not": { + "allOf": [ + { + "$comment": "The fine-grained identifier fields", + "anyOf": [ + { + "required": [ + "omniborArtifactID" + ] + } + ] + }, + { + "$comment": "Fields not to be used with fine-grained identifiers", + "anyOf": [ + { + "required": [ + "cpes" + ] + }, + { + "required": [ + "modules" + ] + }, + { + "required": [ + "programFiles" + ] + }, + { + "required": [ + "programRoutines" + ] + }, + { + "required": [ + "platforms" + ] + }, + { + "required": [ + "repo" + ] + }, + { + "required": [ + "versions" + ] + } + ] + } + ] + } } ], "properties": { @@ -339,7 +406,7 @@ "$ref": "#/definitions/uriType" }, "defaultStatus": { - "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both.", + "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both. When used alongside a fine-grained identifier such as omniborArtifactID, where no versions field will be used, defaultStatus is the status of the artifact identified by the identifier.", "$ref": "#/definitions/status" }, "versions": { @@ -442,6 +509,24 @@ }, "additionalProperties": false } + }, + "omniborArtifactID": { + "type": "string", + "pattern": "^gitoid:blob:sha256:[0-9a-f]{64}$", + "description": "The OmniBOR Artifact ID of the artifact to be matched against.", + "examples": [ + "gitoid:blob:sha256:9f64df92367881be21e23567a31a8ce01994d98b69d28917b5c132ce32a8e6c8", + "gitoid:blob:sha256:09c825ac02df9150e4f93d12ba1da5d1ff5846c3e62503c814aa3a300c535772", + "gitoid:blob:sha256:230f3515d1306690815bd9c3da0d15d8b6fcf43894d17100eb44b6d329a92f61" + ] + }, + "omniborArtifactType": { + "type": "string", + "enum": [ + "artifact", + "buildInput" + ], + "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'build_input' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." } } }, @@ -866,6 +951,22 @@ "minItems": 1, "items": { "$ref": "#/definitions/product" + }, + "contains": { + "anyOf": [ + { + "required": [ + "vendor", + "product" + ] + }, + { + "required": [ + "collectionURL", + "packageName" + ] + } + ] } }, "description": { diff --git a/schema/docs/CVE_Record_Format_bundled_cnaPublishedContainer.json b/schema/docs/CVE_Record_Format_bundled_cnaPublishedContainer.json index 6606fcb123b..0a822a011fd 100644 --- a/schema/docs/CVE_Record_Format_bundled_cnaPublishedContainer.json +++ b/schema/docs/CVE_Record_Format_bundled_cnaPublishedContainer.json @@ -138,6 +138,7 @@ "description": "Provides information about the set of products and services affected by this vulnerability.", "allOf": [ { + "description": "Require one 'identifier-like' set of fields", "anyOf": [ { "required": [ @@ -154,6 +155,7 @@ ] }, { + "description": "Require one 'applicability' field", "anyOf": [ { "required": [ @@ -166,6 +168,71 @@ ] } ] + }, + { + "description": "If omniborArtifactID is used, require omniborArtifactType", + "dependentRequired": { + "omniborArtifactID": [ + "omniborArtifactType" + ] + } + }, + { + "description": "Disallow certain fields when used with a fine-grained identifier", + "not": { + "allOf": [ + { + "$comment": "The fine-grained identifier fields", + "anyOf": [ + { + "required": [ + "omniborArtifactID" + ] + } + ] + }, + { + "$comment": "Fields not to be used with fine-grained identifiers", + "anyOf": [ + { + "required": [ + "cpes" + ] + }, + { + "required": [ + "modules" + ] + }, + { + "required": [ + "programFiles" + ] + }, + { + "required": [ + "programRoutines" + ] + }, + { + "required": [ + "platforms" + ] + }, + { + "required": [ + "repo" + ] + }, + { + "required": [ + "versions" + ] + } + ] + } + ] + } } ], "properties": { @@ -339,7 +406,7 @@ "$ref": "#/definitions/uriType" }, "defaultStatus": { - "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both.", + "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both. When used alongside a fine-grained identifier such as omniborArtifactID, where no versions field will be used, defaultStatus is the status of the artifact identified by the identifier.", "$ref": "#/definitions/status" }, "versions": { @@ -442,6 +509,24 @@ }, "additionalProperties": false } + }, + "omniborArtifactID": { + "type": "string", + "pattern": "^gitoid:blob:sha256:[0-9a-f]{64}$", + "description": "The OmniBOR Artifact ID of the artifact to be matched against.", + "examples": [ + "gitoid:blob:sha256:9f64df92367881be21e23567a31a8ce01994d98b69d28917b5c132ce32a8e6c8", + "gitoid:blob:sha256:09c825ac02df9150e4f93d12ba1da5d1ff5846c3e62503c814aa3a300c535772", + "gitoid:blob:sha256:230f3515d1306690815bd9c3da0d15d8b6fcf43894d17100eb44b6d329a92f61" + ] + }, + "omniborArtifactType": { + "type": "string", + "enum": [ + "artifact", + "buildInput" + ], + "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'build_input' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." } } }, @@ -866,6 +951,22 @@ "minItems": 1, "items": { "$ref": "#/definitions/product" + }, + "contains": { + "anyOf": [ + { + "required": [ + "vendor", + "product" + ] + }, + { + "required": [ + "collectionURL", + "packageName" + ] + } + ] } }, "description": { diff --git a/schema/docs/CVE_Record_Format_bundled_cnaRejectedContainer.json b/schema/docs/CVE_Record_Format_bundled_cnaRejectedContainer.json index bfb1d9e4760..3a88e946ac3 100644 --- a/schema/docs/CVE_Record_Format_bundled_cnaRejectedContainer.json +++ b/schema/docs/CVE_Record_Format_bundled_cnaRejectedContainer.json @@ -138,6 +138,7 @@ "description": "Provides information about the set of products and services affected by this vulnerability.", "allOf": [ { + "description": "Require one 'identifier-like' set of fields", "anyOf": [ { "required": [ @@ -154,6 +155,7 @@ ] }, { + "description": "Require one 'applicability' field", "anyOf": [ { "required": [ @@ -166,6 +168,71 @@ ] } ] + }, + { + "description": "If omniborArtifactID is used, require omniborArtifactType", + "dependentRequired": { + "omniborArtifactID": [ + "omniborArtifactType" + ] + } + }, + { + "description": "Disallow certain fields when used with a fine-grained identifier", + "not": { + "allOf": [ + { + "$comment": "The fine-grained identifier fields", + "anyOf": [ + { + "required": [ + "omniborArtifactID" + ] + } + ] + }, + { + "$comment": "Fields not to be used with fine-grained identifiers", + "anyOf": [ + { + "required": [ + "cpes" + ] + }, + { + "required": [ + "modules" + ] + }, + { + "required": [ + "programFiles" + ] + }, + { + "required": [ + "programRoutines" + ] + }, + { + "required": [ + "platforms" + ] + }, + { + "required": [ + "repo" + ] + }, + { + "required": [ + "versions" + ] + } + ] + } + ] + } } ], "properties": { @@ -339,7 +406,7 @@ "$ref": "#/definitions/uriType" }, "defaultStatus": { - "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both.", + "description": "The default status for versions that are not otherwise listed in the versions list. If not specified, defaultStatus defaults to 'unknown'. Versions or defaultStatus may be omitted, but not both. When used alongside a fine-grained identifier such as omniborArtifactID, where no versions field will be used, defaultStatus is the status of the artifact identified by the identifier.", "$ref": "#/definitions/status" }, "versions": { @@ -442,6 +509,24 @@ }, "additionalProperties": false } + }, + "omniborArtifactID": { + "type": "string", + "pattern": "^gitoid:blob:sha256:[0-9a-f]{64}$", + "description": "The OmniBOR Artifact ID of the artifact to be matched against.", + "examples": [ + "gitoid:blob:sha256:9f64df92367881be21e23567a31a8ce01994d98b69d28917b5c132ce32a8e6c8", + "gitoid:blob:sha256:09c825ac02df9150e4f93d12ba1da5d1ff5846c3e62503c814aa3a300c535772", + "gitoid:blob:sha256:230f3515d1306690815bd9c3da0d15d8b6fcf43894d17100eb44b6d329a92f61" + ] + }, + "omniborArtifactType": { + "type": "string", + "enum": [ + "artifact", + "buildInput" + ], + "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'build_input' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." } } }, @@ -866,6 +951,22 @@ "minItems": 1, "items": { "$ref": "#/definitions/product" + }, + "contains": { + "anyOf": [ + { + "required": [ + "vendor", + "product" + ] + }, + { + "required": [ + "collectionURL", + "packageName" + ] + } + ] } }, "description": { diff --git a/schema/docs/cnaContainer-advanced-example.json b/schema/docs/cnaContainer-advanced-example.json index bed21a497c7..2c9a2e1537b 100644 --- a/schema/docs/cnaContainer-advanced-example.json +++ b/schema/docs/cnaContainer-advanced-example.json @@ -86,8 +86,8 @@ { "vendor": "Example.org", "product": "Example Enterprise", - "artifactID": "gitoid:blob:sha256:fee53a18d32820613c0527aa79be5cb30173c823a9b448fa4817767cc84c6f03", - "artifactType": "artifact", + "omniborArtifactID": "gitoid:blob:sha256:fee53a18d32820613c0527aa79be5cb30173c823a9b448fa4817767cc84c6f03", + "omniborArtifactType": "artifact", "defaultStatus": "affected" } ], diff --git a/schema/docs/full-record-advanced-example.json b/schema/docs/full-record-advanced-example.json index 331a2ef3f87..f1f31500929 100644 --- a/schema/docs/full-record-advanced-example.json +++ b/schema/docs/full-record-advanced-example.json @@ -99,8 +99,8 @@ { "vendor": "Example.org", "product": "Example Enterprise", - "artifactID": "gitoid:blob:sha256:fee53a18d32820613c0527aa79be5cb30173c823a9b448fa4817767cc84c6f03", - "artifactType": "artifact", + "omniborArtifactID": "gitoid:blob:sha256:fee53a18d32820613c0527aa79be5cb30173c823a9b448fa4817767cc84c6f03", + "omniborArtifactType": "artifact", "defaultStatus": "affected" } ], From b532f24c4dbe289cf2f90c47d2052534f4d72540 Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Mon, 21 Jul 2025 12:01:05 -0700 Subject: [PATCH 6/8] fix: Use 'dependencies' instead of 'dependentRequired' The prior commit introduced a constraint using the field name 'dependentRequired', but the CVE Record Format is using an older form of the JSON Schema specification, where that field name is not used. This amends the schema to use the older "dependencies" constraint type, which behaves equivalently for our purposes. Signed-off-by: Andrew Lilley Brinker --- schema/CVE_Record_Format.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/schema/CVE_Record_Format.json b/schema/CVE_Record_Format.json index f4d992e3354..2811b876212 100644 --- a/schema/CVE_Record_Format.json +++ b/schema/CVE_Record_Format.json @@ -123,8 +123,9 @@ }, { "description": "If omniborArtifactID is used, require omniborArtifactType", - "dependentRequired": { - "omniborArtifactID": ["omniborArtifactType"] + "dependencies": { + "omniborArtifactID": ["omniborArtifactType"], + "omniborArtifactType": ["omniborArtifactID"] } }, { From 6fadd5807a1c292169fc2e7e0c2cbaf0918ed508 Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Thu, 24 Jul 2025 14:10:44 -0700 Subject: [PATCH 7/8] Permit "platforms" alongside "omniborArtifactID" This amends the data constraints on the "product" object inside the "affected" array, permitting the "platforms" field, which CNAs can use to indicate what platform an identified binary is intended to run on. Signed-off-by: Andrew Lilley Brinker --- schema/CVE_Record_Format.json | 1 - 1 file changed, 1 deletion(-) diff --git a/schema/CVE_Record_Format.json b/schema/CVE_Record_Format.json index 2811b876212..78ad9a95130 100644 --- a/schema/CVE_Record_Format.json +++ b/schema/CVE_Record_Format.json @@ -145,7 +145,6 @@ {"required": ["modules"]}, {"required": ["programFiles"]}, {"required": ["programRoutines"]}, - {"required": ["platforms"]}, {"required": ["repo"]}, {"required": ["versions"]} ] From 4b7dc227b8d97880270b9efbf679d69dafcb7b10 Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Mon, 4 Aug 2025 14:44:42 -0700 Subject: [PATCH 8/8] fix: typo in desc for `omniborArtifactType` Thanks Matt Power for identifying the oversight. Signed-off-by: Andrew Lilley Brinker --- schema/CVE_Record_Format.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schema/CVE_Record_Format.json b/schema/CVE_Record_Format.json index 78ad9a95130..2d1c4f84438 100644 --- a/schema/CVE_Record_Format.json +++ b/schema/CVE_Record_Format.json @@ -408,7 +408,7 @@ "omniborArtifactType": { "type": "string", "enum": ["artifact", "buildInput"], - "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'build_input' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." + "description": "Specifies how consumers of the Artifact ID should search for matches. If the 'target' is 'artifact', then the Artifact ID is identifying an artifact which should be searched for directly (for example, within a file system by matching against Artifact IDs for files). If the 'target' is 'buildInput' then the Artifact ID is identifying a build input, and consumers should match the Artifact ID against IDs found in OmniBOR Input Manifests for their software." } } },