encoding.vex

Vulnerabilities Exploitability Exchange specifications.

This specification package is based on https://www.cisa.gov/sites/default/files/2023-04/minimum-requirements-for-vex-508c.pdf.

The document https://www.cisa.gov/sites/default/files/2023-01/VEX_Use_Cases_Aprill2022.pdf has also been used for a better understanding of some VEX implementations.

Module Contents

Classes

ActionOrImpact

An object to represent an action or impact for a statement status.

AuthorRole

Role of the document author.

Document

Vulnerabilities Exploitability Exchange document.

Justification

Justification for a statement status.

Metadata

VEX metadata.

Product

Product details.

ProductId

VEX statement product identifier.

ProductStatus

Status information about a vulnerability in that product.

Statement

VEX statement.

StatementMetadata

Metadata for a VEX statement.

StatementStatus

Statement status.

SubProductId

Sub-product ID.

Vulnerability

Statement vulnerability details.

class encoding.vex.ActionOrImpact(statement: str | None = None, timestamp: datetime.datetime | None = None)

Bases: e3.json.JsonData

An object to represent an action or impact for a statement status.

For status Status.NOT_AFFECTED, if justification is not provided, then a VEX statement MUST provide an impact_statement that further explains how or why the listed product_id s are not affected by vul_id.

If justification is provided, then a VEX statement MAY provide an impact_statement.

Variables:
  • statement (str | None) – The statement of this action or impact.

  • timestamp (datetime | None) – The time at which the statement has been last modified.

__bool__() bool

Check if this action or impact is defined.

An action or impact without a statement is considered as False.

Returns:

True if this action or impact has a statement defined to something else that None, False else.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) ActionOrImpact

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

class encoding.vex.AuthorRole(*args, **kwds)

Bases: enum.Enum

Role of the document author.

The author role MAY specify the role of the author.

The author role MAY use the category of publisher roles defined by CSAF 2.0:

Variables:
  • COORDINATOR – indicates individuals or organizations that manage a single vendor’s response or multiple vendors’ responses to a vulnerability, a security flaw, or an incident. This includes all Computer Emergency/Incident Response Teams (CERTs/CIRTs) or agents acting on the behalf of a researcher.

  • DISCOVERER – indicates individuals or organizations that find vulnerabilities or security weaknesses. This includes all manner of researchers.

  • TRANSLATOR – indicates individuals or organizations that translate VEX documents. This includes all manner of language translators, also those who work for the party issuing the original advisory.

  • OTHER – indicates a catchall for everyone else. Currently, this includes editors, reviewers, forwarders, republishers, and miscellaneous contributors.

  • USER – indicates anyone using a vendor’s product.

  • VENDOR – indicates developers or maintainers of information system products or services. This includes all authoritative product vendors, Product Security Incident Response Teams (PSIRTs), and product resellers and distributors, including authoritative vendor partners.

COORDINATOR = 'coordinator'
DISCOVERER = 'discoverer'
OTHER = 'other'
TRANSLATOR = 'translator'
USER = 'user'
VENDOR = 'vendor'
classmethod from_value(value: str | AuthorRole | None, default: AuthorRole | str = OTHER) AuthorRole

Create an author role enum from a given value.

Returns:

An author role enum set according to value and default.

Raise:

python:ValueError If value is not one of the possible values of this enumerate, or if default has an invalid value and value is None.

class encoding.vex.Document(metadata: Metadata, statements: list[Statement] | None = None)

Bases: e3.json.JsonData

Vulnerabilities Exploitability Exchange document.

A VEX document is a binding of product information, vulnerability information, and the relevant status details relating them.

Minimum data elements of a VEX document must include the VEX metadata, product details, vulnerability details, and product status.

Variables:
  • metadata (Metadata) – VEX metadata.

  • statements (list[Statement]) – The list of statements defined for this VEX document.

FORMAT_JSON: str = 'json'
FORMAT_YAML: str = 'yaml'
FORMATS: tuple = ()
add_statement(new_statement: Statement) None

Add a new statement to this VEX document.

If statement has an _id set to None, the value of the statement _id is updated to <document id>/<statement vuln id>.

Parameters:

new_statement – The statement to add to this VEX document.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) Document

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

classmethod from_file(path: pathlib.Path) Document

Create a VEX document from a file content.

The function yaml.safe_load() is used to read the file. If the file content is JSON, the YAML loader handles it safely and extracts data anyway.

Parameters:

path – The path of a VEX document to initialise this document with.

save(path: pathlib.Path, output_format: str = FORMAT_JSON) None

Save this document to a file with the given format.

