The Advantage of Using VEX SBOMs

Ben Strozykowski18 Feb 2025

Software Bills of Material (SBOMs) are documents which contain a list of components and dependencies of a given software ecosystem, like a list of ingredients in a recipe. On its own, an SBOM can provide some context to how the application was created, what kinds of functionality it may contain, as well as provide a glimpse into the lifecycle of the software project.

When a team includes VEX (Vulnerability Exploitability eXchange) in an SBOM, they are better able to view context for vulnerabilities in the stack, accelerate remediation prioritization, and even make compliance more efficient through automation.

What is VEX?

VEX is an extension of the CycloneDX SBOM standard which includes more security-related context for the components listed. In addition to the software component version and licensing information, VEX includes fields about the vulnerability, as well as fields for the security team to justify an exemption to the vulnerability, and finally a way to show the planned actions for remediation.

Status

The current status of the vulnerability according to the SBOM publisher. The status field can be quickly scanned for immediate information about a particular vulnerability.

Here are the status field’s possible values and a short description of each:

  • not_affected: No remediation is required regarding this vulnerability. A not_affected status required the addition of a justification to the statement.
  • 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. Updates should be provided in further VEX documents as knowledge evolves.

Status Justifications

The justification field allows a team to provide additional context to the status field’s value. This is especially useful when a team marks a vulnerability as not_affected to provide the reasoning for why this vulnerability does not affect the software ecosystem.

Here are the possible values for the justification field and a short description of each:

  • component_not_present: The product is not affected by the vulnerability because the component is not included.
  • vulnerable_code_not_present: The vulnerability requires specific configuration to be present, and it is not
  • vulnerable_code_not_in_execute_path: The vulnerable code (likely in subcomponents) can not be executed as it is used by the product.
  • vulnerable_code_cannot_be_controlled_by_adversary: The vulnerable code cannot be controlled by an attacker to exploit the vulnerability.
  • inline_mitigations_already_exist: The product includes built-in protections or features that prevent exploitation of the vulnerability.

Why Use VEX?

Adding VEX to a software product’s SBOM adds the context of real-world impact to vulnerabilities discovered in the stack, reducing the noise and allowing for more streamlined prioritization, and adds clarity to stakeholder communications.
There are many advantages to using VEX, for example:

  1. Vulnerability Context - The existence of a vulnerability is augmented with real-world data about the exploitability of the vulnerability.
  2. Reduce False Positives - Allow providing detailed information about the non-exploitabliity of false positive vulnerabilities found by tools to reduce human work.
  3. Remediation Prioritization - With the added real-world exploitability context, teams can prioritize based on the criticality of the vulnerability, rather than its presence.
  4. Improved Stakeholder Communication - Avoid unnecessary confusion with standardized language to communicate to your stakeholders the vulnerabilities in your software ecosystem.
  5. Compliance Automation and Streamlining - Additional vulnerability context created through automated means reduces the work to show compliance for various privacy, security, and safety frameworks.

A VEX Example

Using an intentionally vulnerable open source software project to practice creating, updating, and packaging a VEX-formatted SBOM can provide some insight into how an organization can utilize VEX to communicate better with their stakeholders.

BrokenCrystals

In our example, we will be using the NodeJS app called BrokenCrystals, which is an intentionally vulnerable open source project for learning Application Security.

Setup

First, clone the BrokenCrystals repository from Github to a local directory:

git clone https://github.com/NeuraLegion/brokencrystals.git

Next, we need to install the package’s dependencies:

cd brokencrystals 
npm install

Now, we generate an SBOM using the built-in npm tool, using the CycloneDX format, and exporting to a file named `sbom.json`:

npm sbom --sbom-format cyclonedx > sbom.json

With this SBOM in hand, we are now ready to add our VEX data to it.

Vexctl

In order to add our VEX information into our SBOM, we will need a tool for creating and updating the files. Vexctl is a simple utility which allows you to add VEX entries for a given package.

In our example, we use go to install vexctl. Additional methods of installation are available and are described in the Github README.

install vexctl (assuming you have go environment):

go install github.com/openvex/vexctl@latest

alternatively, you can directly install the binary from the releases page (https://github.com/openvex/vexctl/releases)

Now that we have our tool installed, we can take a look at a vulnerability which exists in the SBOM. With the package libxmljs, we find that the version included in BrokenCrystals (1.0.11) is vulnerable to CVE-2024-34392, a type confusion vulnerability which can lead to denial of service and remote code execution.

Since we know that we are not using the vulnerable method in our installation of BrokenCrystals, we can create a VEX entry which reflects that information:

vexctl create --product="pkg:npm/libxmljs@1.0.11" \
            --vuln="CVE-2024-34392" \
            --status="not_affected" \
            --justification="vulnerable_code_not_present"

The output of this command is a VEX statement:

{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "@id": "https://openvex.dev/docs/public/vex-fc7aa4d2618d658c2dbbaf3e09cb11dee3786efad6a9de4c8c13b6672a6e25f2",
  "author": "Unknown Author",
  "timestamp": "2025-02-11T09:53:27.082143077-05:00",
  "version": 1,
  "statements": [
    {
    "vulnerability": {
        "name": "CVE-2024-34392"
    },
    "timestamp": "2025-02-11T09:53:27.08214467-05:00",
    "products": [
        {
        "@id": "pkg:npm/libxmljs@1.0.11"
        }
    ],
    "status": "not_affected",
    "justification": "vulnerable_code_not_present"
    }
  ]
}

Save this output to a text file named vex.json.

Brining It Together

Using another utility, we can combine the VEX statement with the CycloneDX SBOM, to create an enhanced SBOM that provides the downstream consumers with more specific information about the vulnerable components of the system.

CtcloneDX Editor/Validator

Install the CycloneDX Editor/Validator project to enhance working with the CycloneDX SBOM:

python -m pip install cyclonedx-editor-validator

Once the utility is installed, we can issue the command to combine the VEX statement from vexctl, and the generated CycloneDX SBOM:

cdx-ev merge-vex –-output-file enhanced-sbom.json sbom.json vex.json

The resulting enhanced-sbom.json file contains both the full CycloneDX SBOM generated at the beginning of this tutorial as well as the VEX statement we created to provide downstream maintainers up-to-date information about the vulnerable status of the system.

Conclusion

Whether one wants to provide customers or other maintainers with more transparency, adding VEX statements to the SBOMs of software projects enhances the component data found within and presents an opportunity to communicate more clearly and openly with downstream consumers of the software ecosystem.

References:

Get A Demo