
VEX Repository Specification
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
When comparing versions:
Example comparisons:
The manifest file provides metadata about a VEX data repository. This file MUST contain information necessary for retrieving and updating VEX data.
https://<domain>/.well-known/vex-repository.jsonvex-repository.json MUST be placed in the root directory of the main branch.The JSON schema for the manifest file is defined here.
{
"name": "Example Org VEX Repository",
"description": "VEX repository for Example Organization",
"versions": [
{
"spec_version": "0.1",
"locations": [
{
"url": "https://example.com/vex-hub/v0/vex-data-v0.tar.gz"
}
],
"update_interval": "24h",
"repository_specific": {
"location": {
"repository_type": "db",
"db_type": "bbolt",
"url": "oci://ghcr.io/example.com/vex-db:0"
}
}
},
{
"spec_version": "1.0",
"locations": [
{
"url": "https://example.com/vex-hub/v1/vex-data-v1.tar.gz//subdirectory"
},
{
"url": "https://example.com/vex-api/v1"
}
],
"update_interval": "1h"
}
]
}
| Field | Required | Description and Usage Notes |
|---|---|---|
| name | ✓ | The name of the repository. |
| Field | Required | Description and Usage Notes |
|---|---|---|
| url | ✓ | A URL for the VEX data location, starting with "https://". The content adheres to the repository structure specifications in section 3 and 4. The URL may include a subdirectory specification by appending '//' followed by the subdirectory path. |
The repository MUST have the following structure:
vex-repository.<archive_extension>
[optional_subdirectory/]
├── index.json
└── pkg/
├── <type>/
│ ├── <namespace>/
│ │ ├── <name>/
│ │ │ └── vex.json
│ │ └── ...
│ └── ...
└── ...
Where <archive_extension> is one of supported archive formats.
The [optional_subdirectory/] is included when the URL in the locations field ends with // followed by a subdirectory path.
This allows for flexibility in repository structure, particularly when using existing repository layouts such as those in GitHub repositories.
For example, if the URL is https://github.com/org/repo/archive/refs/heads/main.tar.gz//repo-main, the file structure would be:
main.tar.gz
└──repo-main/
├── index.json
└── pkg/
└── ...
In this case, repo-main/ is the root directory for the VEX repository within the tar.gz file.
The index.json file serves as a manifest for the contents of the archive file. It MUST be placed in the root directory of the archive or in the specified subdirectory if one is defined in the URL. The file MUST have the following structure:
{
"updated_at": "2023-07-04T12:00:00Z",
"packages": [
{
"id": "pkg:deb/debian/curl",
"location": "pkg/deb/debian/curl/vex.json"
},
{
"id": "pkg:npm/lodash",
"location": "pkg/npm/lodash/vex.json",
"format": "csaf"
}
]
}
Field descriptions:
The schema for the index file is defined here.
Each package's VEX information MUST be stored in a separate JSON file, following the path structure defined in the index.json file. The content of these files MUST adhere to the VEX format specification (OpenVEX or CSAF VEX) as specified in the format field.
A single VEX document MAY include information for different versions, qualifiers and subpaths of the same package.
For OpenVEX document examples, please refer to the OpenVEX specification.
repository_url qualifier of the PURL MAY be used to create the directory structure. For example, a package with PURL "pkg:oci/debian@sha256:3e45770a143ee5afd1ebde5a6aea6e32a71d2bt5602f5dac8025db0d9cc19f10?repository_url=docker.io/library/debian" could be stored in "pkg/oci/docker.io/library/debian/vex.json".location field, regardless of the recommended structure.When updating the VEX repository:
updated_at timestamp.locations URL in the manifest file (vex-repository.json) if necessary.The VEX Repository MUST be distributed as an archive file containing the VEX data and associated metadata. This archive MUST be referenced by the locations field in the vex-repository.json file and is the primary means of distributing VEX information.
The archive file MUST be in one of the following formats:
tar.gz and tgztar.bz2 and tbz2tar.xz and txzzipgzbz2xzWhen selecting a version from the versions array:
spec_version field.When dealing with multiple locations in the locations array:
Clients SHOULD be designed to support multiple VEX repositories.
Clients SHOULD use the following process to check for updates:
update_interval from the vex-repository.json file.update_interval to the locally stored timestamp.For efficient operation, clients MAY implement the following strategies:
update_interval is very short.| description | ✓ | A brief description of the repository. |
| versions | ✓ | An array containing details of available versions. Each object in the array represents a version implementing a VEX Repository Specification version. Versions MUST be sorted in ascending order, from oldest to newest. See separate table for subfields. |
| Field | Required | Description and Usage Notes |
|---|
| spec_version | ✓ | The version of the VEX Repository Specification implemented (e.g., "0.1"). Format MUST be "X.Y" as defined in section 1. |
| locations | ✓ | An array of objects describing VEX data locations. MUST contain at least one location object. See separate table for subfields. |
| update_interval | ✓ | The recommended update check interval for this version's VEX data. Uses Go duration format (e.g., "1h", "30m", "24h"). |
| repository_specific | - | Additional repository-specific information. |
| Field | Required | Description |
|---|
| updated_at | ✓ | Timestamp indicating when this index.json was last updated. |
| packages | ✓ | Array of objects, each representing a package in the repository. |
| packages[].id | ✓ | Identifier of the package. Currently, only Package URL (PURL) is accepted. Version, qualifiers, and subpath MUST be omitted as they are included in the VEX document. For OCI type packages, the repository_url qualifier MUST be included in the id. |
| packages[].location | ✓ | Relative path to the VEX file for this package within the archive. Clients MUST use this field to locate specific package VEX files. |
| packages[].format | - | Format of the VEX data. Either "openvex" or "csaf". If omitted, "openvex" is assumed. |