# Software Bill of Materials (SBOM) & Supply Chain Security

This document outlines the **Software Bill of Materials (SBOM)** architecture in GoClaw, supported standards, distribution mechanisms, and Information Security (InfoSec) placement controls.

---

## 1. Overview & Objectives

Enterprise and pilot customers (e.g. banking, fintech, government, and telecommunications) require a verifiable Software Bill of Materials (SBOM) to comply with cybersecurity frameworks such as ISO/IEC 27001, PCI-DSS, NIST SP 800-218 (SSDF), and US Executive Order 14028.

GoClaw's SBOM infrastructure satisfies the following objectives:
1. **Continuous Vulnerability Management**: Enables automated dependency auditing via vulnerability scanners such as Grype, Trivy, Snyk, and OWASP Dependency-Track.
2. **Rapid Incident Response (0-Day Triage)**: Instantly determines whether GoClaw utilizes a vulnerable library when critical zero-day vulnerabilities (e.g. Log4j, XZ backdoor, or Go `net/http` DoS vectors) emerge.
3. **Supply Chain Integrity**: Records, for every dependency, the `h1:` module checksum the build actually linked, in the same form `go.sum` stores it — so an auditor can verify the inventory against the module graph with `go mod verify`. The SBOM files themselves are covered by SHA-256 digests in `checksums.json`.
4. **Dependency Inventory for License Review**: Provides the exact module path and version of every linked component, which is the input a license review needs. **The SBOM does not assert a license per dependency** — in SPDX those fields are `NOASSERTION`, and CycloneDX leaves the license field out. See "License data" below.

---

## 2. Information Security (InfoSec) Threat Model & Placement Controls

Exposing software dependency inventories naively can introduce security risks. GoClaw implements a 3-tier placement and access model to mitigate these threats:

```mermaid
flowchart LR
    subgraph SBOM["GoClaw SBOM Architecture"]
        direction LR
        T1["<b>1. Release / Supply Chain</b><br/>• goclaw.ulab.mn/releases/<br/>• Current release only<br/>• SHA256 in checksums.json<br/>• CycloneDX 1.5 + SPDX 2.3"]
        T2["<b>2. Live Gateway</b><br/>• /api/admin/sbom<br/>• AuthMiddleware<br/>• Token Protected<br/>• Anti-Recon"]
        T3["<b>3. Offline CLI</b><br/>• goclaw sbom<br/>• Zero Network<br/>• Binary Built-in<br/>• Pipe to Grype"]
    end
```

### A. Anti-Reconnaissance Control
- **Threat**: Publishing an unauthenticated SBOM endpoint on a public server exposes exact versions of all internal libraries and database drivers. Attackers can crawl this endpoint to identify unpatched or zero-day CVEs before administrators can update.
- **Control**: On the live gateway, SBOM access requires a valid gateway token via **`GET /api/admin/sbom`** (and `/api/sbom`, the same handler), guarded by `AuthMiddleware`.
  - Unauthenticated requests receive `401 Unauthorized`.
  - The endpoint is never exposed publicly without valid gateway credentials.
  - Note that GoClaw has a single gateway token rather than per-role credentials: the `/admin/` path segment is naming, not a second privilege tier. Anyone who can open the dashboard can read the SBOM, so treat the token as the control boundary.

### B. Supply Chain Integrity
- **Threat**: Attackers or intermediaries could tamper with distributed SBOM manifests or distribute mismatched inventories.
- **Control**: Official release SBOMs are generated in the GitHub Actions release workflow from the release's linux/amd64 binary. Their SHA-256 digests are published in `checksums.json`, a JSON object that maps each asset name to its digest. It is not in `sha256sum` format, so `sha256sum -c` cannot read it: compare the digest as in [Release Distribution & Checksum Verification](#3-release-distribution--checksum-verification).
- **Limits**: `checksums.json` is served from the same host as the files it covers, so a match shows that a download is complete and uncorrupted, not who produced it. The SBOMs and `checksums.json` are not signed. The macOS binaries are code-signed when the release has a signing certificate configured; build provenance attestations for the binaries are optional and off unless enabled for the repository.

### C. Air-Gapped & Offline Inspection
- **Threat**: Security teams in air-gapped or restricted networks cannot query remote servers or download external scanning dependencies.
- **Control**: The `goclaw sbom` CLI command extracts the SBOM directly from the Go binary's embedded runtime metadata (`runtime/debug.ReadBuildInfo()`). It requires zero internet access and executes in milliseconds.

### D. License Data — What Is and Is Not Included

GoClaw's own license is declared in both formats: CycloneDX carries it as the
metadata component license, SPDX as `LicenseRef-GoClaw-Binary-License` with a matching
`hasExtractedLicensingInfos` entry.

**Per-dependency licenses are not asserted.** Go's build metadata
(`runtime/debug.ReadBuildInfo`) carries module paths, versions and checksums, but no
license information, and GoClaw does not ship a license database to infer it. In SPDX
every dependency therefore reports `NOASSERTION`, which is the SPDX term for "not
evaluated" — it is not a claim that a component is unlicensed. In CycloneDX a
dependency has no `licenses` field at all.

For license review, use the SBOM as the authoritative component inventory and pair it
with `THIRD_PARTY_NOTICES.md`, or run a dedicated license scanner over the module graph.
An exhaustive per-release license bundle is available from security@ulab.mn.

### E. Module Checksums

