Skip to content

Commit 7667061

Browse files
authored
Merge pull request #35 from puerco/v0.2.0
OpenVEX Specification v0.2.0
2 parents d919792 + c240bfc commit 7667061

File tree

1 file changed

+190
-27
lines changed

1 file changed

+190
-27
lines changed

OPENVEX-SPEC.md

Lines changed: 190 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
# OpenVEX Specification v0.0.2
1+
# OpenVEX Specification v0.2.0
22

33
## Overview
44

55
OpenVEX is an implementation of Vulnerability Exploitability eXchange (VEX)
66
designed to be lightweight, and embeddable while meeting all requirements of
7-
a valid VEX implementation as defined in the [Minimum Requirements for VEX] document published on April 2023 as defined by the VEX Working Group coordinated by the [Cybersecurity & Infrastructure Security
8-
Agency](https://www.cisa.gov/) (CISA).
7+
a valid VEX implementation as defined in the [Minimum Requirements for VEX]
8+
document published on April 2023 as defined by the VEX Working Group coordinated
9+
by the [Cybersecurity & Infrastructure Security Agency](https://www.cisa.gov/) (CISA).
910

1011

1112
## The VEX Statement
@@ -110,8 +111,8 @@ expected to flow.
110111
#### Subcomponent
111112

112113
Any components possibly included in the product where the vulnerability originates.
113-
The subcomponents SHOULD also be software identifiers and they SHOULD also be
114-
listed in the product SBOM. subcomponents will most often be one or more of the
114+
The subcomponents SHOULD also list software identifiers and they SHOULD also be
115+
listed in the product SBOM. `subcomponents` will most often be one or more of the
115116
product's dependencies.
116117

117118
### Document
@@ -133,10 +134,12 @@ Here is a sample of a minimal OpenVEX document:
133134
"version": 1,
134135
"statements": [
135136
{
136-
"vulnerability": "CVE-2023-12345",
137+
"vulnerability": {
138+
"name": "CVE-2023-12345"
139+
},
137140
"products": [
138-
"pkg:apk/wolfi/git@2.39.0-r1?arch=armv7",
139-
"pkg:apk/wolfi/git@2.39.0-r1?arch=x86_64"
141+
{"@id": "pkg:apk/wolfi/git@2.39.0-r1?arch=armv7"},
142+
{"@id": "pkg:apk/wolfi/git@2.39.0-r1?arch=x86_64"}
140143
],
141144
"status": "fixed"
142145
}
@@ -172,10 +175,12 @@ A statement in an OpenVEX document looks like the following snippet:
172175
```json
173176
"statements": [
174177
{
175-
"vulnerability": "CVE-2023-12345",
178+
"vulnerability": {
179+
"name": "CVE-2023-12345"
180+
},
176181
"products": [
177-
"pkg:apk/wolfi/git@2.39.0-r1?arch=armv7",
178-
"pkg:apk/wolfi/git@2.39.0-r1?arch=x86_64"
182+
{"@id": "pkg:apk/wolfi/git@2.39.0-r1?arch=armv7"},
183+
{"@id": "pkg:apk/wolfi/git@2.39.0-r1?arch=x86_64"}
179184
],
180185
"status": "fixed"
181186
}
@@ -190,12 +195,10 @@ The following table lists the fields of the OpenVEX statement struct.
190195
| --- | --- | --- |
191196
| @id || Optional IRI identifying the statement to make it externally referenceable. |
192197
| version || Optional integer representing the statement's version number. Defaults to zero, required when incremented. |
193-
| vulnerability || Vulnerability SHOULD use existing and well known identifiers. For example: [CVE](https://cve.mitre.org/), [OSV](https://osv.dev/), [GHSA](https://github.com/advisories), a supplier's vulnerability tracking system such as [RHSA](https://access.redhat.com/security/security-updates/#/) or a propietary system. It is expected that vulnerability identification systems are external to and maintained separately from VEX.<br>`vulnerability` MAY be an IRI and MAY be arbitrary, created by the VEX document `author`. |
194-
| vuln_description || Optional free-form text describing the vulnerability |
198+
| vulnerability || A struct identifying the vulnerability. See the [Vulnerability Data Structure] section below for the complete data structure reference. |
195199
| timestamp || Timestamp is the time at which the information expressed in the Statement was known to be true. Cascades down from the document, see [Inheritance](#Inheritance). |
196200
| last_updated || Timestamp when the statement was last updated. |
197-
| products || Product identifiers that the statement applies to. Any software identifier can be used and SHOULD be traceable to a described item in an SBOM. The use of [Package URLs](https://github.com/package-url/purl-spec) (purls) is recommended. While a product identifier is required to have a complete statement, this field is optional as it can cascade down from the encapsulating document, see [Inheritance](#Inheritance). |
198-
| subcomponents || Identifiers of components where the vulnerability originates. While the statement asserts about the impact on the software product, listing `subcomponents` let scanners find identifiers to match their findings. |
201+
| products || List of product structs that the statement applies to. See the [Product Data Structure] section below for the full description. While a product is required to have a complete statement, this field is optional as it can cascade down from the encapsulating document, see [Inheritance](#Inheritance). |
199202
| status || A VEX statement MUST provide the status of the vulnerabilities with respect to the products and components listed in the statement. `status` MUST be one of the labels defined by VEX (see [Status](#Status-Labels)), some of which have further options and requirements. |
200203
| supplier || Supplier of the product or subcomponent. |
201204
| status_notes || A statement MAY convey information about how `status` was determined and MAY reference other VEX information. |
@@ -218,9 +221,11 @@ readable justification labels and optionally enrich the statement with an
218221

219222
```json
220223
{
221-
"vulnerability": "CVE-2023-12345",
224+
"vulnerability": {
225+
"name": "CVE-2023-12345",
226+
}
222227
"products": [
223-
"pkg:apk/wolfi/product@1.23.0-r1?arch=armv7",
228+
{"@id": "pkg:apk/wolfi/product@1.23.0-r1?arch=armv7"}
224229
],
225230
"status": "not_affected",
226231
"justification": "component_not_present",
@@ -229,6 +234,106 @@ readable justification labels and optionally enrich the statement with an
229234

230235
```
231236

237+
### Product Data Structure
238+
239+
The subject of an VEX statement is the _product_, a piece of software that MUST be
240+
addressable via one of the mechanisms offered by OpenVEX. The spec provides an
241+
expressive `product` struct with fields to address the product using identifiers,
242+
hashes. Note that all mechanisms to address the product are optional but a
243+
valid statement MUST identify a product to be valid.
244+
245+
The optional `@id` field takes an [IRI](#IRI) to make the product referenceable
246+
inside the document and addressable externally. As Package URLs are valid IRIs,
247+
the `@id` can take a purl as a value.
248+
249+
The product field should list as many software identifiers as possible to
250+
help VEX processors when matching the product. The use of
251+
[Package URLs](https://github.com/package-url/purl-spec) (purls) is recommended.
252+
253+
The product and its subcomponents fields share an abstract type called
254+
`Component` that defines the fields that can be used to identify them.
255+
The only difference in `product` is the nested `subcomponents` field.
256+
257+
#### Example Product Struct
258+
259+
```json
260+
{
261+
"@id": "pkg:apk/wolfi/product@1.23.0-r1?arch=armv7",
262+
"identifiers": {
263+
"purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.4",
264+
"cpe23": "cpe:2.3:a:apache:log4j:2.4:-:*:*:*:*:*:*",
265+
"cpe22": "cpe:/a:apache:log4j:2.4:-",
266+
},
267+
"hashes": {
268+
"sha-256": "402fa523b96591d4450ace90e32d9f779fcfd938903e1c5bf9d3701860b8f856",
269+
"sha-512": "d2eb65b083923d90cf55111c598f81d3d9c66f4457dfd173f01a6b7306f3b222541be42a35fe47191a9ca00e017533e8c07ca192bd22954e125557c72d2a3178"
270+
},
271+
"subcomponents": []
272+
}
273+
274+
```
275+
276+
277+
#### Component Fields
278+
279+
These fields are shared by both the `product` and `subcomponent` structs:
280+
281+
| Field | Required | Description |
282+
| --- | --- | --- |
283+
| @id || Optional [IRI](#IRI) identifying the component to make it externally referenceable. |
284+
| identifiers || A map of software identifiers where the key is the type and the value the identifier. OpenVEX favors the use of purl but others are recognized (see the Identifiers Labels table below) |
285+
| hashes || Map of cryptographic hashes of the component. The key is the algorithm name based on the [Hash Function Textual Names](https://www.iana.org/assignments/named-information/named-information.xhtml) from IANA. See [Hash Names Table] for the full supported list. |
286+
287+
The `product` struct uses the above listed fields but has a list of subcomponents,
288+
each itself a `component` subclass:
289+
290+
| Field | Required | Description |
291+
| --- | --- | --- |
292+
| subcomponents || List of `component` structs describing the subcomponents subject of the VEX statement. |
293+
294+
### Vulnerability Data Structure
295+
296+
The vulnerability field in an OpenVEX statement takes the value of a struct that
297+
has the capability to enumerate the vulnerability name and other aliases that may
298+
be used to track it in different databases and systems.
299+
300+
As with the product field, the vulberability has an optional "@id" field that
301+
takes an IRI to make the field referenceable in the document and linkable from
302+
other linked data resources.
303+
304+
#### Example Vulnerability Struct
305+
306+
```json
307+
{
308+
"vulnerability": {
309+
"@id": "https://nvd.nist.gov/vuln/detail/CVE-2019-17571",
310+
"name": "CVE-2019-17571",
311+
"description": "The product deserializes untrusted data without sufficiently verifying that the resulting data will be valid.",
312+
"aliases": [
313+
"GHSA-2qrg-x229-3v8q",
314+
"openSUSE-SU-2020:0051-1",
315+
"SNYK-RHEL7-LOG4J-1472071",
316+
"DSA-4686-1",
317+
"USN-4495",
318+
"DLA-2065-1",
319+
],
320+
}
321+
}
322+
```
323+
324+
#### Vulnerability Struct Fields
325+
326+
The only required field in the vulnerability field is `name`, the main identifier
327+
of the vulnerability. Note that it is not an error to include the identifier used
328+
in the `name` field in the list of aliases.
329+
330+
| Field | Required | Description |
331+
| --- | --- | --- |
332+
| @id || An Internationalized Resource Identifier (IRI) identifying the struct. Used to reference and link the vulnerability data. |
333+
| name || A string with the main identifier used to name the vulnerability. |
334+
| description || Optional free form text describing the vulnerability. |
335+
| aliases | x | A list of strings enumerating other names under which the vulnerability may be known. |
336+
232337
### Status Labels
233338

234339
Status labels inform the impact of a vulnerability in the products listed
@@ -338,9 +443,11 @@ example, the sole statement has its timestamp data derived from the document:
338443
"version": 1,
339444
"statements": [
340445
{
341-
"vulnerability": "CVE-2023-12345",
446+
"vulnerability": {
447+
"name": "CVE-2023-12345"
448+
},
342449
"products": [
343-
"pkg:apk/wolfi/git@2.39.0-r1?arch=armv7",
450+
{"@id": "pkg:apk/wolfi/git@2.39.0-r1?arch=armv7"}
344451
],
345452
"status": "under_investigation"
346453
}
@@ -364,16 +471,20 @@ to avoid duplication:
364471
"statements": [
365472
{
366473
"timestamp": "2023-01-08T18:02:03-06:00",
367-
"vulnerability": "CVE-2023-12345",
474+
"vulnerability": {
475+
"name": "CVE-2023-12345"
476+
},
368477
"products": [
369-
"pkg:apk/wolfi/git@2.39.0-r1?arch=armv7",
478+
{"@id": "pkg:apk/wolfi/git@2.39.0-r1?arch=armv7"},
370479
],
371480
"status": "under_investigation"
372481
},
373482
{
374-
"vulnerability": "CVE-2023-12345",
483+
"vulnerability": {
484+
"name": "CVE-2023-12345"
485+
},
375486
"products": [
376-
"pkg:apk/wolfi/git@2.39.0-r1?arch=armv7",
487+
{"@id": "pkg:apk/wolfi/git@2.39.0-r1?arch=armv7"}
377488
],
378489
"status": "fixed"
379490
},
@@ -403,7 +514,7 @@ processors.
403514

404515
### Public IRI Namespaces
405516

406-
As all documents are required to be identified by an IRI, open vex defines a
517+
As all documents are required to be identified by an IRI, OpenVEX defines a
407518
public namespace that can be used by documents. Users of OpenVEX MAY choose to
408519
use the shared namespace.
409520

@@ -420,7 +531,7 @@ There are two reserved shared namespaces with special meanings:
420531

421532
- `public` this is a public shared name where anybody that needs a valid IRI can
422533
issue identifiers. Only recommended for demos or experiments where name collisions
423-
don't matter.
534+
do not matter.
424535
- `example` a namespace for documentation, demos or other uses where no systems
425536
are expected to run.
426537

@@ -453,9 +564,24 @@ the project could issue an OpenVEX document as follows:
453564
"version": 1,
454565
"statements": [
455566
{
456-
"vulnerability": "CVE-2021-44228",
567+
"vulnerability": {
568+
"@id": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228",
569+
"name": "CVE-2021-44228",
570+
"description": "Remote code injection in Log4j",
571+
"aliases": [
572+
"GHSA-jfh8-c2jp-5v3q"
573+
]
574+
},
457575
"products": [
458-
"pkg:maven/org.springframework.boot/spring-boot@2.6.0"
576+
{
577+
"@id": "pkg:maven/org.springframework.boot/spring-boot@2.6.0-M3",
578+
"identifiers": {
579+
"purl": "pkg:maven/org.springframework.boot/spring-boot@2.6.0-M3",
580+
}
581+
"hashes":{
582+
"sha-256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
583+
}
584+
}
459585
],
460586
"status": "not_affected",
461587
"justification": "vulnerable_code_not_in_execute_path"
@@ -468,10 +594,46 @@ the project could issue an OpenVEX document as follows:
468594
VEX-enabled security scanners could use the vex document to turn off the security
469595
alert and dashboards could present users with the official guidance from the project.
470596

597+
## Appendix A: Hash Names Table
598+
599+
The following list of hash names can be used as keys in the `hashes` field of the
600+
product field. These labels follow and extend the
601+
[Hash Function Textual Names](https://www.iana.org/assignments/named-information/named-information.xhtml)
602+
document from IANA.
603+
604+
| Hash Label |
605+
| --- |
606+
| md5 |
607+
| sha1 |
608+
| sha-256 |
609+
| sha-384 |
610+
| sha-512 |
611+
| sha3-224 |
612+
| sha3-256 |
613+
| sha3-384 |
614+
| sha3-512 |
615+
| blake2s-256 |
616+
| blake2b-256 |
617+
| blake2b-512 |
618+
619+
## Appendix B: Software Identifier Types Table
620+
621+
The following labels can be used as keys when enumerating software identifiers
622+
in the product data structure.
623+
624+
| Type Label | Identifier type |
625+
| --- | --- |
626+
| purl | [Package URL](https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst) |
627+
| cpe22 | [Common Platform Enumeration v2.2](https://cpe.mitre.org/files/cpe-specification_2.2.pdf) |
628+
| cpe23 | [Common Platform Enumeration v2.3](https://csrc.nist.gov/pubs/ir/7695/final) |
629+
471630
## Revisions
472631

473632
| Date | Revision |
474633
| --- | --- |
634+
| 2023-07-18 | Added hash and identifier label catalog tables |
635+
| 2023-07-18 | Updated spec to reflect changes in [OPEV-0015: Expansion of the Vulnerability Field](https://github.com/openvex/community/blob/main/enhancements/opev-0015.md) |
636+
| 2023-07-18 | Updated spec to reflect changes in [OPEV-0014: Expansion of the VEX Product Field](https://github.com/openvex/community/blob/main/enhancements/opev-0014.md) |
475637
| 2023-07-18 | Bumped version of the spec to v0.0.2 after update to meet the VEX-WG doc. |
476638
| 2023-06-01 | Removed supplier from the document level (following VEX-WG doc). |
477639
| 2023-05-29 | Specification updated to reflect the published [Minimum Requirements for VEX] document. |
@@ -489,3 +651,4 @@ alert and dashboards could present users with the official guidance from the pro
489651

490652
[Status Justifications]: https://www.cisa.gov/sites/default/files/publications/VEX_Status_Justification_Jun22.pdf
491653
[Minimum Requirements for VEX]: https://www.cisa.gov/sites/default/files/2023-04/minimum-requirements-for-vex-508c.pdf
654+
[IRI]: https://www.ietf.org/rfc/rfc3987.txt

0 commit comments

Comments
 (0)