Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

*Most tools tell you what's wrong. CVE Lite CLI tells you what to run.*

[![OWASP Lab Project](https://img.shields.io/badge/OWASP-Lab%20Project-48A646?logo=owasp)](https://owasp.org/cve-lite-cli)
Expand Down Expand Up @@ -366,7 +365,7 @@ This is intentional. Because CVE Lite CLI is a security-oriented tool, runtime d
- [Remediation Strategy guide](https://owasp.org/cve-lite-cli/docs/remediation-strategy) - how CVE Lite CLI chooses upgrade targets and parent update paths
- [Release Cooldown Awareness guide](https://owasp.org/cve-lite-cli/docs/release-cooldown) - how CVE Lite CLI reads your package manager's cooldown and warns on fix versions newer than the window you trust
- [SPDX SBOM guide](https://owasp.org/cve-lite-cli/docs/spdx) - SPDX 2.3 output, how findings are attached, NTIA minimum elements, and inventory-only mode
- [CycloneDX SBOM guide](https://owasp.org/cve-lite-cli/docs/cyclonedx) - CycloneDX 1.4 output and Dependency-Track integration
- [CycloneDX SBOM guide](https://owasp.org/cve-lite-cli/docs/cyclonedx) - CycloneDX 1.6 output and Dependency-Track integration

## Security and verification

Expand Down Expand Up @@ -441,4 +440,4 @@ Thank you to those who sponsor CVE Lite CLI and help keep it maintained:

## License

MIT - built in public and maintained as an OWASP Foundation Project by Sonu Kapoor.
MIT - built in public and maintained as an OWASP Foundation Project by Sonu Kapoor.
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ inputs:
required: false
default: "true"
cdx:
description: "Write CycloneDX 1.4 SBOM to a timestamped .cdx.json file"
description: "Write CycloneDX 1.6 SBOM to a timestamped .cdx.json file"
required: false
default: "false"
ca-cert:
Expand Down Expand Up @@ -520,4 +520,4 @@ runs:
if [[ "${EXIT_CODE:-0}" -gt 1 ]]; then
exit "${EXIT_CODE:-0}"
fi
fi
fi
2 changes: 1 addition & 1 deletion src/cli/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function printHelp(): void {
" --json Save scan results to a timestamped JSON file",
" --report [dir] Generate an HTML report in [dir] (default: ./cve-report)",
" --sarif Write SARIF 2.1.0 output to a timestamped .sarif file",
" --sbom <format> Write an SBOM: cyclonedx (1.4) or spdx (2.3), to a timestamped file",
" --sbom <format> Write an SBOM: cyclonedx (1.6) or spdx (2.3), to a timestamped file",
" --sbom-inventory-only Omit the vulnerability overlay from --sbom, leaving a pure inventory",
" --cdx Alias for --sbom cyclonedx",
" --no-open Don't auto-open the report in the browser",
Expand Down
4 changes: 2 additions & 2 deletions src/output/cyclonedx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type CycloneDxMetadata = {

type CycloneDxBom = {
bomFormat: "CycloneDX";
specVersion: "1.4";
specVersion: "1.6";
version: number;
serialNumber: string;
metadata: CycloneDxMetadata;
Expand Down Expand Up @@ -137,7 +137,7 @@ export function buildCycloneDxBom(

return {
bomFormat: "CycloneDX",
specVersion: "1.4",
specVersion: "1.6",
version: 1,
serialNumber: `urn:uuid:${randomUUID()}`,
metadata,
Expand Down
51 changes: 50 additions & 1 deletion tests/cyclonedx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe("buildCycloneDxBom", () => {
it("has valid top-level shape", () => {
const bom = buildCycloneDxBom(allPackages, [], null, "1.0.0");
expect(bom.bomFormat).toBe("CycloneDX");
expect(bom.specVersion).toBe("1.4");
expect(bom.specVersion).toBe("1.6");
expect(bom.serialNumber).toMatch(/^urn:uuid:/);
expect(bom.metadata).toBeDefined();
expect(Array.isArray(bom.components)).toBe(true);
Expand Down Expand Up @@ -127,3 +127,52 @@ describe("buildCycloneDxBom", () => {
expect(bom.metadata.component).toBeUndefined();
});
});

describe("buildCycloneDxBom - CycloneDX 1.6 schema conformance", () => {
// Asserts the required fields from the 1.6 schema directly, without adding
// a schema-validation dependency. Each test pins specVersion to 1.6 first:
// component type/name, affects[].ref, and the scoreMethod enum values were
// already required/valid under 1.4, so without the explicit specVersion
// assertion these would pass unchanged on a regression back to 1.4.
const allPackages = [makePackage("lodash", "4.17.21")];
const findings = [makeFinding("lodash", "4.17.21", "CVE-2021-1234")];

it("declares the current default CycloneDX spec version", () => {
const bom = buildCycloneDxBom(allPackages, findings, null, "1.0.0");
expect(bom.bomFormat).toBe("CycloneDX");
expect(bom.specVersion).toBe("1.6");
});

it("on CycloneDX 1.6, every component satisfies the required component fields (type, name)", () => {
const bom = buildCycloneDxBom(allPackages, findings, null, "1.0.0");
expect(bom.specVersion).toBe("1.6");
for (const component of bom.components) {
expect(component.type).toBeTruthy();
expect(component.name).toBeTruthy();
}
});

it("on CycloneDX 1.6, every vulnerability.affects entry satisfies the required affects field (ref)", () => {
const bom = buildCycloneDxBom(allPackages, findings, null, "1.0.0");
expect(bom.specVersion).toBe("1.6");
for (const vuln of bom.vulnerabilities) {
expect(vuln.affects.length).toBeGreaterThan(0);
for (const affect of vuln.affects) {
expect(affect.ref).toBeTruthy();
}
}
});

it("on CycloneDX 1.6, every rating.method is one of the scoreMethod enum values, including 1.6-only additions", () => {
// CVSSv4 and SSVC are 1.6 additions; they are absent from the 1.4
// scoreMethod enum, so this list itself is version-specific.
const validMethods = ["CVSSv2", "CVSSv3", "CVSSv31", "CVSSv4", "OWASP", "SSVC", "other"];
const bom = buildCycloneDxBom(allPackages, findings, null, "1.0.0");
expect(bom.specVersion).toBe("1.6");
for (const vuln of bom.vulnerabilities) {
for (const rating of vuln.ratings) {
expect(validMethods).toContain(rating.method);
}
}
});
});
2 changes: 1 addition & 1 deletion website/docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ cve-lite install-skill
| `--verbose` | off | Full output: severity table, fix plan, findings table (with EPSS and EPSS Priority columns), coverage notes | `cve-lite . --verbose` |
| `--json` | off | Machine-readable JSON output (suppresses all other output); each finding includes `epssScores` and `prioritySignal` when EPSS data is available | `cve-lite . --json` |
| `--sarif` | off | Write SARIF 2.1.0 output to a timestamped `.sarif` file; can be combined with `--json` and `--report` | `cve-lite . --sarif` |
| `--sbom <format>` | off | Write an SBOM to a timestamped file. Formats: `cyclonedx` (1.4, `.cdx.json`), `spdx` or `spdx2.3` (SPDX 2.3, `.spdx.json`). Can be combined with `--json` and `--sarif`; cannot be combined with `--report` or `--fix` | `cve-lite . --sbom spdx` |
| `--sbom <format>` | off | Write an SBOM to a timestamped file. Formats: `cyclonedx` (1.6, `.cdx.json`), `spdx` or `spdx2.3` (SPDX 2.3, `.spdx.json`). Can be combined with `--json` and `--sarif`; cannot be combined with `--report` or `--fix` | `cve-lite . --sbom spdx` |
| `--sbom-inventory-only` | off | Omit the vulnerability overlay from `--sbom`, leaving a pure inventory. Requires `--sbom` | `cve-lite . --sbom spdx --sbom-inventory-only` |
| `--cdx` | off | Alias for `--sbom cyclonedx`, kept for compatibility | `cve-lite . --cdx` |
| `--report[=<path>]` | off / `./cve-report` | Generate an HTML report with EPSS and EPSS Priority columns and an interactive priority legend; optional path sets output directory (default `./cve-report`); opens in browser by default; cannot be used with `--json` | `cve-lite . --report`<br/>`cve-lite . --report ./reports` |
Expand Down
2 changes: 1 addition & 1 deletion website/docs/cyclonedx.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ sidebar_label: CycloneDX SBOM

# CycloneDX SBOM Output

CVE Lite CLI can write a [CycloneDX 1.4](https://cyclonedx.org/) Software Bill of Materials (SBOM) — a standard format supported by Dependency-Track, GitHub, Azure DevOps, and many enterprise security platforms.
CVE Lite CLI can write a [CycloneDX 1.6](https://cyclonedx.org/) Software Bill of Materials (SBOM) — a standard format supported by Dependency-Track, GitHub, Azure DevOps, and many enterprise security platforms.

## Generating a CycloneDX SBOM

Expand Down
2 changes: 1 addition & 1 deletion website/docs/github-action.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ For usage patterns and complete workflow examples, see [Workflow Integration](./
|---|---|---|---|
| `sarif` | `false` | Write SARIF 2.1.0 output to a timestamped `.sarif` file for GitHub Code Scanning upload | `sarif: "true"` |
| `report` | _(none)_ | Write an HTML report to this directory path; `--no-open` is applied automatically | `report: "./cve-report"` |
| `cdx` | `false` | Write a CycloneDX 1.4 SBOM to a timestamped `.cdx.json` file | `cdx: "true"` |
| `cdx` | `false` | Write a CycloneDX 1.6 SBOM to a timestamped `.cdx.json` file | `cdx: "true"` |

---

Expand Down
2 changes: 1 addition & 1 deletion website/docs/spdx.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This writes a timestamped file (`cve-lite-scan-<timestamp>.spdx.json`) to the cu
`--sbom` accepts `cyclonedx`, `spdx`, and `spdx2.3`. Plain `spdx` means SPDX 2.3 today and will keep meaning 2.3, so a pinned CI command will not change format under you.

```bash
cve-lite . --sbom cyclonedx # CycloneDX 1.4
cve-lite . --sbom cyclonedx # CycloneDX 1.6
cve-lite . --cdx # the same thing, original flag, still supported
```

Expand Down