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

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.endorlabs.com/feedback

```json
{
  "path": "/inventory-insights/sbom/exporting-sboms/index",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Export SBOMs and VEX

> Learn more about software transparency and the role of SBOMs in your organization.

export const YamlTable = ({children, data: propData, content}) => {
  const KV_RE = /^([A-Za-z][A-Za-z0-9_()/#\s-]+?):\s*(.+)$/;
  const INLINE_MD_RE = /(\[([^\]]+)\]\(([^)]+)\))|(`([^`]+)`)|(\*\*([^*]+)\*\*)|(\*([^*]+)\*)/g;
  const YES_RE = /^-yes-$/i;
  const NO_RE = /^-no-$/i;
  const LIMITED_RE = /^-(limited|partial)-$/i;
  const SIMPLE_TAG_RE = /(<br\s*\/?>)|(<p\s*\/?>)|(-note-)|(-warning-)/gi;
  const tryParseKV = trimmed => {
    const m = KV_RE.exec(trimmed);
    return m ? {
      key: m[1],
      value: m[2].trim()
    } : null;
  };
  const registerKey = (key, seenKeys, orderedKeys) => {
    if (!seenKeys.has(key)) {
      orderedKeys.push(key);
      seenKeys.add(key);
    }
  };
  const flushEntry = (currentEntry, entries) => {
    if (Object.keys(currentEntry).length > 0) entries.push(currentEntry);
  };
  const parseDashPrefixed = (lines, entries, orderedKeys, seenKeys) => {
    let currentEntry = {};
    let inEntry = false;
    for (const line of lines) {
      const trimmed = line.trim();
      if (trimmed.startsWith('- ')) {
        if (inEntry) entries.push(currentEntry);
        currentEntry = {};
        inEntry = true;
        const kv = tryParseKV(trimmed.substring(2).trim());
        if (kv) {
          registerKey(kv.key, seenKeys, orderedKeys);
          currentEntry[kv.key] = kv.value;
        }
      } else if (inEntry && trimmed !== '') {
        const kv = tryParseKV(trimmed);
        if (kv) {
          registerKey(kv.key, seenKeys, orderedKeys);
          currentEntry[kv.key] = kv.value;
        }
      }
    }
    flushEntry(currentEntry, entries);
  };
  const parseBlankSeparated = (lines, entries, orderedKeys, seenKeys) => {
    let currentEntry = {};
    let inEntry = false;
    for (const line of lines) {
      const trimmed = line.trim();
      if (trimmed === '') {
        if (inEntry) {
          flushEntry(currentEntry, entries);
          currentEntry = {};
          inEntry = false;
        }
        continue;
      }
      const kv = tryParseKV(trimmed);
      if (!kv) continue;
      const isNewEntry = !line.startsWith(' ') && !line.startsWith('\t');
      if (isNewEntry && inEntry && Object.keys(currentEntry).length > 0) {
        entries.push(currentEntry);
        currentEntry = {};
      }
      registerKey(kv.key, seenKeys, orderedKeys);
      currentEntry[kv.key] = kv.value;
      inEntry = true;
    }
    flushEntry(currentEntry, entries);
  };
  const normalizeEntries = (entries, orderedKeys) => entries.map(entry => {
    const filled = {};
    for (const key of orderedKeys) filled[key] = entry[key] || '';
    return filled;
  });
  const parseYamlTableContent = contentStr => {
    if (!contentStr) return [];
    const entries = [];
    const orderedKeys = [];
    const seenKeys = new Set();
    const lines = contentStr.split('\n');
    if (lines.some(line => line.trim().startsWith('- '))) {
      parseDashPrefixed(lines, entries, orderedKeys, seenKeys);
    } else {
      parseBlankSeparated(lines, entries, orderedKeys, seenKeys);
    }
    return normalizeEntries(entries, orderedKeys);
  };
  const processText = text => {
    if (!text) return text;
    const parts = [];
    let keyIndex = 0;
    let lastIndex = 0;
    let match;
    while ((match = INLINE_MD_RE.exec(text)) !== null) {
      if (match.index > lastIndex) parts.push(text.slice(lastIndex, match.index));
      if (match[1]) {
        parts.push(<a key={keyIndex++} href={match[3]}>{match[2]}</a>);
      } else if (match[4]) {
        parts.push(<code key={keyIndex++}>{match[5]}</code>);
      } else if (match[6]) {
        parts.push(<strong key={keyIndex++}>{match[7]}</strong>);
      } else if (match[8]) {
        parts.push(<em key={keyIndex++}>{match[9]}</em>);
      }
      lastIndex = match.index + match[0].length;
    }
    if (lastIndex < text.length) parts.push(text.slice(lastIndex));
    if (parts.length === 0) return text;
    const keyRef = {
      current: keyIndex
    };
    return expandHtmlTags(parts, keyRef);
  };
  const processBadges = text => {
    if (!text || typeof text !== 'string') return text;
    if (YES_RE.test(text)) return <span className="yt-badge-yes" role="img" aria-label="Supported" title="Supported">✓</span>;
    if (NO_RE.test(text)) return <span className="yt-badge-no" role="img" aria-label="Not supported" title="Not supported">✗</span>;
    if (LIMITED_RE.test(text)) return <span className="yt-badge-limited" role="img" aria-label="Partially supported" title="Partially supported">◐</span>;
    return processText(text);
  };
  const expandSimpleTags = (str, keyRef) => {
    const result = [];
    let last = 0;
    SIMPLE_TAG_RE.lastIndex = 0;
    let m;
    while ((m = SIMPLE_TAG_RE.exec(str)) !== null) {
      if (m.index > last) result.push(str.slice(last, m.index));
      if (m[1]) {
        result.push(<br key={keyRef.current++} />);
      } else if (m[2]) {
        result.push(<br key={keyRef.current++} />, <br key={keyRef.current++} />);
      } else if (m[3]) {
        result.push(<span key={keyRef.current++} className="yt-badge-note" style={{
          fontWeight: 600
        }}>Note: </span>);
      } else if (m[4]) {
        result.push(<span key={keyRef.current++} className="yt-badge-warning" style={{
          fontWeight: 600
        }}>Warning: </span>);
      }
      last = m.index + m[0].length;
    }
    if (last < str.length) result.push(str.slice(last));
    return result;
  };
  const expandHtmlTags = (chunks, keyRef) => {
    const out = [];
    for (const chunk of chunks) {
      if (typeof chunk === 'string') {
        out.push(...expandSimpleTags(chunk, keyRef));
      } else {
        out.push(chunk);
      }
    }
    return out;
  };
  const extractText = node => {
    if (node === null || node === undefined) return '';
    if (typeof node === 'string') return node;
    if (typeof node === 'number') return String(node);
    if (typeof node === 'boolean') return '';
    if (Array.isArray(node)) return node.map(extractText).join('');
    if (node && typeof node === 'object' && node.type) {
      const props = node.props || ({});
      if (typeof props.children === 'string') return props.children;
      if (props.children) return extractText(props.children);
      return '';
    }
    return String(node || '');
  };
  const [mounted, setMounted] = useState(false);
  useEffect(() => {
    setMounted(true);
  }, []);
  const data = useMemo(() => {
    if (propData) return propData;
    if (content && typeof content === 'string') return parseYamlTableContent(content);
    if (!children) return [];
    if (typeof children === 'string') return parseYamlTableContent(children);
    const childrenArray = Array.isArray(children) ? children : [children];
    return parseYamlTableContent(childrenArray.map(extractText).join('').trim());
  }, [children, propData, content]);
  const columns = useMemo(() => {
    if (!data || data.length === 0) return [];
    const firstRow = data[0];
    if (!firstRow || typeof firstRow !== 'object') return [];
    return Object.keys(firstRow);
  }, [data]);
  if (!mounted) return null;
  if (!data || data.length === 0) return null;
  const rowKey = row => columns.map(c => row[c] || '').join('|');
  return <table>
      <thead>
        <tr>
          {columns.map(col => <th key={col}>{col.replaceAll('_', ' ')}</th>)}
        </tr>
      </thead>
      <tbody>
        {data.map(row => <tr key={rowKey(row)}>
            {columns.map(col => <td key={col}>{processBadges(row[col])}</td>)}
          </tr>)}
      </tbody>
    </table>;
};