Parameters:
  • path – The path of the saved file.

  • output_format – The file format. May be any of FORMATS.

Raise:

python:ValueError If output_format is not one of the possible FORMATS.

statement(cve_id: str) Statement | None

Get the statement for given CVE ID.

If this document does not contain any statement defining a vulnerability which ID is cve_id, None is returned.

Parameters:

cve_id – The ID of the CVE to retrieve in the statements of this document.

Returns:

A Statement object which defines the vulnerability cve_id, or None if such a statement does not exist in this document.

class encoding.vex.Justification(*args, **kwds)

Bases: enum.Enum

Justification for a statement status.

For status Status.NOT_AFFECTED, a VEX statement SHOULD provide justification.

If justification is not provided then impact_statement MUST be provided.

Variables:
  • COMPONENT_NOT_PRESENT (str) – The vulnerable subcomponent_id is not included in product_id.

  • INLINE_MITIGATIONS_ALREADY_EXIST (str) – product_id includes built-in protections or features that prevent exploitation of the vulnerability. These built-in protections cannot be subverted by the attacker and cannot be configured or disabled by the user. These mitigations completely prevent exploitation based on known attack vectors.

  • NO_JUSTIFICATION (str) – Use to state that there is no justification set yet.

  • VULNERABLE_CODE_CANNOT_BE_CONTROLLED_BY_ADVERSARY (str) – The vulnerable code is present and used by product_id but cannot be controlled by an attacker to exploit the vulnerability.

  • VULNERABLE_CODE_NOT_IN_EXECUTE_PATH (str) – The vulnerable code (likely in subcomponent_id) cannot be executed due to the way it is used by product_id. Typically, this case occurs when product_id includes the vulnerable code but does not call or otherwise use it.

  • VULNERABLE_CODE_NOT_PRESENT (str) – The vulnerable subcomponent_id is included in product_id but the vulnerable code is not present. Typically, this case occurs when source code is configured or built in a way that excludes the vulnerable code.

COMPONENT_NOT_PRESENT = 'Component not present'
INLINE_MITIGATIONS_ALREADY_EXIST = 'Inline mitigations already exist'
VULNERABLE_CODE_CANNOT_BE_CONTROLLED_BY_ADVERSARY = 'Vulnerable code cannot be controlled by adversary'
VULNERABLE_CODE_NOT_IN_EXECUTE_PATH = 'Vulnerable code not in execute path'
VULNERABLE_CODE_NOT_PRESENT = 'Vulnerable code not present'
NO_JUSTIFICATION = 'No justification'
__bool__() bool

Check if this justification is defined.

Returns:

False only if justification is set to Justification.NO_JUSTIFICATION, else True is returned.

classmethod from_value(value: str | Justification | None, default: Justification | str = NO_JUSTIFICATION) Justification

Create a justification enum from a given value.

Returns:

A justification enum set according to value and default.

Raise:

python:ValueError If value is not one of the possible values of this enumerate, or if default has an invalid value and value is None.

class encoding.vex.Metadata(author: str = AUTHOR, author_role: AuthorRole | str = AUTHOR_ROLE, tooling: str | None = None, version: int = VERSION, _id: str | None = None, created_on: datetime.datetime | None = None, last_updated_on: datetime.datetime | None = None, spec_version: str = SPEC_VERSION)

Bases: e3.json.JsonData

VEX metadata.

To the greatest extent possible, VEX metadata is defined and maintained at the VEX document level.

When appropriate and necessary, VEX metadata is defined at the VEX statement level.

VEX document metadata MAY be synthesized or derived from VEX statement metadata; for example, doc_time_last_updated MUST be at least as recent as the newest statement_time_last_updated.

VEX document metadata MUST accurately apply to all contained VEX statements.

Must include: VEX Format Identifier, Identifier string for the VEX document, Author, Author role, Timestamp.

Variables:
  • author (str) – The author of the VEX document. The author is responsible for the content of the VEX document. A VEX document MUST identify the author. To describe tools or other mechanisms used to generate VEX content, consider tooling.

  • author_role (AuthorRole) – The role of the other of this document. See AuthorRole.

  • tooling (str | None) – Document tooling MAY specify tools or automated mechanisms that generate VEX documents, VEX statements, or other VEX information. Contrast with author.

  • version (int) – The version of a VEX document.

  • _id (str) – The ID of a VEX document.

  • created_on (datetime) – The time this VEX document was created at.

  • last_updated_on (datetime) – The time this VEX document was updated.

  • spec_version (str) – The VEX requirements version used by the parent document. By default, it is set to SPEC_VERSION.

