# How osv-scanner Processes CycloneDX SBOM Files for Security Analysis

> Learn how osv-scanner processes CycloneDX SBOM files for security analysis. Discover component details and vulnerability mapping for enhanced software supply chain security.

- Repository: [Google/osv-scanner](https://github.com/google/osv-scanner)
- Tags: how-to-guide
- Published: 2026-04-25

---

**OSV-Scanner ingests CycloneDX SBOM files as standardized package manifests, extracts component metadata using the Scalibr framework, and maps discovered vulnerabilities back to specific SBOM coordinates while optionally emitting vulnerability-enriched CycloneDX reports.**

The `google/osv-scanner` tool treats CycloneDX SBOM files as first-class inputs for vulnerability detection. When you provide a CycloneDX file—typically with a [`.cdx.json`](https://github.com/google/osv-scanner/blob/main/.cdx.json) extension—the scanner parses its component inventory and queries the Open Source Vulnerabilities (OSV) database for matching security issues. This integration enables security teams to audit software bill of materials without requiring access to original package manager files.

## SBOM Detection and Extractor Resolution

### Plugin Resolution for SBOM Processing

When you invoke `osv-scanner` with the `--sbom` flag, the scan command adds the specified path to `actions.SBOMPaths`. In **[`pkg/osvscanner/scan.go`](https://github.com/google/osv-scanner/blob/main/pkg/osvscanner/scan.go)**, the scanner initializes extractors by calling `scalibrplugin.Resolve([]string{"sbom"}, ...)`, which loads the default SBOM preset defined in [`internal/scalibrplugin/presets.go`](https://github.com/google/osv-scanner/blob/main/internal/scalibrplugin/presets.go). This preset includes the CycloneDX extractor (`github.com/google/osv-scanner/extractor/filesystem/sbom/cdx`) alongside other SBOM format handlers.

### File Matching and Extractor Selection

For each SBOM path provided, the scanner evaluates whether the CycloneDX extractor should handle the file by calling its `FileRequired` method. If the filename matches CycloneDX patterns, the extractor is stored in an `overrideMap` that associates specific file paths with their dedicated parsers. This mapping ensures that when `scalibr.New().Scan` executes, it routes the file to the correct CycloneDX parser rather than using generic file detection.

```go
// Adding a CycloneDX SBOM path from user input
actions.SBOMPaths = []string{"/tmp/project/deps.cdx.json"}

```

```go
// Scan logic: selecting the CycloneDX extractor
sbomExtractors := scalibrplugin.Resolve([]string{"sbom"}, []string{}, &cpb.PluginConfig{})
for _, se := range sbomExtractors {
    sbomExtractor := se.(filesystem.Extractor)
    if sbomExtractor.FileRequired(simplefileapi.New(absPath, nil)) {
        // CycloneDX extractor matches the file name pattern
        overrideMap[absPath] = sbomExtractor
        break
    }
}

```

## Parsing CycloneDX Components

### Extracting Package Metadata

During the actual scan execution, the Scalibr framework invokes the selected CycloneDX extractor to parse the JSON structure. The extractor reads the CycloneDX document and builds a slice of `extractor.Package` objects representing each component defined in the SBOM. For each package, it attaches `cdxmeta.Metadata` containing the original component coordinates from the CycloneDX document.

### Location Tracking with CDXMetadata

The metadata includes **CDXLocations**, which preserves the specific component identifiers and nested positions within the SBOM hierarchy. This provenance data ensures that vulnerability results can reference exact paths within the original document, such as specific component IDs or nested dependency relationships.

## Annotating Vulnerability Sources

After extraction, **[`pkg/osvscanner/vulnerability_result.go`](https://github.com/google/osv-scanner/blob/main/pkg/osvscanner/vulnerability_result.go)** processes each package to determine its origin. If a package's plugin list contains `cdx.Name`, indicating it originated from CycloneDX parsing, the scanner appends the first CDX location to the source path. This creates a compound source string that provides precise traceability from vulnerability findings to specific SBOM entries.

```go
// Annotating the source path with CDX location data
if slices.Contains(p.Plugins, cdx.Name) {
    // p.Metadata is *cdxmeta.Metadata
    locations := p.Metadata.(*cdxmeta.Metadata).CDXLocations
    if len(locations) > 0 {
        source.Path = source.Path + ":" + locations[0] // e.g., sbom:/path/file.cdx.json:pkg:my-lib
    }
}

```

## Generating CycloneDX Output Reports

### Version-Specific BOM Creation

OSV-Scanner can emit its findings as CycloneDX-formatted SBOMs that include vulnerability data. The **[`internal/output/cyclonedx.go`](https://github.com/google/osv-scanner/blob/main/internal/output/cyclonedx.go)** file handles this by selecting a specific CycloneDX version—`models.CycloneDXVersion14`, `models.CycloneDXVersion15`, or `models.CycloneDXVersion16`—defined in **[`pkg/models/cyclonedx.go`](https://github.com/google/osv-scanner/blob/main/pkg/models/cyclonedx.go)**. It then invokes the appropriate BOM creator from **[`internal/output/sbom/models.go`](https://github.com/google/osv-scanner/blob/main/internal/output/sbom/models.go)**, such as `ToCycloneDX14Bom`, `ToCycloneDX15Bom`, or `ToCycloneDX16Bom`.

### Vulnerability Aggregation by PURL

The builders in **[`internal/output/sbom/cyclonedx_common.go`](https://github.com/google/osv-scanner/blob/main/internal/output/sbom/cyclonedx_common.go)** group packages by their **Package URL (PURL)** and inject vulnerability details into the BOM's metadata. This produces a standards-compliant CycloneDX document that describes not only the components but also their associated security vulnerabilities, encoded as JSON and written to the specified output writer.

```go
// Emit a CycloneDX BOM with discovered vulnerabilities
err := output.PrintCycloneDXResults(vulnResult, models.CycloneDXVersion15, os.Stdout)

```

## Summary

- **Detection**: Scanning CycloneDX files requires the `--sbom` flag, which triggers extractor resolution in [`pkg/osvscanner/scan.go`](https://github.com/google/osv-scanner/blob/main/pkg/osvscanner/scan.go) using Scalibr's plugin system.
- **Parsing**: The CycloneDX extractor validates files via `FileRequired` and parses components into `extractor.Package` objects with `CDXMetadata` containing precise location data.
- **Traceability**: Vulnerability results preserve SBOM provenance by appending CDX locations to source paths, creating traceable identifiers like `sbom:/path/file.cdx.json:component-id`.
- **Output**: The scanner supports generating CycloneDX 1.4, 1.5, and 1.6 output documents that aggregate vulnerabilities by PURL using version-specific builders in `internal/output/sbom/`.

## Frequently Asked Questions

### What file patterns does osv-scanner recognize for CycloneDX SBOMs?

The CycloneDX extractor identifies files based on CycloneDX-specific filename conventions, typically matching [`.cdx.json`](https://github.com/google/osv-scanner/blob/main/.cdx.json) extensions or similar patterns. When processing the `--sbom` input paths, the extractor's `FileRequired` method validates whether the target file matches these known CycloneDX signatures before attempting to parse the JSON structure.

### How does osv-scanner map vulnerabilities back to SBOM components?

After parsing, packages originating from CycloneDX sources contain metadata with `CDXLocations` arrays. In [`pkg/osvscanner/vulnerability_result.go`](https://github.com/google/osv-scanner/blob/main/pkg/osvscanner/vulnerability_result.go), the scanner checks for the `cdx.Name` plugin identifier and appends the first location entry to the source path, creating a composite string that points to the specific component within the original SBOM file.

### Can osv-scanner output CycloneDX format with vulnerability data?

Yes. The scanner can generate CycloneDX-formatted SBOMs that include vulnerability information using the appropriate output configuration. This invokes builders in [`internal/output/sbom/models.go`](https://github.com/google/osv-scanner/blob/main/internal/output/sbom/models.go) to create version-specific BOMs (1.4, 1.5, or 1.6) that group packages by PURL and embed vulnerability details according to the CycloneDX specification.

### Which CycloneDX specification versions are supported?

OSV-Scanner supports CycloneDX versions **1.4**, **1.5**, and **1.6**. The desired version is specified via configuration flags, and the corresponding creator function—such as `ToCycloneDX15Bom`—is selected from the `sbom.SpecVersionToBomCreator` map to ensure the output conforms to the chosen specification.