# sbomasm

sbomasm is a comprehensive SBOM management toolkit for assembling, editing, enriching, viewing, and cryptographically signing SBOMs. It supports both SPDX and CycloneDX formats and handles operations that span multiple SBOMs — merging microservice SBOMs into a platform-wide view, enriching components with license data, editing metadata for compliance, and signing SBOMs for integrity verification.

**Repository:** [github.com/interlynk-io/sbomasm](https://github.com/interlynk-io/sbomasm)

***

## Use Cases

| Operation        | When to Use                                                           |
| ---------------- | --------------------------------------------------------------------- |
| Assemble (merge) | Combine SBOMs from multiple services, containers, or modules into one |
| Edit             | Update metadata (supplier, author, version) before distribution       |
| Enrich           | Fill missing license information from ClearlyDefined                  |
| Remove           | Strip components or fields before sharing externally                  |
| View             | Inspect SBOM structure and dependencies                               |
| Sign / Verify    | Establish authenticity and detect tampering                           |

***

## Installation

### Homebrew (macOS/Linux)

```bash
brew tap interlynk-io/interlynk
brew install sbomasm
```

### Go Install

```bash
go install github.com/interlynk-io/sbomasm@latest
```

### Pre-Built Binaries

Download from the [GitHub releases page](https://github.com/interlynk-io/sbomasm/releases) for Linux (amd64, arm64), macOS (amd64, arm64), and Windows (amd64).

### Docker

```bash
docker run -v $(pwd):/data ghcr.io/interlynk-io/sbomasm:latest assemble \
  -n 'my-app' -v '1.0.0' -o /data/merged.json /data/sbom1.json /data/sbom2.json
```

### Build from Source

```bash
git clone https://github.com/interlynk-io/sbomasm.git
cd sbomasm
make build
```

### Verify Installation

```bash
sbomasm version
```

***

## Core Operations

### Assemble (Merge SBOMs)

Combine multiple SBOMs into a single document. Four merge strategies are available:

| Strategy     | Flag                    | Behavior                                                           |
| ------------ | ----------------------- | ------------------------------------------------------------------ |
| Hierarchical | `--hierMerge` (default) | Preserves component structure; nests input SBOMs under a new root  |
| Flat         | `--flatMerge`           | Removes relationships; flattens all components to the same level   |
| Assembly     | `--assemblyMerge`       | Treats each SBOM independently without linking to primary          |
| Augment      | `--augmentMerge`        | Enriches a primary SBOM with data from others; no new root created |

#### Hierarchical Merge (Default)

```bash
sbomasm assemble \
  -n 'platform-sbom' \
  -v '2.0.0' \
  -o merged.cdx.json \
  service-a.cdx.json service-b.cdx.json service-c.cdx.json
```

#### Flat Merge

```bash
sbomasm assemble \
  --flatMerge \
  -n 'platform-sbom' \
  -v '2.0.0' \
  -o merged.cdx.json \
  service-a.cdx.json service-b.cdx.json
```

#### Assembly Merge

```bash
sbomasm assemble \
  --assemblyMerge \
  -n 'platform-sbom' \
  -v '2.0.0' \
  -o merged.cdx.json \
  service-a.cdx.json service-b.cdx.json
```

#### Augment Merge

Enrich an existing SBOM with components from other SBOMs without changing the root structure:

```bash
sbomasm assemble \
  --augmentMerge \
  --primary base-sbom.cdx.json \
  --merge-mode if-missing-or-empty \
  -o enriched.cdx.json \
  additional-data.cdx.json
```

Merge modes for augment:

* `if-missing-or-empty` (default) — only fills in empty or missing fields
* `overwrite` — replaces existing values

#### Output Format Control

```bash
# CycloneDX JSON (default)
sbomasm assemble -n 'app' -v '1.0' -o out.cdx.json sbom1.json sbom2.json

# CycloneDX XML
sbomasm assemble -n 'app' -v '1.0' --xml -o out.cdx.xml sbom1.json sbom2.json

# SPDX JSON
sbomasm assemble -n 'app' -v '1.0' --outputSpecSpdx -o out.spdx.json sbom1.json sbom2.json

# Specific spec version
sbomasm assemble -n 'app' -v '1.0' --outputSpecVersion 1.5 -o out.json sbom1.json sbom2.json
```

#### Configuration-Driven Assembly

Generate a configuration template:

```bash
sbomasm generate
```

Example configuration file (`assemble-config.yaml`):

```yaml
app:
  name: 'platform-sbom'
  version: '2.0.0'
  type: 'application'
  description: 'Combined platform SBOM'
  supplier:
    name: 'Acme Corp'
    email: 'security@acme.com'
  author:
    - name: 'Security Team'
      email: 'security@acme.com'
  licenses:
    - id: 'Apache-2.0'
  purl: 'pkg:generic/acme/platform@2.0.0'
  cpe: 'cpe:2.3:a:acme:platform:2.0.0:*:*:*:*:*:*:*'

output:
  spec: cyclonedx
  file_format: json
  file: 'platform-sbom.cdx.json'

assemble:
  hierarchical_merge: true
  include_components: true
  include_dependency_graph: true
```

Run with configuration:

```bash
sbomasm assemble --configPath assemble-config.yaml service-a.cdx.json service-b.cdx.json
```

#### Assemble Parameters

| Parameter             | Short | Required          | Default               | Description                |
| --------------------- | ----- | ----------------- | --------------------- | -------------------------- |
| `--name`              | `-n`  | Yes (non-augment) | —                     | Name for assembled SBOM    |
| `--version`           | `-v`  | Yes (non-augment) | —                     | Version for assembled SBOM |
| `--output`            | `-o`  | No                | stdout                | Output file path           |
| `--type`              | `-t`  | No                | `application`         | Component type             |
| `--configPath`        | `-c`  | No                | —                     | YAML configuration file    |
| `--hierMerge`         | `-m`  | No                | Default               | Hierarchical merge         |
| `--flatMerge`         | `-f`  | No                | —                     | Flat merge                 |
| `--assemblyMerge`     | `-a`  | No                | —                     | Assembly merge             |
| `--augmentMerge`      | —     | No                | —                     | Augment merge              |
| `--primary`           | `-p`  | Augment only      | —                     | Primary SBOM file          |
| `--merge-mode`        | —     | No                | `if-missing-or-empty` | Merge mode for augment     |
| `--outputSpecCdx`     | `-g`  | No                | Default               | CycloneDX output           |
| `--outputSpecSpdx`    | `-s`  | No                | —                     | SPDX output                |
| `--outputSpecVersion` | `-e`  | No                | Latest                | Spec version               |
| `--xml`               | `-x`  | No                | —                     | XML output                 |
| `--json`              | `-j`  | No                | Default               | JSON output                |

**Component type values:** `application`, `framework`, `library`, `container`, `device`, `firmware`

***

### Edit SBOM Metadata

Modify metadata on the SBOM document, primary component, or specific components.

#### Edit Document Metadata

```bash
sbomasm edit \
  --subject document \
  --supplier "Acme Corp (https://acme.com)" \
  --author "Security Team" \
  --tool "sbomasm (v2.0)" \
  --timestamp \
  -o updated.cdx.json \
  original.cdx.json
```

#### Edit Primary Component

```bash
sbomasm edit \
  --subject primary-component \
  --name "my-application" \
  --version "2.1.0" \
  --purl "pkg:generic/acme/my-application@2.1.0" \
  --license "Apache-2.0" \
  --description "Main application component" \
  -o updated.cdx.json \
  original.cdx.json
```

#### Edit a Specific Component

```bash
sbomasm edit \
  --subject component-name-version \
  --search "log4j-core:2.17.0" \
  --license "Apache-2.0" \
  --supplier "Apache Foundation (https://apache.org)" \
  -o updated.cdx.json \
  original.cdx.json
```

#### Edit Modes

| Flag        | Behavior                                           |
| ----------- | -------------------------------------------------- |
| (default)   | Overwrite existing values                          |
| `--append`  | Add to existing values (e.g., additional licenses) |
| `--missing` | Only set if the field is currently empty           |

#### Editable Fields

| Field       | Flag            | Format                             |
| ----------- | --------------- | ---------------------------------- |
| Name        | `--name`        | String                             |
| Version     | `--version`     | String                             |
| Type        | `--type`        | Component type value               |
| Supplier    | `--supplier`    | `"Name (url)"`                     |
| Author      | `--author`      | String (repeatable)                |
| PURL        | `--purl`        | Package URL                        |
| CPE         | `--cpe`         | CPE identifier                     |
| License     | `--license`     | SPDX expression (repeatable)       |
| Hash        | `--hash`        | `"Algorithm (value)"` (repeatable) |
| Tool        | `--tool`        | `"Name (version)"` (repeatable)    |
| Copyright   | `--copyright`   | String                             |
| Lifecycle   | `--lifecycle`   | Phase name (repeatable)            |
| Description | `--description` | String                             |
| Repository  | `--repository`  | URL                                |
| Timestamp   | `--timestamp`   | Flag — adds current time           |

***

### Enrich SBOMs

Fill missing license information using the ClearlyDefined API.

```bash
# Enrich missing licenses
sbomasm enrich --fields license -o enriched.cdx.json sbom.cdx.json

# Force-replace existing licenses
sbomasm enrich --fields license --force -o enriched.cdx.json sbom.cdx.json

# Custom license joining operator
sbomasm enrich --fields license --license-exp-join AND -o enriched.cdx.json sbom.cdx.json

# Adjust batch size and retry behavior
sbomasm enrich --fields license --chunk-size 50 --max-retries 3 --max-wait 10 -o enriched.cdx.json sbom.cdx.json
```

| Parameter            | Short | Default | Description                                      |
| -------------------- | ----- | ------- | ------------------------------------------------ |
| `--fields`           | —     | —       | Fields to enrich (currently: `license`)          |
| `--output`           | `-o`  | stdout  | Output file                                      |
| `--force`            | `-f`  | Off     | Replace existing values                          |
| `--max-retries`      | `-r`  | `2`     | API retry attempts                               |
| `--max-wait`         | `-w`  | `5`     | Max wait time (seconds)                          |
| `--license-exp-join` | `-j`  | `OR`    | License expression operator: `OR`, `AND`, `WITH` |
| `--chunk-size`       | `-c`  | `100`   | Batch size for API requests                      |

The enrichment process reports:

* Total components
* Components selected for enrichment
* Successfully enriched count
* Skipped count
* Failed count

***

### Remove Components or Fields

Strip components or metadata before external distribution.

```bash
# Remove a specific component
sbomasm rm --components --name "internal-lib" -o cleaned.cdx.json sbom.cdx.json

# Remove a field from all components
sbomasm rm --field author --scope component --all -o cleaned.cdx.json sbom.cdx.json

# Remove dependencies
sbomasm rm --dependency --id "pkg:npm/internal@1.0.0" -o cleaned.cdx.json sbom.cdx.json

# Dry run — preview changes
sbomasm rm --components --name "internal-*" --dry-run sbom.cdx.json

# Summary of changes
sbomasm rm --components --name "internal-lib" --summary -o cleaned.cdx.json sbom.cdx.json
```

***

### View SBOM Structure

Inspect SBOM contents without modifying the file.

```bash
# Default tree view
sbomasm view sbom.cdx.json

# Verbose — show all fields
sbomasm view --verbose sbom.cdx.json

# Show only licenses
sbomasm view --only-licenses sbom.cdx.json

# Filter by component type
sbomasm view --filter-type "library,framework" sbom.cdx.json

# Show vulnerabilities with severity filter
sbomasm view --vulnerabilities --min-severity high sbom.cdx.json

# Limit tree depth
sbomasm view --max-depth 2 sbom.cdx.json

# Flat list format
sbomasm view --format flat sbom.cdx.json

# JSON output
sbomasm view --format json -o structure.json sbom.cdx.json

# Hide disconnected components
sbomasm view --hide-islands sbom.cdx.json
```

***

### Sign and Verify SBOMs

Cryptographically sign SBOMs for integrity verification using the SecureSBOM service.

#### Sign

```bash
sbomasm sign \
  --key-id "your-key-id" \
  --api-key "$SECURE_SBOM_API_KEY" \
  --output signed.cdx.json \
  sbom.cdx.json
```

For SPDX (detached signature):

```bash
sbomasm sign \
  --key-id "your-key-id" \
  --api-key "$SECURE_SBOM_API_KEY" \
  --detached \
  --output signature.b64 \
  sbom.spdx.json
```

#### Verify

```bash
# CycloneDX (embedded signature)
sbomasm verify \
  --key-id "your-key-id" \
  --api-key "$SECURE_SBOM_API_KEY" \
  signed.cdx.json

# SPDX (detached signature)
sbomasm verify \
  --key-id "your-key-id" \
  --api-key "$SECURE_SBOM_API_KEY" \
  --signature "$(cat signature.b64)" \
  sbom.spdx.json
```

| Parameter    | Default                | Description                      |
| ------------ | ---------------------- | -------------------------------- |
| `--key-id`   | —                      | Signing key ID (required)        |
| `--api-key`  | `$SECURE_SBOM_API_KEY` | API key for SecureSBOM service   |
| `--base-url` | Default service URL    | Custom SecureSBOM endpoint       |
| `--output`   | stdout                 | Output file                      |
| `--detached` | Off                    | Return detached signature (SPDX) |
| `--timeout`  | `30s`                  | Request timeout                  |
| `--retry`    | `3`                    | Retry attempts                   |

***

## Supported Formats

### Input

| Spec      | Versions      | File Formats         |
| --------- | ------------- | -------------------- |
| SPDX      | 2.1, 2.2, 2.3 | JSON, XML, Tag-Value |
| CycloneDX | 1.0 – 1.6     | JSON, XML            |

### Output

| Spec      | Default Version | File Formats |
| --------- | --------------- | ------------ |
| SPDX      | 2.3             | JSON         |
| CycloneDX | 1.6             | JSON, XML    |

Formats are auto-detected on input. Cross-format assembly (mixing SPDX and CycloneDX inputs) is supported — the output format is determined by flags.

***

## Advanced Usage

### Multi-Module Builds

For projects with multiple build modules (e.g., microservices, monorepos):

```bash
# Step 1: Generate per-module SBOMs during build
cd service-a && syft . -o cyclonedx-json > ../sboms/service-a.cdx.json
cd service-b && syft . -o cyclonedx-json > ../sboms/service-b.cdx.json
cd service-c && syft . -o cyclonedx-json > ../sboms/service-c.cdx.json

# Step 2: Assemble into platform SBOM
sbomasm assemble \
  -n 'platform' \
  -v '$(git describe --tags)' \
  -t application \
  -o platform-sbom.cdx.json \
  sboms/*.cdx.json

# Step 3: Enrich with license data
sbomasm enrich --fields license -o platform-sbom-enriched.cdx.json platform-sbom.cdx.json

# Step 4: Score quality
sbomqs score platform-sbom-enriched.cdx.json

# Step 5: Upload to Interlynk
pylynk upload --prod 'platform' --sbom platform-sbom-enriched.cdx.json
```

### Large SBOM Handling

For SBOMs with thousands of components:

* **Batch assembly:** Assemble in stages — merge groups of SBOMs first, then merge the results.
* **Enrichment chunking:** Use `--chunk-size 50` to reduce memory usage during license enrichment.
* **View depth limiting:** Use `--max-depth 2` and `--hide-islands` for readable output.
* **JSON output:** Use `--format json` for machine processing rather than tree rendering.

```bash
# Stage 1: Merge groups
sbomasm assemble -n 'batch-1' -v '1.0' -o batch1.json group1/*.json
sbomasm assemble -n 'batch-2' -v '1.0' -o batch2.json group2/*.json

# Stage 2: Final assembly
sbomasm assemble -n 'complete' -v '1.0' -o final.json batch1.json batch2.json
```

### Dependency-Track Integration

Fetch SBOMs directly from Dependency-Track, assemble, and optionally upload back:

```bash
sbomasm assemble dt \
  --url https://dtrack.example.com \
  --api-key "$DT_API_KEY" \
  -n 'combined' \
  -v '1.0.0' \
  -o combined.cdx.json \
  <project-uuid-1> <project-uuid-2>
```

### CI/CD Pipeline Example

```yaml
# GitHub Actions: Full SBOM pipeline
name: SBOM Pipeline
on:
  release:
    types: [published]

jobs:
  sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Generate SBOMs
        run: |
          syft ./service-a -o cyclonedx-json > service-a.cdx.json
          syft ./service-b -o cyclonedx-json > service-b.cdx.json

      - name: Assemble Platform SBOM
        run: |
          sbomasm assemble \
            -n '${{ github.event.repository.name }}' \
            -v '${{ github.event.release.tag_name }}' \
            -o platform.cdx.json \
            service-a.cdx.json service-b.cdx.json

      - name: Enrich Licenses
        run: sbomasm enrich --fields license -o platform-enriched.cdx.json platform.cdx.json

      - name: Quality Gate
        run: |
          SCORE=$(sbomqs score --json platform-enriched.cdx.json | jq -r '.files[0].sbom_quality_score')
          if (( $(echo "$SCORE < 7.0" | bc -l) )); then
            echo "::error::SBOM quality $SCORE below threshold 7.0"
            exit 1
          fi

      - name: Upload to Interlynk
        env:
          INTERLYNK_SECURITY_TOKEN: ${{ secrets.INTERLYNK_SERVICE_TOKEN }}
        run: pylynk upload --prod '${{ github.event.repository.name }}' --sbom platform-enriched.cdx.json
```

***

## Error Handling

### Common Errors

| Error                       | Cause                                       | Resolution                                                  |
| --------------------------- | ------------------------------------------- | ----------------------------------------------------------- |
| `file not found`            | Invalid input path                          | Verify file path; use absolute paths in Docker              |
| `unsupported format`        | Unrecognized SBOM format                    | Ensure input is valid CycloneDX or SPDX                     |
| `name and version required` | Missing `--name` or `--version`             | Provide both for non-augment assembly                       |
| `primary file required`     | Augment merge without `--primary`           | Specify `--primary` with augment merge                      |
| `invalid reference`         | Dependency references nonexistent component | Fix the source SBOM; ensure all referenced components exist |
| ClearlyDefined API timeout  | Network or rate limiting                    | Increase `--max-wait` and `--max-retries`                   |
| Signing service unavailable | SecureSBOM API down                         | Check service status; increase `--timeout`                  |

### Debug Mode

Enable debug logging globally:

```bash
sbomasm --debug assemble -n 'app' -v '1.0' -o out.json input.json
```

Debug output includes processing flow details, component matching decisions, deduplication results, and API request/response information.

***

## Best Practices

### Assembly

* Use **hierarchical merge** for platform-level SBOMs where component provenance matters.
* Use **flat merge** when downstream consumers need a simple component list.
* Use **augment merge** to enrich vendor-provided SBOMs without altering their structure.
* Include `--type` to set the correct component type (`application`, `container`, `library`).
* Store assembly configuration in version control alongside your build scripts.

### Editing

* Use `--missing` mode to fill gaps without overwriting vendor-provided metadata.
* Use `--append` to add supplementary licenses or authors without removing existing ones.
* Edit the `document` subject to set creation tool and timestamp metadata before distribution.

### Enrichment

* Run enrichment after assembly to process all components in one pass.
* Use `--license-exp-join AND` for conservative license interpretation in regulated environments.
* Review enrichment reports — failed components may need manual attention.

### Security

* Sign SBOMs before distributing to external parties.
* Verify received SBOMs before importing into your supply chain management system.
* Store signing API keys in a secrets manager; never commit to source control.
* Strip internal components (`sbomasm rm`) before sharing SBOMs externally.

***

## Common Misconfigurations

| Issue                                        | Symptom                       | Fix                                                     |
| -------------------------------------------- | ----------------------------- | ------------------------------------------------------- |
| Missing `--name` and `--version` on assemble | Error at startup              | Always provide both unless using augment merge          |
| Mixing formats without output spec flag      | Unexpected output format      | Explicitly set `--outputSpecCdx` or `--outputSpecSpdx`  |
| Augment without `--primary`                  | Error requiring primary file  | Specify the base SBOM with `--primary`                  |
| Large enrichment without `--chunk-size`      | Timeouts or high memory usage | Set `--chunk-size 50` for SBOMs with 1000+ components   |
| Signing without `SECURE_SBOM_API_KEY`        | Authentication error          | Set the environment variable or use `--api-key`         |
| Editing with default overwrite mode          | Vendor metadata lost          | Use `--missing` or `--append` to preserve existing data |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.interlynk.io/productivity-tools/sbomasm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