AUTHOR: str = 'AdaCore'
AUTHOR_ROLE: AuthorRole
SPEC_VERSION: str = '1.0.0'
VERSION: int = 1
as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) Metadata

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

class encoding.vex.Product(products: list[ProductId], supplier: str, subcomponents: list[SubProductId] | None = None)

Bases: e3.json.JsonData

Product details.

Variables:
  • products (list[ProductID]) – Product details MUST include one or more product_id and MAY include one or more subcomponent_id.

  • supplier (str) –

    Product details SHOULD identify the supplier of product_id or subcomponent_id. supplier MUST clearly indicate the product_id or subcomponent_id to which supplier applies. For example:

    • [supplier]/[product_id]

    • [supplier]/[subcomponent_id]

  • subcomponents (list[ProductId] | None) –

    A VEX statement MAY include one or more identifiers for subcomponents associated with vulnerability details.

    A VEX statement asserts the status of product_id with respect to vul_id. A VEX statement MAY also convey that subcomponent_id is included in product_id. A common VEX use case is to convey that subcomponent_id is affected by vul_id while product_id is not_affected by vul_id.

    subcomponent_id MAY be derived from product_id, particularly if product_id is associated with SBOM or other references that convey dependencies.

    subcomponent_id MAY be derived from vul_id or vul_description.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) Product

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

subcomponent(_id: str, version: str) SubProductId | None

Get a subcomponent with given ID if any.

Parameters:
  • _id – The ID of the subcomponent to look for.

  • version – The version of the subcomponent to look for.

Returns:

A matching subcomponent ID, or None if no such subcomponent could be found.

class encoding.vex.ProductId(_id: str, version: str)

Bases: e3.json.JsonData

VEX statement product identifier.

The specifications say:

product_id MUST identify the product or component that vul_id and status applies to.

product_id MAY specify a set of products or components and MUST specify at least one of:

  • subcomponent_id

  • A component (often a subcomponent of a product)

  • A product, for example, a final good assembled

  • A set of products or components, for example, a product line or family

  • A supplier (indicating the set of all products or components from the supplier)

Variables:
  • _id (str) – The ID of the product.

  • version (str) – Version, or version range of the product.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

class encoding.vex.ProductStatus(*args, **kwds)

Bases: enum.Enum

Status information about a vulnerability in that product.

Variables:
  • NOT_AFFECTED – No remediation is required regarding this vulnerability.

  • AFFECTED – Actions are recommended to remediate or address this vulnerability.

  • FIXED – These product versions contain a fix for the vulnerability.

  • UNDER_INVESTIGATION – It is not yet known whether these product versions are affected by the vulnerability. An update will be provided in a later release.

NOT_AFFECTED = 'Not affected'
AFFECTED = 'Affected'
FIXED = 'Fixed'
UNDER_INVESTIGATION = 'Under investigation'
classmethod from_value(value: str | ProductStatus | None, default: ProductStatus | str = UNDER_INVESTIGATION) ProductStatus

Create a product status enum from a given value.

Returns:

A product status enum set according to value and default.

Raise:

python:ValueError If value is not one of the possible values of this enumerate, or if default has an invalid value and value is None.

class encoding.vex.Statement(metadata: StatementMetadata, status: StatementStatus, vulnerability: Vulnerability, product: Product)

Bases: e3.json.JsonData

VEX statement.

A VEX statement is a declaration that MUST convey a single status that applies to a single vul_id for one or more product_id s.

A VEX statement MUST be logically contained within a VEX document.

A VEX statement MUST exist only within one VEX document, that is, VEX statements are logically local to their containing VEX document.

Variables:
  • metadata (Metadata) – The metadata defining this VEX statement.

  • status (Status) – The status of this VEX statement.

  • vulnerability (Vulnerability) – The details of the unique vulnerability defined for this VEX statement.

  • product (Product) – The details of the products for the given vulnerability of this VEX statement.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) Statement

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

class encoding.vex.StatementMetadata(version: int | None = None, _id: str | None = None, first_issued_on: datetime.datetime | None = None, last_updated_on: datetime.datetime | None = None)

Bases: e3.json.JsonData

Metadata for a VEX statement.

To the extent possible, VEX metadata is stored in VEX documents. Certain metadata is specific to VEX statements.

