> ## Documentation Index
> Fetch the complete documentation index at: https://zeropath.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SCA SBOM Exports

> CycloneDX, SPDX, VEX, and ML-BOM artifacts backed by the ZeroPath SCA and AI inventories

## Overview

ZeroPath's SBOM service generates export-ready CycloneDX, SPDX, VEX, and ML-BOM documents directly from the SCA and AI inventories your scans already produced. An SBOM built from the SCA inventory reuses the same normalized dependency graph that powers alerting, so the artifact matches what you see in the UI. The same inventory drives [dependency coverage](/docs/sca/ecosystems) and [per-package license data](/docs/sca/licenses), so an SBOM is only as complete as the scan behind it. The pre-scan snapshot fallback described below uses a standard component scanner and may differ, and does not apply to the VEX or ML-BOM formats — see [Data Sources](#data-sources).

<Steps>
  <Step title="Request">
    Accepts a request tied to a scan. You can optionally specify an SCA scan for
    richer inventory data; by default the scan's own SCA inventory is used. SBOM,
    SPDX and VEX exports need that inventory to still be retained (see
    [Retained inventories](#retained-inventories)); ML-BOM exports never do.
  </Step>

  <Step title="Process">
    The job is queued and processed asynchronously; poll its status or receive a
    webhook when it finishes.
  </Step>

  <Step title="Build">
    The SBOM is built from the chosen data source (preferably the SCA
    inventory).
  </Step>

  <Step title="Upload">
    Uploads the JSON artifact to managed object storage and returns a pre-signed
    download URL.
  </Step>

  <Step title="Track">
    Tracks status, attempt count, and expiration so you can poll or receive
    webhook updates.
  </Step>
</Steps>

## Request Flow

<Steps>
  <Step title="Submit">
    Choose the scan, desired format (CycloneDX JSON, SPDX JSON, standalone VEX,
    or ML-BOM), and, for CycloneDX JSON, whether to include embedded VEX data.
    Jobs can be created through the UI or API.
  </Step>

  <Step title="Process">
    ZeroPath processes the job, hydrates the dependency inventory, and generates
    the artifact. Automatic retries handle any interruptions.
  </Step>

  <Step title="Store">
    Finished SBOMs are uploaded to ZeroPath's artifact bucket with a
    time-limited retention policy (24 hours by default, configurable per
    tenant).
  </Step>

  <Step title="Retrieve">
    The API returns a signed URL; optional webhooks fire when the job
    transitions to `Succeeded` or `Failed`.
  </Step>
</Steps>

From a repository's **Inventory** tab, **Export SBOM** stages the artifact for the scan shown on that tab (the selected branch's latest finished full scan).

## Retained inventories

Every SCA scan writes a full dependency inventory. ZeroPath keeps the inventory of the newest
completed scan of each scanned branch and of the scan attached to the newest completed full
scan; when a newer scan supersedes a generation, the older inventory is retired at scan
completion (packages that findings still reference are kept). The scan itself, its findings
and their history are never deleted.

* A CycloneDX, SPDX or VEX export pinned to a retired scan is refused at request time with
  `412 PRECONDITION_FAILED` ("SCA inventory for scan … was retired on …; export the latest
  scan"). A job that was already queued when the retirement happened fails on its next
  attempt for the same reason.
* ML-BOM exports are unaffected: they are built from the AI inventory, which is not retired.
* `scans.getScan` returns `scaScan.inventoryRetiredAt` and `sca.listManifestsForRepository`
  returns `inventoryRetiredAt`, so an integration can pick an exportable scan without
  guessing from an empty package list; a retired scan's manifest list contains only the
  packages findings still reference.

## Formats & VEX Support

<Tabs>
  <Tab title="CycloneDX JSON">
    Best for tooling that expects component graphs, dependency relationships, and embedded VEX. When VEX is requested, each vulnerability carries a CycloneDX `analysis.state`: `not_affected` when the vulnerable code path is not reachable, `exploitable` when it is reachable and confirmed, or `in_triage` when it is reachable but not yet validated. ZeroPath also includes CWE references, a CVSS rating when the advisory carries real CVSS data, and [KEV/EPSS exploit intelligence](#vulnerability-intelligence-properties) as `zeropath:`-namespaced properties.

    When the scan has [AI Inventory](/docs/sca/ai-inventory) data, this export is automatically enriched with the AI/ML components ZeroPath detected — no separate request required. See [Artifact Contents](#artifact-contents) for what that adds.
  </Tab>

  <Tab title="SPDX JSON">
    Aligns with procurement/legal workflows. ZeroPath includes annotations for direct vs transitive dependencies, license declarations, and dependency relationships (`DEPENDS_ON`, `DESCRIBES`). SPDX does not carry VEX or AI Inventory data — use CycloneDX JSON, standalone VEX, or ML-BOM for those.
  </Tab>

  <Tab title="Embedded VEX">
    An add-on to CycloneDX JSON: available only when the SBOM is sourced from the ZeroPath SCA inventory, which holds the vulnerability status VEX requires. If a job targets a repository snapshot, VEX must be disabled. For a document containing only vulnerability data, use standalone VEX instead.
  </Tab>

  <Tab title="Standalone VEX">
    A CycloneDX document that carries only `vulnerabilities[]` — no components, no dependency graph — for tooling that consumes exploitability statements separately from the component inventory. Built entirely from the SCA inventory, so it always requires a completed SCA scan; there is no repository-snapshot path for this format. Downloads as `{codeScanId}-vex.json`.
  </Tab>

  <Tab title="ML-BOM">
    A CycloneDX 1.6 machine-learning bill of materials scoped to one repository's [AI Inventory](/docs/sca/ai-inventory): LLM SDKs, agent frameworks, and similar detected packages as `library` components, model files as `machine-learning-model` components, and agent configs, prompt templates, and datasets as `data` components. Each component carries `zeropath:ai:*` properties for the fields ZeroPath actually knows about it — kind, usage, tier, provider, model format, detection source, manifest/file path, and reachability — so an absent property means that field is not known, not empty.

    Built entirely from the AI inventory, so it always requires a completed code scan; a repository that has only ever run standalone SCA scans returns a clear error until a full scan runs. An empty AI inventory produces a valid document with no components rather than an error. Downloads as `{codeScanId}-mlbom.json`.
  </Tab>
</Tabs>

## Data Sources

<Tabs>
  <Tab title="Preferred: SCA Inventory">
    * Uses the canonical inventory built by the ZeroPath SCA service, so it includes direct/transitive classification, license data, application ownership, and previously validated vulnerability context.
    * SBOMs generated from inventory are consistent: the package set, ordering, and dependency edges match the UI and alerting exactly. Document-level identifiers such as the CycloneDX serial number and timestamp are unique per generation.
    * VEX data is available because the inventory knows which packages are reachable, not reachable, or still in triage.
  </Tab>

  <Tab title="Fallback: Repository Snapshot">
    * Used when a team requests a CycloneDX JSON or SPDX JSON SBOM before a full SCA scan finishes.
    * ZeroPath clones the repository at the requested commit and runs a standard component scanner over its manifests/lockfiles, outputting the same CycloneDX/SPDX structure.
    * Because no inventory exists yet, these SBOMs carry component/relationship data only — no VEX and no reachability. If a lockfile is missing for an ecosystem that needs one, transitive dependencies may be under-reported. For a complete SBOM that includes reachability and VEX data, use an inventory-backed export.
    * Standalone VEX and ML-BOM have no repository-snapshot fallback. Standalone VEX requires a completed SCA scan; ML-BOM requires a completed code scan and uses the linked SCA scan when one exists.
  </Tab>
</Tabs>

## Artifact Contents

Every CycloneDX JSON and SPDX JSON export includes:

* Repository metadata (name, commit SHA, scan timestamp).
* One entry per manifest path (package-lock.json, requirements.txt, go.mod, pom.xml, Podfile, etc.).
* Normalized ecosystems and Package URLs (PURL) for each dependency.
* Direct vs transitive annotations plus a summary of the dependency path so teams know how a package entered the build. Maven transitive dependencies now include full parent-child dependency-path chains.
* License information per package, sourced from manifest fields and external metadata. These fields are informational, not legal advice.
* Dependency relationships (CycloneDX `dependencies`, SPDX `relationships`).
* Optional VEX blocks (embedded, via CycloneDX JSON's VEX option) showing current status, ZeroPath vulnerability IDs, CVSS/EPSS ratings, CWEs, and remediation hints. Standalone VEX carries the same vulnerability entries without the component graph.

CycloneDX JSON additionally carries AI Inventory enrichment when the scan has AI Inventory data: AI/ML-flagged packages carry `zeropath:ai:*` properties (kind, usage, tier, provider, model format, detection source, manifest/file path, and reachability — each present only when known), and file-derived AI signals with no package identity — model files, agent configs — appear as additional components. SPDX is not enriched this way; use ML-BOM for a dedicated, per-repository AI/ML inventory.

### Vulnerability intelligence properties

KEV and EPSS — see [Exploit intelligence: KEV and EPSS](/docs/sca/reachability#exploit-intelligence-kev-and-epss) for what these signals mean — appear on each CycloneDX vulnerability entry (embedded or standalone VEX) as properties in the `zeropath:` namespace:

| Property | Meaning |
| - | - |
| `zeropath:kev` | `"true"` or `"false"` — whether the CVE is in the CISA KEV catalog. |
| `zeropath:kev:dateAdded` | ISO date CISA added the CVE to KEV. Present only when `zeropath:kev` is `"true"`. |
| `zeropath:kev:knownRansomware` | `"true"` or `"false"` — tied to a known ransomware campaign. Present only when `zeropath:kev` is `"true"`. |
| `zeropath:epss:score` | EPSS exploit probability, `0`–`1`, as a string. |
| `zeropath:epss:percentile` | EPSS percentile rank, `0`–`1`, as a string. |

A property is included only when ZeroPath actually knows the value: absence means not known, never a fabricated "not exploited" or a zero score.

EPSS additionally appears as a CycloneDX rating alongside any CVSS rating, so tools that only read `ratings[]` still see it:

```json theme={null}
{
  "method": "other",
  "source": { "name": "EPSS", "url": "https://www.first.org/epss/" },
  "score": 0.42
}
```

## Storage & Access

* SBOMs are stored in ZeroPath-managed object storage with an automatic expiration policy (24 hours by default; can be extended for enterprise tenants).
* Download links are pre-signed URLs that carry the same expiration. Pull the artifact into your own storage if you need longer retention.
* Every job records organization, repository, requester, format, and expiration so you always know who generated which SBOM.

## Adoption Guide

<Steps>
  <Step title="Run at Least One SCA Scan">
    This unlocks inventory-backed SBOMs and VEX exports. Scheduled scans keep
    the inventory current.
  </Step>

  <Step title="Submit SBOM Requests per Release">
    Kick off a job whenever you cut a release branch, tag, or artifact that
    needs provenance.
  </Step>

  <Step title="Choose the Right Format">
    Use CycloneDX JSON (with embedded or standalone VEX) for
    engineering/security workflows, SPDX for procurement/legal stakeholders, and
    ML-BOM when you need a per-repository AI/ML inventory on its own.
  </Step>

  <Step title="Integrate Delivery">
    Plug pre-signed URLs into CI/CD approvals, artifact registries, or audit
    tickets so reviewers can fetch the document automatically.
  </Step>

  <Step title="Mirror Long-Lived Artifacts">
    If policy requires multi-year retention, copy the SBOM into your own storage
    before the link expires.
  </Step>
</Steps>

## Troubleshooting Tips

<AccordionGroup>
  <Accordion title="&#x22;VEX requires SCA inventory&#x22;">
    Applies to both embedded VEX (the CycloneDX JSON option) and the standalone VEX format. Rerun the job with a completed SCA scan selected, or disable VEX for snapshot-based exports.
  </Accordion>

  <Accordion title="&#x22;ML-BOM export requires a code scan&#x22;">
    Shown when a repository has only ever run standalone SCA scans and never a full/code scan. AI Inventory is anchored to a code scan, so run a full scan for the repository and retry the export.
  </Accordion>

  <Accordion title="&#x22;Repository snapshot failed&#x22;">
    Usually caused by missing SCM credentials or a deleted branch/tag. Re-run after fixing access or target a different commit.
  </Accordion>

  <Accordion title="Incomplete dependency list">
    Verify the latest SCA scan finished successfully and that manifests were included (shown in the SCA tab). SBOMs mirror whatever the scan captured.
  </Accordion>

  <Accordion title="Jobs stuck in Pending or Processing">
    SBOM jobs now update their status automatically when generation completes or fails, even if you close the browser or navigate away before the result appears. If a job still shows as pending after ten minutes, ensure SBOM workers are running for your workspace and contact support if it persists.
  </Accordion>

  <Accordion title="Generation failed with an error message">
    SBOM jobs report a specific failure reason. Common failure categories include:

    * **Artifact download failed** — the generated SBOM could not be retrieved from storage. This is usually transient; retry the job.
    * **Artifact missing** — generation completed but no downloadable file was produced. Re-run with a scan that has inventory data.
    * **Generation failed** — an error occurred during SBOM assembly. The error message will include details from the processing pipeline.
    * **Timeout** — the job did not finish within the allowed window. This can happen for very large repositories; contact support if it persists.

    The failure reason on the job indicates whether the issue is with scan data, artifact storage, or processing.
  </Accordion>
</AccordionGroup>

## Comparing Results with Other SBOM Tools

When comparing ZeroPath SBOMs against tools like Syft, Trivy, or Grype, you may notice differences in package counts.

### Why Package Counts Differ

| Factor | ZeroPath | Other Tools (e.g., Syft) |
| - | - | - |
| **Dev dependencies** | Declared dev deps are recorded from the manifest; transitive expansion targets the production graph | Often include every installed dev transitive (e.g. from `node_modules`) |
| **Data source** | Lockfiles and manifests | May also scan `node_modules` directory, binaries, or container layers |
| **Optional/peer dependencies** | Declared ones recorded from the manifest; their subtrees included when resolution covers them | May include unresolved optional deps |
| **Workspace/monorepo packages** | Scoped to the target manifest | May include all workspace packages |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.