To export an SBOM you must first perform a successful `endorctl` scan. If you haven't successfully scanned a project see [quick start](/introduction/getting-started#quick-start) for more information.

Endor Labs supports export in the [CycloneDX format](https://cyclonedx.org/docs/1.6/json/#bomFormat), [VEX](https://cyclonedx.org/capabilities/vex/) format, and [SPDX format](https://spdx.github.io/spdx-spec/v2.3/file-information/).

## Export an SBOM through the Endor Labs user interface

When you export an SBOM at the project level, it includes all the packages in the project and all the package versions. This allows you to combine the SBOMs of multiple packages and versions into a single SBOM. A consolidated SBOM for the project enables quick identification and assessment of vulnerabilities across all software components.

### Export an SBOM as CycloneDX

You can export SBOM of the project in the CycloneDX format.

1. Select **Projects** from the left sidebar.

2. Select the project for which to create an SBOM.

3. Click **Export SBOM** in the top right-hand corner.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/cyclonedx-sbom.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=bb69bca7b514e0534005bdde5f83b0e4" alt="sbom in CycloneDX" width="1134" height="933" data-path="images/inventory-insights/sbom/cyclonedx-sbom.webp" />

4. Select **CycloneDX**.

5. Choose whether to export as an application or a library.

   If you choose to export as an application, enter an application name.

6. Select the output format and type of SBOM you would like to generate in **FILE FORMAT**.

7. Click **Add More** to select the packages and package versions you want to include in the SBOM.

   If you do not select specific packages, the SBOM will include information for all packages and package versions.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/cyclonedx-addmore.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=5e81284fa06f691255467dda4675c126" alt="Add more" width="1134" height="902" data-path="images/inventory-insights/sbom/cyclonedx-addmore.webp" />

   You can filter by ecosystem to select the type of packages to include in the SBOM.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/cyclonedx-addmore-ecosystem.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=b1c773220862bf0191c8052058eb6d8a" alt="Add more ecosystem" width="1503" height="1202" data-path="images/inventory-insights/sbom/cyclonedx-addmore-ecosystem.webp" />

   You can also search and select multiple package versions of the same package.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/cyclonedx-addmore-version.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=4291b6cfbd41fb36c7c6d9b4592fc507" alt="Add more version" width="1134" height="900" data-path="images/inventory-insights/sbom/cyclonedx-addmore-version.webp" />

8. Click **Export SBOM**.

   A file containing the SBOM will download from your browser.

### Export an SBOM as SPDX

You can export SBOM of the project in the SPDX format.

1. Select **Projects** from the left sidebar.

2. Select the project for which to create an SBOM.

3. Click **Export SBOM** in the top right-hand corner.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/spdx-sbom.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=778600ece690951f3c4e574ad68bc3c5" alt="sbom as SPDX" width="1134" height="867" data-path="images/inventory-insights/sbom/spdx-sbom.webp" />

4. Select **SPDX**.

5. Enter the name of your application in **Application Name**.

6. Select the output format and type of SBOM you would like to generate in **File Format**.

7. Click **Add More** to select the packages and package versions you want to include in the SBOM.

   If you do not select specific packages, the SBOM will include information for all packages and package versions.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/spdx-addmore.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=a9d5349bc7b4d8827fbe65f267b15eb5" alt="Select packages" width="1119" height="866" data-path="images/inventory-insights/sbom/spdx-addmore.webp" />

   You can filter by ecosystem to select the type of packages to include in the SBOM.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/spdx-addmore-ecosystem.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=2202495a7ff439a0771917755b2ef1b5" alt="Select packages" width="1119" height="867" data-path="images/inventory-insights/sbom/spdx-addmore-ecosystem.webp" />

   You can also search and select multiple package versions of the same package.

   <img src="https://mintcdn.com/endorlabs-b4795f4f/2CFeZIRm7eKUPEq0/images/inventory-insights/sbom/spdx-addmore-version.webp?fit=max&auto=format&n=2CFeZIRm7eKUPEq0&q=85&s=67ca3abfbe793b9f87da57e78ff609f7" alt="Select packages" width="1119" height="842" data-path="images/inventory-insights/sbom/spdx-addmore-version.webp" />

8. Click **Export SBOM**.

   A file containing the SBOM will download from your browser.

## Export SBOM through endorctl

You can use the following options with the SBOM export command.

<YamlTable>
  {`


    - Flag: \`component-type\`
    Environment_Variable: \`ENDOR_SBOM_COMPONENT_TYPE\`
    Type: string
    Description: Set the SBOM component type to \`application\`, or \`library\` (default \`application\`).

    - Flag: \`output-format\`
    Environment_Variable: \`ENDOR_SBOM_OUTPUT_FORMAT\`
    Type: string
    Description: Set the SBOM format to \`json\` or \`xml\` for CycloneDX, and \`json\` or \`tag-value\` for SPDX (\`json\` is the default for both).

    - Flag: \`package-version-name\`
    Environment_Variable: \`ENDOR_SBOM_PACKAGE_VERSION_NAME\`
    Type: string
    Description: Name of the package version for which you want to generate an SBOM.

    - Flag: \`package-version-uuid\`
    Environment_Variable: \`ENDOR_SBOM_PACKAGE_VERSION_UUID\`
    Type: string
    Description: The UUID of the package version for which you want to generate an SBOM.

    - Flag: \`timeout\`
    Environment_Variable: \`ENDOR_SBOM_TIMEOUT\`
    Type: string
    Description: Set the timeout for the SBOM generation (default \`30s\`). Use the Go duration format, for example, 30s, 1m.

    - Flag: \`with-vex\`
    Environment_Variable: \`ENDOR_SBOM_WITH_VEX\`
    Type: boolean
    Description: Generate the corresponding VEX document along with the SBOM.

    - Flag: \`project-uuid\`
    Environment_Variable: \`ENDOR_SBOM_PROJECT_UUID\`
    Type: string
    Description: The UUID of the project for which you want to generate an SBOM.

    - Flag: \`project-name\`
    Environment_Variable: \`ENDOR_SBOM_PROJECT_NAME\`
    Type: string
    Description: Name of the project for which you want to generate an SBOM.

    - Flag: \`app-name\`
    Environment_Variable: \`ENDOR_SBOM_APP_NAME\`
    Type: string
    Description: Name of the application or the library. Required for multi-package SBOM export.

    - Flag: \`package-version-uuids\`
    Environment_Variable: \`ENDOR_SBOM_PACKAGE_VERSION_UUIDS\`
    Type: string
    Description: The list of package version UUIDs to export an SBOM.


    `}
</YamlTable>

You can export an SBOM in CycloneDX or SPDX format using endorctl, for a single package version or across multiple package versions.

<Tabs>
  <Tab title="Export SBOM with a single package version">
    To export an SBOM you will need the package version name for which you'd like to create an SBOM or its UUID. You can also export an SBOM with multiple package versions. To export an SBOM with multiple package versions, you need the package version UUIDs or the project name.

    Pass the package name or UUID to the command `endorctl sbom export` using the `--package-version-name` or `--uuid` flags.

    To export an SBOM, you must first retrieve the package version name through the API.

    You can easily export a reference package name and the scanned version you'd like to export as environment variables.

    ```shell theme={null}
    export PACKAGE_NAME=<insert_package_name>
    export VERSION=<insert_package_version>
    ```

    Then query the API for the package version name and set this as an environment variable:

    ```shell theme={null}
    export PACKAGE_VERSION_NAME=$(endorctl api list -r PackageVersion --filter "meta.name matches $PACKAGE_NAME AND meta.name matches $VERSION" --field-mask=meta.name | jq -r ".list.objects[].meta.name")
    ```

    Export an SBOM in the CycloneDX format through endorctl using the package version name.

    ```shell theme={null}
    endorctl sbom export --package-version-name=$PACKAGE_VERSION_NAME >> cyclonedx.json

    ```

    Export an SBOM in the SPDX format through endorctl using the package version name.

    ```shell theme={null}
    endorctl sbom export --format spdx --package-version-name=$PACKAGE_VERSION_NAME >> spdx.json

    ```
  </Tab>

  <Tab title="Export SBOM in CycloneDX format with multiple package versions">
    To export multiple package versions in an SBOM, you need the UUIDs of package versions, or the name or UUID of the project to which the package versions belong.

    To create an SBOM based on project details, either provide the project UUID with the `--project-uuid` flag or the project name with the `--project-name` flag. You also need to provide a name for the package with the `--app-name` flag.

    Run the command to create an SBOM with multiple package versions using the project UUID.

    ```shell theme={null}
    endorctl sbom export -n <Namespace> --project-uuid=<Project UUID> --app-name=<Application Name> >> <SBOM Name>.json

    ```

    For example:

    ```shell theme={null}
    endorctl sbom export -n test --project-uuid=66e345c340669666c22979d6 --app-name=actions-hu/app-java-demo >> cyclonedx-sbom.json
    ```

    Run the following commands to create an SBOM with multiple package versions with the project name.

    1. Fetch the project name using the project's UUID.

    ```shell theme={null}
    endorctl api get -r Project --uuid <Project's UUID> -n <namesapce> |jq .meta.name

    ```

    2. Run the following command and replace `<Project Name>` with the project name you retrieved in the previous step.

    ```shell theme={null}
    endorctl sbom export -n <Namespace> --project-name=<Project Name> --app-name=<Application Name> >> <SBOM Name>.json
    ```

    For example:

    ```shell theme={null}
    endorctl sbom export -n test --project-name=actions-hu/app-java-demo --app-name=actions-hu/app-java-demo >> cyclonedx-sbom.json
    ```

    Generate an SBOM based on package version UUIDs, provide the package version UUIDs with the `--package-version-uuids` flag. You also need to provide a name for the package with the `--app-name` flag.

    ```shell theme={null}
    endorctl sbom export -n <Namespace> --package-version-uuids=<Package Version UUID 1>,<Package Version UUID 2>,... <Package Version UUID N> --app-name=<Application Name> >> <SBOM Name>.json
    ```

    For example:

    ```shell theme={null}
    endorctl sbom export -n test --package-version-uuids=66e345c340669666c22979d6,89f456c340669666c229854a,43a56b1340669666c289d4a2 --app-name=actions-hu/app-java-demo >> spdx-sbom.json

    ```
  </Tab>

  <Tab title="Export SBOM in SPDX format with multiple package versions">
    To export multiple package versions in an SBOM, you need the UUIDs of package versions, or the name or UUID of the project to which the package versions belong.

    To create an SBOM based on project details, either provide the project UUID with the `--project-uuid` flag or the project name with the `--project-name` flag. You also need to provide a name for the package with the `--app-name` flag.

    Run the command to create an SBOM with multiple package versions using the project UUID.

    ```shell theme={null}
    endorctl sbom export --format spdx -n <Namespace> --project-uuid=<Project UUID> --app-name=<Application Name> >> <SBOM Name>.json

    ```

    For example:

    ```shell theme={null}

    endorctl sbom export --format spdx -n test --project-uuid=66e345c340669666c22979d6 --app-name=actions-hu/app-java-demo >> spdx-sbom.json
    ```

    Run the following commands to create an SBOM with multiple package versions with the project name.

    1. Fetch the project name using the project's UUID.

    ```shell theme={null}
    endorctl api get -r Project --uuid <Project's UUID> -n <namesapce> |jq .meta.name

    ```

    2. Run the following command and replace `<Project Name>` with the project name you retrieved in the previous step.

    ```shell theme={null}
    endorctl sbom export --format spdx --output-format=<Format Type> -n <Namespace> --project-name=<Project Name> --app-name=<Application Name> >> <SBOM Name>.json
    ```

    For example:

    ```shell theme={null}
    endorctl sbom export --format spdx --output-format=json -n test --project-name=actions-hu/app-java-demo --app-name=actions-hu/app-java-demo >> spdx-sbom.json
    ```

    Generate an SBOM based on package version UUIDs, provide the package version UUIDs with the `--package-version-uuids` flag. You also need to provide a name for the package with the `--app-name` flag.

    ```shell theme={null}
    endorctl sbom export --format spdx --output-format=json  -n <Namespace> --package-version-uuids=<Package Version UUID 1>,<Package Version UUID 2>,... <Package Version UUID N> --app-name=<Application Name> >> <SBOM Name>.json
    ```

    For example:

    ```shell theme={null}
    endorctl sbom export --format spdx --output-format=json -n test --package-version-uuids=66e345c340669666c22979d6,89f456c340669666c229854a,43a56b1340669666c289d4a2 --app-name=actions-hu/app-java-demo >> spdx-sbom.json
    ```
  </Tab>
</Tabs>

To export the CycloneDX SBOM as a library rather than an application use `--component-type=library`.

```shell theme={null}
endorctl sbom export --component-type=library --package-version-name=$PACKAGE_VERSION_NAME >> cyclonedx.json
```

To export the CycloneDX SBOM in XML format rather than json use `--output-format` with the XML parameter.

```shell theme={null}
endorctl sbom export --output-format=xml --package-version-name=$PACKAGE_VERSION_NAME >> cyclonedx.xml
```

To export a VEX document use the flag `--with-vex`

```shell theme={null}
endorctl sbom export --with-vex
```

To export the SPDX SBOM using the tag-value format instead of json, use `--output-format=tag-value`.

```shell theme={null}
endorctl sbom export --format spdx --output-format=tag-value --package-version-name=$PACKAGE_VERSION_NAME >> sbom-spdx.spdx
```

<Note>
  endorctl generates SBOMs in the CycloneDX format by default.
</Note>

## Endor Labs Export Formats

Endor Labs provides the following fields to map to the [NTIA minimum elements of an SBOM standard](https://www.ntia.gov/report/2021/minimum-elements-software-bill-materials-sbom).

### CycloneDX Format

Endor Labs supports export in the CycloneDX format.

The following table lists the mandatory and some optional fields in the SBOM file that Endor Labs exports.

<YamlTable>
  {`


    - Field: \`bomFormat\`
    Mandatory: true
    Description: Specifies the format of the SBOM.

    - Field: \`specVersion\`
    Mandatory: true
    Description: The version of the specification used (for example, "1.4").

    - Field: \`serialNumber\`
    Mandatory: false
    Description: A unique identifier for the SBOM document.

    - Field: \`version\`
    Mandatory: true
    Description: The revision number of the SBOM.

    - Field: \`metadata\`
    Mandatory: false
    Description: Contains metadata about the SBOM and primary component.

    - Field: \`metadata.timestamp\`
    Mandatory: false
    Description: The date and time when the SBOM was generated.

    - Field: \`metadata.component\`
    Mandatory: false
    Description: Information about the main component described by the SBOM.

    - Field: \`metadata.component.bom-ref\`
    Mandatory: false
    Description: A reference identifier for the component within the BOM.

    - Field: \`metadata.component.type\`
    Mandatory: false
    Description: The type of the main component (for example, "application" or "library").

    - Field: \`metadata.component.name\`
    Mandatory: false
    Description: The name of the main component.

    - Field: \`metadata.component.version\`
    Mandatory: false
    Description: The version of the main component.

    - Field: \`metadata.component.hashes\`
    Mandatory: false
    Description: Cryptographic hashes of the main component.

    - Field: \`metadata.component.purl\`
    Mandatory: false
    Description: The Package URL (purl) for the main component.

    - Field: \`metadata.supplier\`
    Mandatory: false
    Description: Information about the supplier of the software.

    - Field: \`metadata.supplier.name\`
    Mandatory: false
    Description: The name of the supplier.

    - Field: \`metadata.supplier.url\`
    Mandatory: false
    Description: URLs associated with the supplier.

    - Field: \`metadata.supplier.contact\`
    Mandatory: false
    Description: Contact information for the supplier.

    - Field: \`metadata.licenses\`
    Mandatory: false
    Description: License information for the main component.

    - Field: \`components\`
    Mandatory: true
    Description: List of software components included in the SBOM.

    - Field: \`components[].bom-ref\`
    Mandatory: false
    Description: A reference identifier for each component within the BOM.

    - Field: \`components[].type\`
    Mandatory: true
    Description: The type of each component (for example, "library").

    - Field: \`components[].name\`
    Mandatory: true
    Description: The name of each component.

    - Field: \`components[].version\`
    Mandatory: false
    Description: The version of each component.

    - Field: \`components[].licenses\`
    Mandatory: false
    Description: License information for each component.

    - Field: \`components[].licenses[].license.name\`
    Mandatory: false
    Description: The name of the license.

    - Field: \`components[].purl\`
    Mandatory: false
    Description: The Package URL (purl) for each component.

    - Field: \`components[].externalReferences\`
    Mandatory: false
    Description: External references for components.

    - Field: \`components[].externalReferences[].url\`
    Mandatory: false
    Description: The URL of the external reference.

    - Field: \`components[].externalReferences[].type\`
    Mandatory: false
    Description: The type of the external reference (for example, "\`vcs\`").

    - Field: \`components[].pedigree\`
    Mandatory: false
    Description: Contains pedigree metadata for components that use an [Endor patch](/risk-remediation/endor-patches). See [Patch data in SBOM](#patch-data-in-sbom) for more information.

    - Field: \`components[].pedigree.ancestors\`
    Mandatory: false
    Description: The upstream component version that is the base for the patch. The patched component in the SBOM is derived from this ancestor.

    - Field: \`components[].pedigree.patches\`
    Mandatory: false
    Description: List of patches applied to the component. Each patch includes the base64-encoded diff and the vulnerabilities it resolves.

    - Field: \`components[].pedigree.patches[].diff\`
    Mandatory: false
    Description: The base64-encoded patch content.

    - Field: \`components[].pedigree.patches[].resolves\`
    Mandatory: false
    Description: List of vulnerabilities resolved by this patch.

    - Field: \`dependencies\`
    Mandatory: false
    Description: Describes the relationships between components.

    - Field: \`dependencies[].ref\`
    Mandatory: false
    Description: Reference to a component in the dependency relationship.

    - Field: \`dependencies[].dependsOn\`
    Mandatory: false
    Description: List of components that this component depends on.

    `}
</YamlTable>

#### Patch data in SBOM

CycloneDX SBOMs generated by Endor Labs include patch data for components that use an Endor patch. This allows consumers of the SBOM to see exactly which upstream version was patched, what changes were applied, and which vulnerabilities those patches resolve.

The following fields describe how patch data appears in the exported SBOM.

<YamlTable>
  {`


    - Field: \`pedigree.patches[].diff\`
    Description: Contains the patch data associated with the component. The \`diff\` object stores the patch as  base64 encoded content with \`contentType\` set to \`text/plain\`.
    - Field: \`pedigree.ancestors\`
    Description: Contains the upstream component version that was used as the base for the patch. This is the original version from which the patched version was derived.
    - Field: \`pedigree.patches[].resolves\`
    Description: Identifies the vulnerabilities resolved by the patch. Each entry sets \`type\` to \`security\` and specifies \`name\` as the vulnerability identifier such as a GHSA ID.
    - Field: \`version\`
    Description: Specifies the component version as declared in the manifest file. If a version reference such as \`endor-latest\` is used, the SBOM retains the value declared in the manifest file.


    `}
</YamlTable>

The following example shows a patched component in a CycloneDX SBOM.

```json expandable theme={null}
{
  "bom-ref": "mvn://com.fasterxml.jackson.core:jackson-databind@2.9.10.3-endor-2024-07-10",
  "type": "library",
  "name": "com.fasterxml.jackson.core:jackson-databind",
  "version": "2.9.10.3-endor-2024-07-10",
  "licenses": [],
  "purl": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.10.3-endor-2024-07-10",
  "pedigree": {
    "ancestors": [
      {
        "bom-ref": "mvn://com.fasterxml.jackson.core:jackson-databind@2.9.10.3",
        "type": "library",
        "name": "com.fasterxml.jackson.core:jackson-databind",
        "version": "2.9.10.3",
        "licenses": [],
        "purl": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.10.3",
        "externalReferences": [
          {
            "url": "https://github.com/fasterxml/jackson-databind.git",
            "type": "vcs"
          }
        ]
      }
    ],
    "patches": [
      {
        "diff": {
          "text": {
            "content": "<base64-encoded patch content>",
            "contentType": "text/plain",
            "encoding": "base64"
          }
        },
        "resolves": [
          {
            "id": "",
            "name": "GHSA-q93h-jc49-78gg",
            "description": "",
            "type": "security"
          },
          {
            "id": "",
            "name": "GHSA-p43x-xfjf-5jhr",
            "description": "",
            "type": "security"
          }
        ]
      }
    ]
  }
}
```

### VEX Format

The following table lists the mandatory and some optional fields in the VEX file that Endor Labs exports.

<YamlTable>
  {`


    - Field: \`bomFormat\`
    Mandatory: true
    Description: Specifies the format of the VEX document.

    - Field: \`specVersion\`
    Mandatory: true
    Description: The version of the specification used.

    - Field: \`serialNumber\`
    Mandatory: true
    Description: A unique identifier for the VEX document.

    - Field: \`version\`
    Mandatory: true
    Description: The revision number of the VEX document.

    - Field: \`metadata\`
    Mandatory: true
    Description: Contains metadata about the VEX document and primary component.

    - Field: \`metadata.timestamp\`
    Mandatory: true
    Description: The date and time when the VEX document was generated.

    - Field: \`metadata.tools\`
    Mandatory: true
    Description: Information about tools used to generate the VEX document.

    - Field: \`metadata.tools.services\`
    Mandatory: true
    Description: List of services used in generating the VEX document.

    - Field: \`metadata.tools.services[].provider\`
    Mandatory: true
    Description: Information about the provider of the service.

    - Field: \`metadata.tools.services[].provider.name\`
    Mandatory: true
    Description: The name of the service provider.

    - Field: \`metadata.tools.services[].provider.url\`
    Mandatory: true
    Description: URLs associated with the service provider.

    - Field: \`metadata.tools.services[].name\`
    Mandatory: true
    Description: The name of the service.

    - Field: \`metadata.tools.services[].version\`
    Mandatory: true
    Description: The version of the service.

    - Field: \`metadata.tools.services[].description\`
    Mandatory: true
    Description: A description of the service.

    - Field: \`metadata.component\`
    Mandatory: true
    Description: Information about the main component described by the VEX document.

    - Field: \`metadata.component.bom-ref\`
    Mandatory: true
    Description: A reference identifier for the component within the VEX.

    - Field: \`metadata.component.type\`
    Mandatory: true
    Description: The type of the main component.

    - Field: \`metadata.component.name\`
    Mandatory: true
    Description: The name of the main component.

    - Field: \`metadata.component.version\`
    Mandatory: true
    Description: The version of the main component.

    - Field: \`metadata.component.hashes\`
    Mandatory: true
    Description: Cryptographic hashes of the main component.

    - Field: \`metadata.component.purl\`
    Mandatory: true
    Description: The Package URL (purl) for the main component.

    - Field: \`vulnerabilities\`
    Mandatory: true
    Description: List of vulnerabilities associated with the component.

    - Field: \`vulnerabilities[].id\`
    Mandatory: false
    Description: The identifier of the vulnerability.

    - Field: \`vulnerabilities[].references\`
    Mandatory: false
    Description: References related to the vulnerability.

    - Field: \`vulnerabilities[].references[].source.url\`
    Mandatory: false
    Description: URL of the reference source.

    - Field: \`vulnerabilities[].ratings\`
    Mandatory: false
    Description: Severity ratings for the vulnerability.

    - Field: \`vulnerabilities[].ratings[].score\`
    Mandatory: false
    Description: Numerical score of the severity.

    - Field: \`vulnerabilities[].ratings[].severity\`
    Mandatory: false
    Description: Textual representation of the severity.

    - Field: \`vulnerabilities[].ratings[].method\`
    Mandatory: false
    Description: The method used for rating (for example, "CVSSv3").

    - Field: \`vulnerabilities[].ratings[].vector\`
    Mandatory: false
    Description: The vector string for the rating.

    - Field: \`vulnerabilities[].cwes\`
    Mandatory: false
    Description: Common Weakness Enumeration (CWE) identifiers.

    - Field: \`vulnerabilities[].description\`
    Mandatory: false
    Description: A description of the vulnerability.

    - Field: \`vulnerabilities[].detail\`
    Mandatory: false
    Description: Detailed information about the vulnerability.

    - Field: \`vulnerabilities[].recommendation\`
    Mandatory: false
    Description: Recommended actions to address the vulnerability.

    - Field: \`vulnerabilities[].advisories\`
    Mandatory: false
    Description: List of advisories related to the vulnerability.

    - Field: \`vulnerabilities[].advisories[].url\`
    Mandatory: false
    Description: URL of the advisory.

    - Field: \`vulnerabilities[].published\`
    Mandatory: false
    Description: The date when the vulnerability was published.

    - Field: \`vulnerabilities[].updated\`
    Mandatory: false
    Description: The date when the vulnerability information was last updated.

    - Field: \`vulnerabilities[].credits\`
    Mandatory: false
    Description: Credits for individuals or organizations related to the vulnerability.

    - Field: \`vulnerabilities[].credits.individuals\`
    Mandatory: false
    Description: List of individuals credited.

    - Field: \`vulnerabilities[].analysis\`
    Mandatory: false
    Description: Analysis of the vulnerability's impact on the component.

    - Field: \`vulnerabilities[].analysis.state\`
    Mandatory: false
    Description: The state of the analysis (for example, \`not_affected\`).

    - Field: \`vulnerabilities[].analysis.justification\`
    Mandatory: false
    Description: Justification for the analysis state.

    - Field: \`vulnerabilities[].affects\`
    Mandatory: false
    Description: Information about which components are affected by the vulnerability.

    - Field: \`vulnerabilities[].affects[].ref\`
    Mandatory: false
    Description: Reference to the affected component.


    `}
</YamlTable>

### SPDX Format

The following table lists the mandatory and some optional fields in the SPDX file that Endor Labs exports.

<YamlTable>
  {`


    - Field: \`spdxVersion\`
    Mandatory: true
    Description: Specifies the SPDX specification version used.

    - Field: \`dataLicense\`
    Mandatory: true
    Description: Specifies the data license for the SPDX document.

    - Field: \`SPDXID\`
    Mandatory: true
    Description: Unique identifier for the SPDX document.

    - Field: \`name\`
    Mandatory: true
    Description: Name of the SPDX document.

    - Field: \`documentNamespace\`
    Mandatory: false
    Description: Defines the namespace URI for the document.

    - Field: \`creationInfo\`
    Mandatory: true
    Description: Contains metadata about when and how the document was created.

    - Field: \`creationInfo.licenseListVersion\`
    Mandatory: false
    Description: Specifies the version of the SPDX license list used.

    - Field: \`creationInfo.creators[]\`
    Mandatory: true
    Description: List of entities that created the document (tool, organization, or person).

    - Field: \`creationInfo.created\`
    Mandatory: true
    Description: The date and time when the document was created.

    - Field: \`packages[]\`
    Mandatory: true
    Description: List of packages included in the SPDX document.

    - Field: \`packages[].name\`
    Mandatory: true
    Description: Name of the package.

    - Field: \`packages[].SPDXID\`
    Mandatory: true
    Description: Unique identifier for the package.

    - Field: \`packages[].versionInfo\`
    Mandatory: false
    Description: Version of the package, if known.

    - Field: \`packages[].supplier\`
    Mandatory: false
    Description: Information about the package supplier.

    - Field: \`packages[].downloadLocation\`
    Mandatory: true
    Description: Location from where the package can be downloaded.

    - Field: \`packages[].filesAnalyzed\`
    Mandatory: false
    Description: Indicates whether the files in the package were analyzed.

    - Field: \`packages[].licenseConcluded\`
    Mandatory: false
    Description: License the package is concluded to be under.

    - Field: \`packages[].licenseDeclared\`
    Mandatory: false
    Description: License declared by the package supplier.

    - Field: \`packages[].copyrightText\`
    Mandatory: false
    Description: Copyright statement for the package.

    - Field: \`packages[].externalRefs[]\`
    Mandatory: false
    Description: List of external references related to the package.

    - Field: \`packages[].externalRefs[].referenceCategory\`
    Mandatory: true
    Description: Category of the external reference.

    - Field: \`packages[].externalRefs[].referenceType\`
    Mandatory: false
    Description: Type of external reference (for example, \`purl\`).

    - Field: \`packages[].externalRefs[].referenceLocator\`
    Mandatory: true
    Description: Value used to locate the reference (for example, a Package URL).


    `}
</YamlTable>
