Generate CycloneDX VEX

Use vexcalibur generate when you have a supported CycloneDX JSON or XML SBOM, or when you want to fetch package inventory from a GitHub Dependency Graph SBOM, and need CycloneDX 1.6 VEX JSON based on OSV-compatible vulnerability findings.

Generate From A Public Fixture

The repository fixture is safe to use in public-service examples. The command must still opt in before contacting the public OSV API:

uv run --frozen vexcalibur generate \
  tests/fixtures/sbom/cyclonedx-json-simple.json \
  --allow-public-osv \
  --output /tmp/vexcalibur-vex.json

Live OSV results can change. Add --timestamp when tests or review steps need deterministic document metadata:

uv run --frozen vexcalibur generate \
  tests/fixtures/sbom/cyclonedx-json-simple.json \
  --allow-public-osv \
  --timestamp 2026-06-23T00:00:00Z \
  --output /tmp/vexcalibur-vex.json

Generate With A Private OSV Mirror

Use --osv-url for private mirrors. Do not pass --allow-public-osv for private SBOMs:

uv run --frozen vexcalibur generate \
  path/to/sbom.json \
  --osv-url https://osv.internal.example \
  --output /tmp/vexcalibur-vex.json

The configured endpoint must implement the OSV query API shape used by Vexcalibur’s provider client.

Generate From A GitHub Repository SBOM

Use --github-repo OWNER/REPO when the package inventory should come from GitHub Dependency Graph instead of a local SBOM file:

uv run --frozen vexcalibur generate \
  --github-repo vexcalibur-dev/vexcalibur \
  --allow-public-osv \
  --output /tmp/vexcalibur-vex.json

Vexcalibur requests an SPDX JSON report from GitHub’s asynchronous SBOM API, polls until the report is ready, downloads it, and extracts package URL references from that SPDX document. It then uses the same vulnerability source and CycloneDX VEX rendering pipeline as local CycloneDX input.

Token resolution for --github-repo is designed to work in local shells and CI:

  • Public repositories can be requested without a token, subject to GitHub API rate limits.

  • --github-token-env NAME reads a token from the named environment variable.

  • Without --github-token-env, Vexcalibur checks GH_TOKEN and GITHUB_TOKEN for https://api.github.com.

  • For non-default GitHub API hosts, pass --github-token-env NAME explicitly or rely on the gh auth token fallback for that host.

  • If no token environment variable is set, Vexcalibur tries gh auth token. Pass --no-gh-auth to disable that fallback.

Use --github-api-url for GitHub Enterprise API hosts:

uv run --frozen vexcalibur generate \
  --github-repo internal/example \
  --github-api-url https://github.example.test/api/v3 \
  --github-token-env GH_ENTERPRISE_TOKEN \
  --osv-url https://osv.internal.example \
  --output /tmp/vexcalibur-vex.json

In GitHub Actions, grant contents: read and pass the workflow token. This is a step excerpt that assumes Vexcalibur is already installed in the job:

permissions:
  contents: read

steps:
  - run: |
      vexcalibur generate \
        --github-repo "$GITHUB_REPOSITORY" \
        --github-token-env GITHUB_TOKEN \
        --osv-url https://osv.internal.example \
        --output vex.json
    env:
      GITHUB_TOKEN: ${{ github.token }}

When using the companion action, pass the same CLI arguments through args:

permissions:
  contents: read

steps:
  - uses: vexcalibur-dev/vexcalibur-action@d9967565ac550fd5a22feb8f64ca966e51444cc5
    with:
      package-spec: vexcalibur==0.1.0
      args: |
        generate
        --github-repo
        ${{ github.repository }}
        --github-token-env
        GITHUB_TOKEN
        --osv-url
        https://osv.internal.example
        --output
        vex.json
    env:
      GITHUB_TOKEN: ${{ github.token }}

Fetching an SBOM from GitHub is a network operation. Passing that SBOM-derived package inventory to public OSV is a separate network boundary and still requires --allow-public-osv.

Generate Offline From Local Findings

Use --findings-file when another trusted process has already produced vulnerability findings or exploitability analysis. This mode never contacts OSV.

uv run --frozen vexcalibur generate \
  path/to/sbom.json \
  --offline \
  --findings-file path/to/findings.json \
  --output /tmp/vexcalibur-vex.json

The findings file uses Vexcalibur’s local findings JSON format. Local findings must identify SBOM components by component_ref or by a package URL that appears exactly once in the SBOM.

Choose A Source Mode For CI

Use exactly one vulnerability source mode in automated jobs:

  • Public fixture or intentionally public package inventory: use --allow-public-osv.

  • Private SBOM with an internal OSV-compatible service: use --osv-url https://osv.internal.example.

  • Offline or pre-reviewed vulnerability data from a local SBOM file: use --offline --findings-file path/to/findings.json.

  • GitHub-hosted package inventory: use --github-repo OWNER/REPO and choose one vulnerability source mode.

Do not pass --allow-public-osv for private SBOMs. Do not combine --findings-file with --allow-public-osv or --osv-url; local findings mode is the no-network path.

Write To Standard Output

Omit --output to write the VEX JSON to standard output:

uv run --frozen vexcalibur generate \
  tests/fixtures/sbom/cyclonedx-json-simple.json \
  --allow-public-osv

Generate From XML Input

Use the same command for CycloneDX XML SBOM input:

uv run --frozen vexcalibur generate \
  tests/fixtures/sbom/cyclonedx-xml-simple.xml \
  --allow-public-osv \
  --output /tmp/vexcalibur-vex.json

Supported Input

All generate source modes currently support:

  • CycloneDX JSON SBOMs with specVersion 1.4, 1.5, or 1.6; JSON input must be UTF-8.

  • CycloneDX XML SBOMs rooted at bom in the http://cyclonedx.org/schema/bom/1.4, /1.5, or /1.6 namespace; XML may use parser-detected XML encodings such as UTF-8 or UTF-16, and DTD, entity, and external-reference declarations are rejected.

  • GitHub Dependency Graph SBOM input from --github-repo OWNER/REPO; GitHub generates an SPDX JSON report and Vexcalibur extracts package URL references from package externalRefs.

  • GitHub API URLs must use HTTPS and must not include userinfo, query strings, or fragments. For GitHub Enterprise Server, use the API base URL such as https://github.example.test/api/v3.

  • Token-backed GitHub SBOM requests need repository Contents: read permission. Public repositories can be requested without a token, subject to GitHub API rate limits.

  • Local SBOM files and GitHub SBOM report downloads up to 10 MiB.

  • Up to 10,000 components.

  • Component nesting up to 50 levels.

  • Unique component refs for components with package URLs.

OSV-backed generation also requires components with package URLs and versions from either the PURL, CycloneDX version field, or GitHub SPDX versionInfo. It intentionally fails when no precise query set can be built. That is safer than producing an empty VEX document that could look authoritative.

Local findings mode can produce an empty VEX document when the findings file explicitly contains no findings.

Current Limitations

The current generator does not yet support:

  • Policy-driven VEX state selection for OSV-derived findings.

  • Legacy vexy XML output or CycloneDX 1.4 VEX output.

See the CycloneDX VEX output reference for the generated document contract.