Skip to main content

Generate and transform VEX documents from SBOMs and vulnerability data sources.

Project description

Vexcalibur

Vexcalibur wordmark and sword logo

CI CodeQL OpenSSF Scorecard Dependency Review

Vexcalibur is a general-purpose VEX toolkit for vulnerability exploitability workflows across SBOM, package URL, and vulnerability data ecosystems.

Vexcalibur currently ingests CycloneDX JSON and XML SBOM files, can fetch GitHub Dependency Graph SBOMs, collects findings from OSV-compatible APIs or local findings files, and renders CycloneDX 1.6 VEX JSON. It is intended to replace legacy vexy usage over time while staying provider-neutral and ecosystem-neutral.

Status

Usable for the workflows listed below, with unstable public contracts before the first 1.0 release.

Area Current status
SBOM ingest Supports CycloneDX JSON/XML files for CycloneDX 1.4, 1.5, and 1.6, plus GitHub Dependency Graph SBOM input from repository SPDX JSON.
Vulnerability sources Supports public OSV with explicit opt-in, private OSV-compatible endpoints, and no-network local findings files.
VEX output Emits CycloneDX 1.6 VEX JSON with deterministic output when --timestamp is provided.
GitHub Actions Use vexcalibur-action for CI workflows.
Legacy vexy compatibility Supports a narrow vexy CLI subset for CycloneDX JSON VEX generation while preserving the public OSV opt-in boundary.
Stability CLI flags, Python APIs, and output details can change before 1.0. Pin exact versions after releases begin.

Current workflows:

  • Query OSV-compatible APIs for one or more package URLs with vexcalibur query-osv.
  • Generate CycloneDX 1.6 VEX JSON from CycloneDX JSON/XML SBOM files or GitHub Dependency Graph SBOM input with vexcalibur generate.
  • Generate VEX from local findings without contacting a vulnerability service.
  • Run selected legacy vexy commands through the compatibility executable.
  • Run Vexcalibur from GitHub Actions through the companion action.

Development

Prerequisites:

  • Python 3.10 or newer
  • uv 0.11.17

Install dependencies:

uv sync

Run offline tests:

uv run --frozen pytest -m "not live" --cov-fail-under=75

Run live compatibility smoke tests only when you intentionally want to call the covered public services:

uv run --frozen pytest -m live -q

Run static checks:

uv run --frozen ruff check src tests docs/conf.py
uv run --frozen mypy src

Build the documentation:

uv sync --extra docs
make docs

The canonical generated documentation is available on the Vexcalibur documentation site.

Try the CLI:

uv run --frozen vexcalibur --help

Query OSV for a package URL:

uv run --frozen vexcalibur query-osv pkg:pypi/django@1.2 --allow-public-osv

Expected result: the command prints the submitted package URL and any OSV vulnerability IDs returned by https://api.osv.dev.

Like generate, query-osv requires --allow-public-osv for the public OSV API and accepts --osv-url for private mirrors.

Generate CycloneDX VEX JSON from a CycloneDX SBOM:

generate refuses to send package URLs or component versions to the public OSV API unless you pass --allow-public-osv. Do not use that flag with private SBOMs or sensitive package inventories. Use --osv-url for a private OSV mirror. Library callers that inject an OSV client must also provide the matching osv_base_url; the same public-OSV opt-in check is enforced before the client is used.

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

Illustrative private-mirror command, replacing the URL with your internal OSV endpoint:

uv run --frozen vexcalibur generate tests/fixtures/sbom/cyclonedx-json-simple.json --osv-url https://osv.internal.example --output /tmp/vexcalibur-vex.json

Generate from a GitHub repository's Dependency Graph SBOM. This fetches the SBOM from GitHub, then still requires an explicit opt-in before sending the resulting package inventory to public OSV:

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

Offline command using local findings, replacing the file paths with your SBOM and findings JSON:

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

Legacy vexy compatibility command using the same no-network findings source:

uv run --frozen vexy -c tests/fixtures/vexy/legacy-config.yml -i tests/fixtures/sbom/cyclonedx-xml-1.5-simple.xml --format json --schema-version 1.6 --output - --offline --findings-file tests/fixtures/findings/all-analysis-states.json --timestamp 2026-06-23T00:00:00Z

The compatibility command accepts -c/--config for argument compatibility but does not read legacy data-source credentials. Select a Vexcalibur source mode with --findings-file, --osv-url, or --allow-public-osv.

For a deterministic document timestamp, provide --timestamp. Live OSV data can change over time, so identical inputs can still produce different vulnerability findings unless OSV responses are controlled.

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
python - <<'PY'
import json
from pathlib import Path

vex = json.loads(Path("/tmp/vexcalibur-vex.json").read_text())
assert vex["bomFormat"] == "CycloneDX"
assert vex["specVersion"] == "1.6"
assert vex["metadata"]["timestamp"] == "2026-06-23T00:00:00+00:00"
print(f"validated {len(vex.get('vulnerabilities', []))} generated VEX findings")
PY

The OSV-backed generator queries OSV for versioned components with package URLs, emits CycloneDX vulnerability entries for OSV matches, and marks findings in_triage by default. Local findings can provide explicit VEX analysis states and details.

Supported input for all generate source modes:

  • 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 with --github-repo OWNER/REPO; Vexcalibur requests an SPDX JSON report from GitHub's asynchronous SBOM API and extracts package URL references.
  • Local SBOM files and GitHub SBOM report downloads up to 10 MiB, up to 10,000 components, and component nesting up to 50 levels.
  • Unique component refs for components with package URLs. Duplicate queried component refs are rejected because VEX affects entries refer to components by ref.
  • Explicit source configuration. Public OSV requires --allow-public-osv; private mirrors use --osv-url; offline local findings use --findings-file.

Additional OSV-backed requirements:

  • Components need package URLs and either a PURL version, a CycloneDX component version, or GitHub SPDX versionInfo; unversioned components are not queried.
  • The OSV query set must be non-empty. If no component can be queried precisely, the command fails instead of producing an empty VEX that looks authoritative.

Local findings mode can produce an empty VEX document when the findings file explicitly contains "findings": [].

Project Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vexcalibur-0.1.1.tar.gz (734.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vexcalibur-0.1.1-py3-none-any.whl (40.1 kB view details)

Uploaded Python 3

File details

Details for the file vexcalibur-0.1.1.tar.gz.

File metadata

  • Download URL: vexcalibur-0.1.1.tar.gz
  • Upload date:
  • Size: 734.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for vexcalibur-0.1.1.tar.gz
Algorithm Hash digest
SHA256 4715dfa6bb3c11157cff8ef65d2c2dcf8bcb7f6fe845b215322ec58db5d41d7b
MD5 55051c27da78ac011db25147c15337ec
BLAKE2b-256 40dd698a6e9f8375324d341631520c006a63c008154c46f8526c8a76976da34d

See more details on using hashes here.

Provenance

The following attestation bundles were made for vexcalibur-0.1.1.tar.gz:

Publisher: pypi.yml on vexcalibur-dev/vexcalibur

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vexcalibur-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: vexcalibur-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 40.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for vexcalibur-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 179e5d059000e43b4439fc21b0cd46ed6a99915a2777e19063417e09a7512467
MD5 a782b9851074ecf6c056e38f62db1471
BLAKE2b-256 dc1321d13c550ed24acac17a9b65080d339fd2adf343f33ffd24f968389f6895

See more details on using hashes here.

Provenance

The following attestation bundles were made for vexcalibur-0.1.1-py3-none-any.whl:

Publisher: pypi.yml on vexcalibur-dev/vexcalibur

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page