Variables:
  • version (int) –

    indicates the version of the VEX statement.

    • A VEX statement MUST provide one version.

    • version MUST clearly convey positive incremental change.

    • version MUST be incremented when any content within the VEX statement changes.

    • version MAY be derived from or otherwise be related to document_version.

  • _id (str | None) –

    _id uniquely identifies a VEX statement within a VEX document.

    • A VEX statement MUST be able to be specifically referenced within a VEX document.

    • A VEX statement SHOULD provide one _id.

    • _id SHOULD be created within the author and doc_id namespaces and MAY be generated from other VEX information, for example, author/doc_id/statement_id.

    • _id MAY minimally be an index of VEX statements within the scope of doc_id.

  • first_issued_on (datetime) –

    A VEX statement MUST provide the date and time that the VEX statement was first issued.

    • first_issued_on MAY be derived from or otherwise related to doc_time_first_issued.

    • first_issued_on MAY be derived from or otherwise related to impact_statement_time or action_statement_time.

  • last_updated_on (datetime) –

    A VEX statement MUST provide the date and time that the VEX statement was last modified.

    • last_updated_on MUST initially be equivalent to first_issued_on.

    • last_updated_on MAY be derived from or otherwise related to impact_statement_time or action_statement_time.

    • last_updated_on MUST be equivalent to or newer than the most recent impact_statement_time or action_statement_time.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) StatementMetadata

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

class encoding.vex.StatementStatus(status: ProductStatus | str | None = ProductStatus.UNDER_INVESTIGATION, impact: ActionOrImpact | None = None, justification: Justification | str | None = Justification.NO_JUSTIFICATION, action: ActionOrImpact | None = None, notes: str | None = None)

Bases: e3.json.JsonData

Statement status.

A VEX statement MUST provide one status that applies to all contained product_id s with respect to vul_id.

The statement status is made of a product status (not affected,fixed …), and impact depending on the status and justification.

For affected* products, an *action* **MUST be defined which SHOULD describe actions to remediate or mitigate vul_id.

Variables:
  • status (ProductStatus) – The current status of this statement.

  • impact (ActionOrImpact) –

    For status ProductStatus.NOT_AFFECTED, if justification is not provided, then a VEX statement MUST provide an impact statement that further explains how or why the listed product ids are ProductStatus.NOT_AFFECTED by given vulnerability.

    If justification is provided, then a VEX statement MAY provide an impact statement.

    An impact statement MAY include an impact statement time, recording when the impact statement was issued.

  • justification (Justification) – Justification for the current status.

  • action (ActionOrImpact) –

    For status ProductStatus.AFFECTED, a VEX statement MUST include one action statement that SHOULD describe actions to remediate or mitigate given vulnerability.

    An action statement MAY include action statement time recording when the action statement was issued.

  • notes (str | None) – Status notes MAY convey information about how status was determined and MAY reference other VEX information.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) StatementStatus

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

class encoding.vex.SubProductId(_id: str, version: str, platforms: list[str], status: StatementStatus | None)

Bases: ProductId

Sub-product ID.

Variables:
  • _id (str) – see ProductId

  • version (str) – see ProductId

  • platforms (list[str]) – The list of platform for this sub-product ID.

  • status (StatementStatus) – The status of the sub product.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.

classmethod from_dict(obj: dict) SubProductId

Load a dictionary as a JSON data object.

Parameters:

obj – The dictionary to initialize the JSON data object with.

Returns:

A new JsonData object initialized with values from the input dictionary.

class encoding.vex.Vulnerability(_id: str, component: str, description: str, score: float | None = None, vector: str | None = None, version: str | None = None, source: str | None = None, url: str | None = None)

Bases: e3.json.JsonData

Statement vulnerability details.

Vulnerability details identify and provide information about the vulnerability in a VEX statement.

Variables:
  • _id (str) –

    Identifies the vulnerability in a VEX statement.

    • A VEX statement MUST specify one _id.

    • _id SHOULD use existing, readily available, and well-known identifiers such as: CVE, the Global Security Database (GSD), or a supplier’s vulnerability identification system. It is expected that vulnerability identification systems are external to and maintained separately from VEX.

    • _id MAY be URIs or URLs.

    • _id MAY be arbitrary and MAY be created by the author.

  • description (str) –

    A VEX statement MUST include or reference one description that corresponds to _id.

    description MUST either be included in the VEX statement or made available to VEX consumers (for example, through a URL).

  • component (str) – The name of the component this vulnerability applies to.

  • score (float | None) – The base score for this vulnerability as defined by https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator and the CVE vector. Set to None if there is no such computed metric for this vulnerability.

  • vector (str | None) – The CVE score vector are defined by https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator. Set to None if no such vector is defined.

  • version (str | None) – The version(s) of component for which this vulnerability is defined.

  • source (str | None) – The emitter of the above score and vector if any.

  • url (str | None) – An url to get details on this vulnerability.

as_dict() dict[str, Any]

Return the dict representation of this JSON data object.