From fb009cc8523033c3a8a6d78e20eacd287b7613fa Mon Sep 17 00:00:00 2001 From: AbdaullahAG Date: Sun, 6 Sep 2026 00:06:17 +0300 Subject: [PATCH 1/2] fix(output): bump default CycloneDX output to 1.6 specVersion moves from 1.4 to 1.6. --cdx and --sbom cyclonedx keepworking the same, only the emitted version changes. Current BOMshape already satisfies the 1.6 schema so no structural changeswere needed. Updated help text and added test coverage for the1.6 schema's required fields. Closes #1080 --- src/cli/help.ts | 4 ++-- src/output/cyclonedx.ts | 4 ++-- tests/cyclonedx.test.ts | 45 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/cli/help.ts b/src/cli/help.ts index af12885f..2320b982 100644 --- a/src/cli/help.ts +++ b/src/cli/help.ts @@ -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 Write an SBOM: cyclonedx (1.4) or spdx (2.3), to a timestamped file", + " --sbom 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", @@ -120,4 +120,4 @@ export function printOverridesHelp(): void { " -h, --help Show this help" ]; console.log(lines.join("\n")); -} +} \ No newline at end of file diff --git a/src/output/cyclonedx.ts b/src/output/cyclonedx.ts index 08cc4485..5b92f263 100644 --- a/src/output/cyclonedx.ts +++ b/src/output/cyclonedx.ts @@ -50,7 +50,7 @@ type CycloneDxMetadata = { type CycloneDxBom = { bomFormat: "CycloneDX"; - specVersion: "1.4"; + specVersion: "1.6"; version: number; serialNumber: string; metadata: CycloneDxMetadata; @@ -137,7 +137,7 @@ export function buildCycloneDxBom( return { bomFormat: "CycloneDX", - specVersion: "1.4", + specVersion: "1.6", version: 1, serialNumber: `urn:uuid:${randomUUID()}`, metadata, diff --git a/tests/cyclonedx.test.ts b/tests/cyclonedx.test.ts index afe66a08..3a8f4f91 100644 --- a/tests/cyclonedx.test.ts +++ b/tests/cyclonedx.test.ts @@ -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); @@ -127,3 +127,46 @@ 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 (per the required fields the current + // shape already satisfies: top-level bomFormat/specVersion, component + // type/name, vulnerability.affects[].ref, and rating.method enum). + 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("every component satisfies the 1.6 required component fields (type, name)", () => { + const bom = buildCycloneDxBom(allPackages, findings, null, "1.0.0"); + for (const component of bom.components) { + expect(component.type).toBeTruthy(); + expect(component.name).toBeTruthy(); + } + }); + + it("every vulnerability.affects entry satisfies the 1.6 required affects field (ref)", () => { + const bom = buildCycloneDxBom(allPackages, findings, null, "1.0.0"); + for (const vuln of bom.vulnerabilities) { + expect(vuln.affects.length).toBeGreaterThan(0); + for (const affect of vuln.affects) { + expect(affect.ref).toBeTruthy(); + } + } + }); + + it("every rating.method is one of the 1.6 scoreMethod enum values", () => { + const validMethods = ["CVSSv2", "CVSSv3", "CVSSv31", "CVSSv4", "OWASP", "SSVC", "other"]; + const bom = buildCycloneDxBom(allPackages, findings, null, "1.0.0"); + for (const vuln of bom.vulnerabilities) { + for (const rating of vuln.ratings) { + expect(validMethods).toContain(rating.method); + } + } + }); +}); \ No newline at end of file From a81df12701c6872289b761f614ec18d65a26cb96 Mon Sep 17 00:00:00 2001 From: AbdaullahAG Date: Sun, 6 Sep 2026 21:05:32 +0300 Subject: [PATCH 2/2] fix(output): update remaining 1.4 references and tighten version-pinning tests action.yml, README.md, and the four website/docs pages now say 1.6 instead of 1.4. The three schema-conformance tests now assert specVersion === 1.6 first, so a regression back to 1.4 fails them for the right reason. --- README.md | 5 ++--- action.yml | 4 ++-- src/cli/help.ts | 2 +- tests/cyclonedx.test.ts | 20 +++++++++++++------- website/docs/cli-reference.md | 2 +- website/docs/cyclonedx.md | 2 +- website/docs/github-action.md | 2 +- website/docs/spdx.md | 2 +- 8 files changed, 22 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 63f05b34..e0587a29 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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 @@ -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. \ No newline at end of file diff --git a/action.yml b/action.yml index fb3cdef4..bf65ded2 100644 --- a/action.yml +++ b/action.yml @@ -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: @@ -520,4 +520,4 @@ runs: if [[ "${EXIT_CODE:-0}" -gt 1 ]]; then exit "${EXIT_CODE:-0}" fi - fi + fi \ No newline at end of file diff --git a/src/cli/help.ts b/src/cli/help.ts index 2320b982..dfbeb75b 100644 --- a/src/cli/help.ts +++ b/src/cli/help.ts @@ -120,4 +120,4 @@ export function printOverridesHelp(): void { " -h, --help Show this help" ]; console.log(lines.join("\n")); -} \ No newline at end of file +} diff --git a/tests/cyclonedx.test.ts b/tests/cyclonedx.test.ts index 3a8f4f91..84759fc8 100644 --- a/tests/cyclonedx.test.ts +++ b/tests/cyclonedx.test.ts @@ -130,9 +130,10 @@ describe("buildCycloneDxBom", () => { describe("buildCycloneDxBom - CycloneDX 1.6 schema conformance", () => { // Asserts the required fields from the 1.6 schema directly, without adding - // a schema-validation dependency (per the required fields the current - // shape already satisfies: top-level bomFormat/specVersion, component - // type/name, vulnerability.affects[].ref, and rating.method enum). + // 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")]; @@ -142,16 +143,18 @@ describe("buildCycloneDxBom - CycloneDX 1.6 schema conformance", () => { expect(bom.specVersion).toBe("1.6"); }); - it("every component satisfies the 1.6 required component fields (type, name)", () => { + 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("every vulnerability.affects entry satisfies the 1.6 required affects field (ref)", () => { + 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) { @@ -160,13 +163,16 @@ describe("buildCycloneDxBom - CycloneDX 1.6 schema conformance", () => { } }); - it("every rating.method is one of the 1.6 scoreMethod enum values", () => { + 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); } } }); -}); \ No newline at end of file +}); diff --git a/website/docs/cli-reference.md b/website/docs/cli-reference.md index 28a7d7eb..c95fefcd 100644 --- a/website/docs/cli-reference.md +++ b/website/docs/cli-reference.md @@ -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 ` | 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 ` | 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[=]` | 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`
`cve-lite . --report ./reports` | diff --git a/website/docs/cyclonedx.md b/website/docs/cyclonedx.md index 46144adb..5f63ab63 100644 --- a/website/docs/cyclonedx.md +++ b/website/docs/cyclonedx.md @@ -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 diff --git a/website/docs/github-action.md b/website/docs/github-action.md index 47781847..d0268832 100644 --- a/website/docs/github-action.md +++ b/website/docs/github-action.md @@ -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"` | --- diff --git a/website/docs/spdx.md b/website/docs/spdx.md index 6cbe9172..4d9f1e18 100644 --- a/website/docs/spdx.md +++ b/website/docs/spdx.md @@ -19,7 +19,7 @@ This writes a timestamped file (`cve-lite-scan-.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 ```