Each dependency carries the `h1:` value recorded in `go.sum` — as the `go:mod:h1`
property in CycloneDX, and as an `OTHER` external reference in SPDX. This is a Go
*dirhash* (a hash over the module's file listing), **not** the SHA-256 of a downloadable
artifact, so it is deliberately not published under a `SHA-256` label that no verifier
could reproduce. It is checkable directly against `go.sum` and `go mod verify`.

---

## 3. Supported Formats

| Format | Specification | Primary Use Case | Media Type |
|---|---|---|---|
| **CycloneDX 1.5** | OWASP Standard | Vulnerability scanning (Grype, Trivy, Snyk, Dependency-Track) | `application/vnd.cyclonedx+json` |
| **SPDX 2.3** | ISO/IEC 5962:2021 | Procurement documentation, dependency inventory for legal review | `application/spdx+json` |
| **Summary** | Human-Readable Text / JSON | Operator inspections, terminal review, Web UI dashboard | `application/json` / `text/plain` |

---

## 4. Usage Guide

### 1. Offline Inspection via CLI

```bash
# View human-readable dependency summary
goclaw sbom

# Export CycloneDX 1.5 JSON for vulnerability scanners
goclaw sbom --format cyclonedx --output goclaw-sbom.cdx.json

# Export SPDX 2.3 JSON
goclaw sbom --format spdx --output goclaw-sbom.spdx.json

# Pipe directly into Anchore Grype for instant scanning (zero-file workflow)
goclaw sbom -f cyclonedx | grype

# Scan using Aqua Trivy
goclaw sbom -f cyclonedx -o sbom.json && trivy sbom sbom.json
```

### 2. Fetching via Authenticated Admin API

On a running gateway instance, operators or automated compliance agents can retrieve the SBOM with a bearer token:

```bash
# Download CycloneDX 1.5 JSON
curl -H "X-Goclaw-Token: <GATEWAY_AUTH_TOKEN>" \
  "http://localhost:8080/api/admin/sbom?format=cyclonedx" \
  -o goclaw-sbom.cdx.json

# Download SPDX 2.3 JSON
curl -H "X-Goclaw-Token: <GATEWAY_AUTH_TOKEN>" \
  "http://localhost:8080/api/admin/sbom?format=spdx" \
  -o goclaw-sbom.spdx.json

# Direct browser download with attachment header
http://localhost:8080/api/admin/sbom?format=cyclonedx&download=1
```

### 3. Release Distribution & Checksum Verification

Only the current release is served at `https://goclaw.ulab.mn/releases/<version>/`;
`/releases/latest.json` names it (for example `{"version":"v0.0.96",…}`). A request
for an earlier version's files there returns 404. Every release from v0.2.2 on also
stays at `https://storage.googleapis.com/goclaw-releases/releases/<version>/`, the
same files and `checksums.json`, so the commands below work there with that
`BASE_URL`. The files of releases before that are available from security@ulab.mn.

```bash
VERSION=$(curl -fsSL https://goclaw.ulab.mn/releases/latest.json \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["version"])')
BASE_URL="https://goclaw.ulab.mn/releases/${VERSION}"
SBOM="goclaw-${VERSION}-linux-amd64-sbom.cdx.json"

# Download SBOM and checksums manifest
curl -fsSL "${BASE_URL}/${SBOM}" -o "${SBOM}"
curl -fsSL "${BASE_URL}/checksums.json" -o checksums.json

# Verify cryptographic integrity
EXPECTED_SHA=$(grep -o "\"${SBOM}\"[[:space:]]*:[[:space:]]*\"[^\"]*" checksums.json | grep -o '[^"]*$')
ACTUAL_SHA=$(shasum -a 256 "${SBOM}" | awk '{print $1}')

if [ "$EXPECTED_SHA" = "$ACTUAL_SHA" ]; then
    echo "✅ SBOM Integrity Verified: SHA-256 matches."
else
    echo "❌ Integrity Mismatch!"
    exit 1
fi
```

### 4. Integration with OWASP Dependency-Track

Automate continuous supply-chain monitoring by posting release SBOMs to your internal Dependency-Track server:

```bash
curl -X "POST" "https://dtrack.corp.example.com/api/v1/bom" \
     -H "X-Api-Key: $DTRACK_API_KEY" \
     -H "Content-Type: multipart/form-data" \
     -F "projectName=GoClaw" \
     -F "projectVersion=${VERSION}" \
     -F "autoCreate=true" \
     -F "bom=@goclaw-sbom.cdx.json"
```

---

## 5. Codebase Structure

- `internal/sbom/sbom.go`: Core collector, module dependency model, and validation of Go `h1:` module checksums.
- `internal/sbom/cyclonedx.go`: OWASP CycloneDX 1.5 JSON serializer.
- `internal/sbom/spdx.go`: Linux Foundation SPDX 2.3 JSON serializer.
- `internal/sbom/summary.go`: Component categorizer and human-readable terminal formatter.
- `internal/cli/cmd_sbom.go`: CLI command implementation for `goclaw sbom`.
- `internal/gateway/handler_sbom.go`: Authenticated API handler for `/api/admin/sbom` and `/api/sbom`.
- `web/js/views/system.js` & `web/index.html`: Admin Web UI card for viewing and downloading SBOMs.
- `.github/workflows/release.yml`: Release CI/CD automation generating official CycloneDX and SPDX assets.
