@cdxgen/cdxgen 13.0.0 → 13.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -13
- package/bin/audit.js +6 -0
- package/bin/cdxgen.js +140 -8
- package/bin/convert.js +7 -0
- package/bin/evinse.js +1 -1
- package/bin/hbom.js +13 -4
- package/bin/tracebom.js +9 -1
- package/data/component-tags.json +8 -1
- package/data/frameworks-list.json +86 -1
- package/data/remediations.json +1144 -0
- package/data/rules/asar-archives.yaml +1 -1
- package/data/rules/build-fidelity.yaml +782 -0
- package/data/rules/package-integrity.yaml +13 -13
- package/lib/audit/index.js +48 -4
- package/lib/audit/scoring.js +2 -8
- package/lib/cli/bomAssembly.js +83 -15
- package/lib/cli/cliOptions.js +124 -7
- package/lib/cli/index.js +76 -48
- package/lib/cli/jsBom.js +32 -3
- package/lib/cli/jvmBom.js +1494 -1315
- package/lib/cli/managedBom.js +97 -28
- package/lib/cli/nativeBom.js +189 -10
- package/lib/core/buildLedger.js +799 -0
- package/lib/core/deferredExit.js +141 -0
- package/lib/core/env.js +69 -1
- package/lib/core/fs.js +60 -0
- package/lib/core/logger.js +76 -25
- package/lib/core/severity.js +16 -0
- package/lib/core/syncFileWriter.js +106 -0
- package/lib/core/ui.js +46 -2
- package/lib/ecosystems/ecosystems.js +9 -0
- package/lib/ecosystems/gradleutils.js +355 -15
- package/lib/ecosystems/parsers-js.js +26 -0
- package/lib/ecosystems/parsers-jvm.js +9 -0
- package/lib/ecosystems/parsers-misc.js +16 -2
- package/lib/ecosystems/parsers-python.js +171 -35
- package/lib/ecosystems/parsers-rust.js +12 -2
- package/lib/ecosystems/pypiClassifiers.js +326 -0
- package/lib/ecosystems/pythonutils.js +49 -1
- package/lib/ecosystems/rubyutils.js +13 -0
- package/lib/ecosystems/utils.js +9 -1
- package/lib/evinser/evinser.js +30 -12
- package/lib/helpers/remote/dependency-track.js +81 -14
- package/lib/inventory/auditCategories.js +9 -0
- package/lib/inventory/depsUtils.js +72 -0
- package/lib/inventory/dosai.js +431 -22
- package/lib/inventory/envcontext.js +211 -19
- package/lib/inventory/fetchBatch.js +57 -0
- package/lib/inventory/jvmToolEnv.js +593 -0
- package/lib/inventory/osinfo.js +123 -16
- package/lib/inventory/table.js +9 -5
- package/lib/inventory/toolRequirements.js +903 -0
- package/lib/managers/binary.js +216 -40
- package/lib/managers/docker.js +26 -5
- package/lib/server/server.js +1 -1
- package/lib/stages/postgen/annotationBuilder.js +97 -0
- package/lib/stages/postgen/auditBom.js +76 -79
- package/lib/stages/postgen/introspection/annotate.js +320 -0
- package/lib/stages/postgen/introspection/commandFacts.js +293 -0
- package/lib/stages/postgen/introspection/emit.js +192 -0
- package/lib/stages/postgen/introspection/formulationEvidence.js +427 -0
- package/lib/stages/postgen/introspection/markers.js +227 -0
- package/lib/stages/postgen/introspection/reflect.js +1214 -0
- package/lib/stages/postgen/introspection/report.js +1208 -0
- package/lib/stages/postgen/introspection/score.js +1067 -0
- package/lib/stages/postgen/introspection/shapeCommand.js +304 -0
- package/lib/stages/postgen/parentEdge.js +156 -0
- package/lib/stages/postgen/postgen.js +115 -2
- package/lib/stages/postgen/ruleEngine.js +17 -0
- package/lib/stages/pregen/envAudit.js +42 -2
- package/lib/stages/pregen/pregen.js +1171 -6
- package/lib/validator/bomValidator.js +11 -2
- package/package.json +14 -14
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/audit/scoring.d.ts +2 -8
- package/types/lib/audit/scoring.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +14 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +2 -1
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +8 -0
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/buildLedger.d.ts +272 -0
- package/types/lib/core/buildLedger.d.ts.map +1 -0
- package/types/lib/core/deferredExit.d.ts +84 -0
- package/types/lib/core/deferredExit.d.ts.map +1 -0
- package/types/lib/core/env.d.ts +22 -1
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +21 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/logger.d.ts +14 -1
- package/types/lib/core/logger.d.ts.map +1 -1
- package/types/lib/core/severity.d.ts +11 -0
- package/types/lib/core/severity.d.ts.map +1 -0
- package/types/lib/core/syncFileWriter.d.ts +33 -0
- package/types/lib/core/syncFileWriter.d.ts.map +1 -0
- package/types/lib/core/ui.d.ts +1 -1
- package/types/lib/core/ui.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +33 -0
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pypiClassifiers.d.ts +80 -0
- package/types/lib/ecosystems/pypiClassifiers.d.ts.map +1 -0
- package/types/lib/ecosystems/pythonutils.d.ts +20 -0
- package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/utils.d.ts +4 -4
- package/types/lib/ecosystems/utils.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +5 -1
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/helpers/remote/dependency-track.d.ts +45 -4
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -1
- package/types/lib/inventory/auditCategories.d.ts +8 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -1
- package/types/lib/inventory/depsUtils.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +20 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/fetchBatch.d.ts +9 -0
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +189 -0
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -0
- package/types/lib/inventory/osinfo.d.ts +83 -2
- package/types/lib/inventory/osinfo.d.ts.map +1 -1
- package/types/lib/inventory/table.d.ts +4 -1
- package/types/lib/inventory/table.d.ts.map +1 -1
- package/types/lib/inventory/toolRequirements.d.ts +216 -0
- package/types/lib/inventory/toolRequirements.d.ts.map +1 -0
- package/types/lib/managers/binary.d.ts +71 -0
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotationBuilder.d.ts +53 -0
- package/types/lib/stages/postgen/annotationBuilder.d.ts.map +1 -0
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/introspection/annotate.d.ts +81 -0
- package/types/lib/stages/postgen/introspection/annotate.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/commandFacts.d.ts +32 -0
- package/types/lib/stages/postgen/introspection/commandFacts.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/emit.d.ts +71 -0
- package/types/lib/stages/postgen/introspection/emit.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/formulationEvidence.d.ts +154 -0
- package/types/lib/stages/postgen/introspection/formulationEvidence.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/markers.d.ts +57 -0
- package/types/lib/stages/postgen/introspection/markers.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/reflect.d.ts +77 -0
- package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/report.d.ts +85 -0
- package/types/lib/stages/postgen/introspection/report.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/score.d.ts +149 -0
- package/types/lib/stages/postgen/introspection/score.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/shapeCommand.d.ts +79 -0
- package/types/lib/stages/postgen/introspection/shapeCommand.d.ts.map +1 -0
- package/types/lib/stages/postgen/parentEdge.d.ts +35 -0
- package/types/lib/stages/postgen/parentEdge.d.ts.map +1 -0
- package/types/lib/stages/postgen/postgen.d.ts +2 -2
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +131 -0
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -32,15 +32,16 @@ Supported output document formats:
|
|
|
32
32
|
|
|
33
33
|
## Choose your path
|
|
34
34
|
|
|
35
|
-
| Persona | What cdxgen helps you do | First command | Read next
|
|
36
|
-
| --------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
37
|
-
| **Developers** | Generate a CycloneDX BOM from a local repo, git URL, purl, or container image | `cdxgen -o bom.json .` | [CLI Usage][docs-cli], [Supported Project Types][docs-project-types]
|
|
38
|
-
| **AI platform teams** | Generate AI/ML BOMs, catalog prompt/model/MCP surfaces, and run AI-BOM governance | `aibom .` | [AI-BOM Guide](docs/AI_BOM.md), [AI-BOM lesson](docs/LESSON15.md)
|
|
39
|
-
| **Hardware teams** | Generate an HBOM or merged HBOM+OBOM host view for the current host | `hbom -o hbom.json` | [HBOM guide](docs/HBOM.md), [HBOM lesson](docs/LESSON13.md)
|
|
40
|
-
| **AppSec** | Enrich BOMs with evidence, run BOM audit rules, and feed downstream security workflows | `cdxgen -o bom.json --profile appsec --evidence --bom-audit .` | [BOM Audit](docs/BOM_AUDIT.md), [Threat Model](docs/THREAT_MODEL.md)
|
|
41
|
-
| **
|
|
42
|
-
| **
|
|
43
|
-
| **
|
|
35
|
+
| Persona | What cdxgen helps you do | First command | Read next |
|
|
36
|
+
| --------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| **Developers** | Generate a CycloneDX BOM from a local repo, git URL, purl, or container image | `cdxgen -o bom.json .` | [CLI Usage][docs-cli], [Supported Project Types][docs-project-types] |
|
|
38
|
+
| **AI platform teams** | Generate AI/ML BOMs, catalog prompt/model/MCP surfaces, and run AI-BOM governance | `aibom .` | [AI-BOM Guide](docs/AI_BOM.md), [AI-BOM lesson](docs/LESSON15.md) |
|
|
39
|
+
| **Hardware teams** | Generate an HBOM or merged HBOM+OBOM host view for the current host | `hbom -o hbom.json` | [HBOM guide](docs/HBOM.md), [HBOM lesson](docs/LESSON13.md) |
|
|
40
|
+
| **AppSec** | Enrich BOMs with evidence, run BOM audit rules, and feed downstream security workflows | `cdxgen -o bom.json --profile appsec --evidence --bom-audit .` | [BOM Audit](docs/BOM_AUDIT.md), [Threat Model](docs/THREAT_MODEL.md) |
|
|
41
|
+
| **Build engineers** | Grade how completely the SBOM captured the project, and get ranked fixes when the build environment degraded it | `cdxgen --profile introspect --introspect-fail-below 70 -o bom.json .` | [Build Introspection](docs/INTROSPECTION.md), [Fidelity loop skill](.agents/skills/sbom-fidelity-loop/SKILL.md) |
|
|
42
|
+
| **SOC analysts** | Build OBOM inventories for live hosts and triage runtime posture issues | `obom -o obom.json --deep --bom-audit --bom-audit-categories obom-runtime` | [OBOM lessons](docs/OBOM_LESSONS.md), [Server Usage][docs-server] |
|
|
43
|
+
| **Compliance teams** | Validate BOM quality, check SCVS/CRA posture, and export SPDX deliverables | `cdx-validate -i bom.json --benchmark scvs-l2,cra` | [cdx-validate](docs/CDX_VALIDATE.md), [cdx-convert](docs/CDX_CONVERT.md), [Permissions][docs-permissions] |
|
|
44
|
+
| **Security Teams** | Dynamically trace executions to capture cryptographic activities, CBOM properties, software components, and services | `tracebom --cbom-output cbom.json -- npm test` | [Threat Model](docs/THREAT_MODEL.md) |
|
|
44
45
|
|
|
45
46
|
### Role-based quick starts
|
|
46
47
|
|
|
@@ -120,6 +121,7 @@ Sections include:
|
|
|
120
121
|
- [MCP Inventory](docs/MCP.md)
|
|
121
122
|
- [REPL Guide](docs/REPL.md)
|
|
122
123
|
- [Custom Properties](docs/CUSTOM_PROPERTIES.md)
|
|
124
|
+
- [Claude Code Plugin](claude-plugin/README.md)
|
|
123
125
|
- [Deprecations](docs/DEPRECATIONS.md)
|
|
124
126
|
- [Security Policy](SECURITY.md)
|
|
125
127
|
- [Threat Model](docs/THREAT_MODEL.md)
|
|
@@ -214,7 +216,7 @@ Common asset names:
|
|
|
214
216
|
#### Linux
|
|
215
217
|
|
|
216
218
|
```bash
|
|
217
|
-
VERSION="v13.
|
|
219
|
+
VERSION="v13.1.0"
|
|
218
220
|
ASSET="cdx-audit-linux-amd64"
|
|
219
221
|
BASE_URL="https://github.com/cdxgen/cdxgen/releases/download/${VERSION}"
|
|
220
222
|
|
|
@@ -228,7 +230,7 @@ chmod +x "${ASSET}"
|
|
|
228
230
|
#### macOS
|
|
229
231
|
|
|
230
232
|
```bash
|
|
231
|
-
VERSION="v13.
|
|
233
|
+
VERSION="v13.1.0"
|
|
232
234
|
ASSET="cdx-audit-darwin-arm64"
|
|
233
235
|
BASE_URL="https://github.com/cdxgen/cdxgen/releases/download/${VERSION}"
|
|
234
236
|
|
|
@@ -242,7 +244,7 @@ chmod +x "${ASSET}"
|
|
|
242
244
|
#### Windows (PowerShell)
|
|
243
245
|
|
|
244
246
|
```powershell
|
|
245
|
-
$Version = "v13.
|
|
247
|
+
$Version = "v13.1.0"
|
|
246
248
|
$Asset = "cdx-audit-windows-amd64.exe"
|
|
247
249
|
$BaseUrl = "https://github.com/cdxgen/cdxgen/releases/download/$Version"
|
|
248
250
|
|
|
@@ -267,7 +269,7 @@ steps:
|
|
|
267
269
|
env:
|
|
268
270
|
GH_TOKEN: ${{ github.token }}
|
|
269
271
|
run: |
|
|
270
|
-
gh release download v13.
|
|
272
|
+
gh release download v13.1.0 \
|
|
271
273
|
--repo cdxgen/cdxgen \
|
|
272
274
|
--pattern 'cdx-audit-linux-amd64' \
|
|
273
275
|
--pattern 'cdx-audit-linux-amd64.sha256'
|
|
@@ -620,6 +622,17 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
|
|
|
620
622
|
pnpm dlx @cdxgen/cdxgen-plugins-bin
|
|
621
623
|
```
|
|
622
624
|
|
|
625
|
+
## Claude Code plugin
|
|
626
|
+
|
|
627
|
+
The cdxgen toolkit is also packaged as a [Claude Code](https://claude.com/claude-code) plugin, so agents drive the correct command and flags — including the dry-run-first and no-auto-install safety constraints — instead of guessing.
|
|
628
|
+
|
|
629
|
+
```shell
|
|
630
|
+
claude plugin marketplace add cdxgen/cdxgen
|
|
631
|
+
claude plugin install cdxgen@cdxgen-plugins
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
It ships skills covering SBOM generation, container and rootfs scans, OBOM/HBOM, CBOM, AI-BOM and MCP inventory, BOM auditing, signing, validation, conversion, evidence enrichment, runtime tracing, and Dependency-Track publishing. See [claude-plugin/README.md](claude-plugin/README.md).
|
|
635
|
+
|
|
623
636
|
## Rust accelerator (cdxrs)
|
|
624
637
|
|
|
625
638
|
cdxgen ships with an optional Rust accelerator binary, `cdxrs`, which speeds up hot paths such as registry metadata lookups where available. Use the `--rust` and `--no-rust` arguments to toggle it, or set the environment variable `CDXGEN_RS_DISABLE=all` to force the JavaScript path. See the [cdxrs protocol](./docs/CDXRS_PROTOCOL.md) document for implementation details.
|
package/bin/audit.js
CHANGED
|
@@ -132,6 +132,11 @@ const args = yargs(hideBin(process.argv))
|
|
|
132
132
|
"Path to a license compliance policy YAML file. Evaluates every component license in the BOM(s) and reports prohibited and warning-level violations as a separate table. Error-level (prohibited) violations cause a non-zero exit.",
|
|
133
133
|
type: "string",
|
|
134
134
|
})
|
|
135
|
+
.option("introspect", {
|
|
136
|
+
description:
|
|
137
|
+
"Include a build-fidelity introspection verdict for each audited BOM. The BOM was not generated by this run, so the verdict rests on BOM structure alone.",
|
|
138
|
+
type: "boolean",
|
|
139
|
+
})
|
|
135
140
|
.check((argv) => {
|
|
136
141
|
if (!argv.bom && !argv.bomDir) {
|
|
137
142
|
throw new Error("Specify --bom or --bom-dir.");
|
|
@@ -204,6 +209,7 @@ function writeOrPrint(output, outputPath) {
|
|
|
204
209
|
categories: splitCsv(args.categories),
|
|
205
210
|
directBomAudit: args.directBomAudit,
|
|
206
211
|
failSeverity: args.failSeverity,
|
|
212
|
+
introspect: args.introspect === true,
|
|
207
213
|
licensePolicy: args.licensePolicy,
|
|
208
214
|
maxTargets: args.maxTargets,
|
|
209
215
|
minSeverity: args.minSeverity,
|
package/bin/cdxgen.js
CHANGED
|
@@ -4,6 +4,7 @@ import crypto from "node:crypto";
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import http from "node:http";
|
|
6
6
|
import https from "node:https";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
7
8
|
import {
|
|
8
9
|
basename,
|
|
9
10
|
dirname,
|
|
@@ -25,6 +26,12 @@ import {
|
|
|
25
26
|
validateSpecVersion,
|
|
26
27
|
} from "../lib/cli/cliOptions.js";
|
|
27
28
|
import { createBom, submitBom } from "../lib/cli/index.js";
|
|
29
|
+
import { closeLedger } from "../lib/core/buildLedger.js";
|
|
30
|
+
import {
|
|
31
|
+
getDeferredFailures,
|
|
32
|
+
INTROSPECTION_FAILURE_EXIT_CODE,
|
|
33
|
+
isDeferredFailOnError,
|
|
34
|
+
} from "../lib/core/deferredExit.js";
|
|
28
35
|
import { TRACE_MODE, thoughtEnd, thoughtLog } from "../lib/core/logger.js";
|
|
29
36
|
import {
|
|
30
37
|
PROJECT_CONFIG_FILENAMES,
|
|
@@ -57,6 +64,7 @@ import {
|
|
|
57
64
|
retrieveCdxgenVersion,
|
|
58
65
|
safeExistsSync,
|
|
59
66
|
safeMkdirSync,
|
|
67
|
+
safeRmSync,
|
|
60
68
|
safeSpawnSync,
|
|
61
69
|
safeWriteSync,
|
|
62
70
|
setActivityContext,
|
|
@@ -486,8 +494,33 @@ const args = _yargs
|
|
|
486
494
|
"deep-learning",
|
|
487
495
|
"ml-deep",
|
|
488
496
|
"ml-tiny",
|
|
497
|
+
"introspect",
|
|
489
498
|
],
|
|
490
499
|
})
|
|
500
|
+
.option("introspect", {
|
|
501
|
+
type: "boolean",
|
|
502
|
+
description:
|
|
503
|
+
"Reflect on how the build environment limited BOM completeness and write an introspection report. Enabled by --profile introspect or CDXGEN_INTROSPECT=true. Pass --no-introspect to keep it off.",
|
|
504
|
+
})
|
|
505
|
+
.option("introspect-report", {
|
|
506
|
+
description:
|
|
507
|
+
"Path for the markdown introspection report. Defaults to <output>.introspection.md; '-' writes the report to stderr.",
|
|
508
|
+
})
|
|
509
|
+
.option("introspect-json", {
|
|
510
|
+
description:
|
|
511
|
+
"Path for the JSON introspection report consumed by remediation loops. Defaults to <output>.introspection.json.",
|
|
512
|
+
})
|
|
513
|
+
.option("introspect-fail-below", {
|
|
514
|
+
type: "number",
|
|
515
|
+
description:
|
|
516
|
+
"CI gate: exit with status 4 after the BOM is written when the overall introspection score is below this 0-100 threshold. Absent means the gate never fails.",
|
|
517
|
+
})
|
|
518
|
+
.option("introspect-annotate", {
|
|
519
|
+
type: "boolean",
|
|
520
|
+
default: true,
|
|
521
|
+
description:
|
|
522
|
+
"Carry the introspection verdict inside the BOM as metadata properties and annotations. Enabled with --introspect; pass --no-introspect-annotate to keep the BOM untouched.",
|
|
523
|
+
})
|
|
491
524
|
.option("lifecycle", {
|
|
492
525
|
description: "Product lifecycle for the generated BOM.",
|
|
493
526
|
hidden: true,
|
|
@@ -602,6 +635,7 @@ const args = _yargs
|
|
|
602
635
|
"suggest-build-tools",
|
|
603
636
|
"ruby-docker-install",
|
|
604
637
|
"resolve-gradle-distribution",
|
|
638
|
+
"jvm-tool-setup",
|
|
605
639
|
],
|
|
606
640
|
})
|
|
607
641
|
.option("min-confidence", {
|
|
@@ -887,15 +921,26 @@ if (args.bomAuditIncludeTrusted && args.bomAuditOnlyTrusted) {
|
|
|
887
921
|
|
|
888
922
|
if (args.tui && !readEnvironmentVariable("CI")) {
|
|
889
923
|
const cdxuiPath = resolvePluginBinary("cdxui");
|
|
890
|
-
if (cdxuiPath) {
|
|
891
|
-
|
|
924
|
+
if (!cdxuiPath) {
|
|
925
|
+
console.error(
|
|
926
|
+
"The terminal user interface requires the cdxui plugin binary, which is not installed for this platform.\nInstall @cdxgen/cdxgen-plugins-bin, or set CDXUI_CMD to a cdxui binary, then retry. Continuing without the interface.",
|
|
927
|
+
);
|
|
928
|
+
} else {
|
|
929
|
+
const cdxgenArgs = process.argv
|
|
930
|
+
.slice(2)
|
|
931
|
+
.filter((a) => a !== "--tui" && !a.startsWith("--tui="));
|
|
932
|
+
// Arguments cross the process boundary separated by the unit separator
|
|
933
|
+
// rather than by spaces: a scan path may legitimately contain a space, and
|
|
934
|
+
// re-splitting on whitespace would silently turn it into two paths.
|
|
892
935
|
const cdxuiResult = safeSpawnSync(cdxuiPath, ["--generate"], {
|
|
893
936
|
stdio: "inherit",
|
|
894
937
|
env: {
|
|
895
938
|
...process.env,
|
|
896
939
|
CDXGEN_CMD:
|
|
897
|
-
readEnvironmentVariable("CDXGEN_CMD") ||
|
|
898
|
-
|
|
940
|
+
readEnvironmentVariable("CDXGEN_CMD") ||
|
|
941
|
+
[process.argv[0], process.argv[1]].filter(Boolean).join("\x1f") ||
|
|
942
|
+
"cdxgen",
|
|
943
|
+
CDXGEN_ARGS: cdxgenArgs.join("\x1f"),
|
|
899
944
|
},
|
|
900
945
|
});
|
|
901
946
|
process.exit(cdxuiResult.status || 0);
|
|
@@ -999,6 +1044,29 @@ const { options, warnings: phase3Warnings } = buildOptionsFromArgs(args, {
|
|
|
999
1044
|
isDryRun,
|
|
1000
1045
|
isSecureMode,
|
|
1001
1046
|
});
|
|
1047
|
+
// Exit status reserved for the introspection CI gate: the BOM was generated
|
|
1048
|
+
// and written, but its introspection score missed the configured threshold.
|
|
1049
|
+
// Distinct from 1 so CI can tell a generation failure from a not-good-enough
|
|
1050
|
+
// SBOM.
|
|
1051
|
+
const INTROSPECTION_GATE_EXIT_CODE = 4;
|
|
1052
|
+
// The ledger recorder resolves its environment lazily, so the parsed flag is
|
|
1053
|
+
// bridged into the environment it reads: a run started with --introspect
|
|
1054
|
+
// records the same events as one started with CDXGEN_INTROSPECT=true. Without
|
|
1055
|
+
// an explicitly configured sidecar, an automatic temp sidecar captures
|
|
1056
|
+
// worker-thread events the main thread never sees; it is removed once the
|
|
1057
|
+
// reports are written. Dry-run creates no files, so it keeps an in-memory
|
|
1058
|
+
// ledger only.
|
|
1059
|
+
let autoLedgerSidecar;
|
|
1060
|
+
if (options.introspect) {
|
|
1061
|
+
process.env.CDXGEN_INTROSPECT = "true";
|
|
1062
|
+
if (!isDryRun && !readEnvironmentVariable("CDXGEN_INTROSPECT_LEDGER")) {
|
|
1063
|
+
autoLedgerSidecar = join(
|
|
1064
|
+
tmpdir(),
|
|
1065
|
+
`cdxgen-introspect-ledger-${process.pid}.jsonl`,
|
|
1066
|
+
);
|
|
1067
|
+
process.env.CDXGEN_INTROSPECT_LEDGER = autoLedgerSidecar;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1002
1070
|
const cliActivityProjectType = Array.isArray(options.projectType)
|
|
1003
1071
|
? options.projectType.join(",")
|
|
1004
1072
|
: options.projectType;
|
|
@@ -1672,8 +1740,14 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1672
1740
|
prepareEnv(srcDir, options);
|
|
1673
1741
|
prepPhase.succeed("");
|
|
1674
1742
|
} catch (err) {
|
|
1675
|
-
|
|
1676
|
-
|
|
1743
|
+
if (isDeferredFailOnError(err)) {
|
|
1744
|
+
// A deep-mode provisioning failure under --fail-on-error: the scan
|
|
1745
|
+
// continues so the run still produces the verdict that explains it.
|
|
1746
|
+
prepPhase.fail("environment preparation failed");
|
|
1747
|
+
} else {
|
|
1748
|
+
prepPhase.fail(err);
|
|
1749
|
+
throw err;
|
|
1750
|
+
}
|
|
1677
1751
|
}
|
|
1678
1752
|
}
|
|
1679
1753
|
thoughtLog("Getting ready to generate the BOM ⚡️.");
|
|
@@ -1745,7 +1819,7 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1745
1819
|
{
|
|
1746
1820
|
const postPhase = defaultUi.phase("Post-processing BOM");
|
|
1747
1821
|
try {
|
|
1748
|
-
bomNSData = postProcess(
|
|
1822
|
+
bomNSData = await postProcess(
|
|
1749
1823
|
bomNSData,
|
|
1750
1824
|
{ ...options, executeOsQuery },
|
|
1751
1825
|
srcDir,
|
|
@@ -1997,7 +2071,7 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1997
2071
|
dbObjMap,
|
|
1998
2072
|
evinseOptions,
|
|
1999
2073
|
);
|
|
2000
|
-
const evinseJson = evinserModule.createEvinseFile(
|
|
2074
|
+
const evinseJson = await evinserModule.createEvinseFile(
|
|
2001
2075
|
sliceArtefacts,
|
|
2002
2076
|
evinseOptions,
|
|
2003
2077
|
);
|
|
@@ -2136,6 +2210,64 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2136
2210
|
console.log("Try running the command with -t <type> or -r argument");
|
|
2137
2211
|
}
|
|
2138
2212
|
}
|
|
2213
|
+
// The reflection consumed the ledger while producing its reports, so an
|
|
2214
|
+
// automatic sidecar can be released and removed. An explicitly configured
|
|
2215
|
+
// sidecar belongs to the user and is left alone.
|
|
2216
|
+
if (autoLedgerSidecar) {
|
|
2217
|
+
closeLedger();
|
|
2218
|
+
try {
|
|
2219
|
+
safeRmSync(autoLedgerSidecar, { force: true });
|
|
2220
|
+
} catch {
|
|
2221
|
+
// Best-effort cleanup of our own temp file: a runtime whose permission
|
|
2222
|
+
// model denies the removal must not fail a run whose BOM and reports
|
|
2223
|
+
// are already written.
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
// A --fail-on-error extractor failure on an introspected run was deferred
|
|
2227
|
+
// until the BOM and both reports existed; here it finally claims its
|
|
2228
|
+
// non-zero exit. It outranks the fidelity gate because a failed toolchain is
|
|
2229
|
+
// the more fundamental claim, and the report still carries the gate
|
|
2230
|
+
// decision.
|
|
2231
|
+
const deferredFailures = getDeferredFailures();
|
|
2232
|
+
if (deferredFailures.length) {
|
|
2233
|
+
const reported = new Set();
|
|
2234
|
+
for (const failure of deferredFailures) {
|
|
2235
|
+
const message = `fail-on-error: ${failure.detail} (tool: ${failure.tool}${failure.exitCode !== undefined ? `, exit ${failure.exitCode}` : ""}).`;
|
|
2236
|
+
if (!reported.has(message)) {
|
|
2237
|
+
reported.add(message);
|
|
2238
|
+
console.error(message);
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
// Exit 5 is the promise that the outputs exist. A run that failed before
|
|
2242
|
+
// producing any BOM never made that promise and keeps the historical
|
|
2243
|
+
// exit 1, which is what "cdxgen failed to generate a BOM" has always
|
|
2244
|
+
// meant.
|
|
2245
|
+
const wroteBom = Boolean(bomNSData?.bomJson);
|
|
2246
|
+
console.error(
|
|
2247
|
+
wroteBom
|
|
2248
|
+
? `fail-on-error: ${reported.size} extractor failure(s) were deferred so the BOM and the introspection report could be written; exiting ${INTROSPECTION_FAILURE_EXIT_CODE}.`
|
|
2249
|
+
: "fail-on-error: no BOM was produced, so there is no verdict to report; exiting 1.",
|
|
2250
|
+
);
|
|
2251
|
+
if (cleanup) {
|
|
2252
|
+
cleanupSourceDir(srcDir);
|
|
2253
|
+
}
|
|
2254
|
+
process.exit(wroteBom ? INTROSPECTION_FAILURE_EXIT_CODE : 1);
|
|
2255
|
+
}
|
|
2256
|
+
// The introspection CI gate fires only after the BOM and the reports are
|
|
2257
|
+
// written: a below-threshold score reports a not-good-enough SBOM, never a
|
|
2258
|
+
// lost one.
|
|
2259
|
+
if (
|
|
2260
|
+
bomNSData?.introspectionGate &&
|
|
2261
|
+
bomNSData.introspectionGate.passed === false
|
|
2262
|
+
) {
|
|
2263
|
+
console.error(
|
|
2264
|
+
`Build introspection: score ${bomNSData.introspectionGate.score} is below the --introspect-fail-below threshold ${bomNSData.introspectionGate.threshold}.`,
|
|
2265
|
+
);
|
|
2266
|
+
if (cleanup) {
|
|
2267
|
+
cleanupSourceDir(srcDir);
|
|
2268
|
+
}
|
|
2269
|
+
process.exit(INTROSPECTION_GATE_EXIT_CODE);
|
|
2270
|
+
}
|
|
2139
2271
|
thoughtEnd();
|
|
2140
2272
|
// Automatically submit the bom data
|
|
2141
2273
|
// biome-ignore lint/suspicious/noDoubleEquals: yargs passes true for empty values
|
package/bin/convert.js
CHANGED
|
@@ -7,6 +7,7 @@ import process from "node:process";
|
|
|
7
7
|
import yargs from "yargs";
|
|
8
8
|
import { hideBin } from "yargs/helpers";
|
|
9
9
|
|
|
10
|
+
import { installConsoleShim, restoreConsole } from "../lib/core/ui.js";
|
|
10
11
|
import {
|
|
11
12
|
retrieveCdxgenVersion,
|
|
12
13
|
safeExistsSync,
|
|
@@ -74,6 +75,12 @@ const args = _yargs
|
|
|
74
75
|
.help()
|
|
75
76
|
.wrap(Math.min(120, yargs().terminalWidth())).argv;
|
|
76
77
|
|
|
78
|
+
// stdout carries the payload and nothing else; every diagnostic goes to the
|
|
79
|
+
// live region's stream. Without the shim a `--print`/`--json` document shares
|
|
80
|
+
// stdout with progress messages and cannot be piped into a parser.
|
|
81
|
+
installConsoleShim();
|
|
82
|
+
process.once("exit", restoreConsole);
|
|
83
|
+
|
|
77
84
|
const loadCycloneDxBom = async (inputPath) => {
|
|
78
85
|
if (!safeExistsSync(inputPath)) {
|
|
79
86
|
console.error(`Input file '${inputPath}' not found.`);
|
package/bin/evinse.js
CHANGED
|
@@ -338,7 +338,7 @@ ensureCycloneDxInput(args.input);
|
|
|
338
338
|
// Analyze the project using atom. Convert package namespaces to purl using the db
|
|
339
339
|
const sliceArtefacts = await analyzeProject(dbObjMap, args);
|
|
340
340
|
// Create the SBOM with Evidence
|
|
341
|
-
const bomJson = createEvinseFile(sliceArtefacts, args);
|
|
341
|
+
const bomJson = await createEvinseFile(sliceArtefacts, args);
|
|
342
342
|
// Validate our final SBOM
|
|
343
343
|
if (!(await validateBom(bomJson))) {
|
|
344
344
|
process.exit(1);
|
package/bin/hbom.js
CHANGED
|
@@ -8,6 +8,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
8
8
|
|
|
9
9
|
import { createHBom } from "../lib/cli/index.js";
|
|
10
10
|
import { thoughtLog } from "../lib/core/logger.js";
|
|
11
|
+
import { installConsoleShim, restoreConsole } from "../lib/core/ui.js";
|
|
11
12
|
import {
|
|
12
13
|
DEBUG_MODE,
|
|
13
14
|
isDryRun,
|
|
@@ -192,6 +193,12 @@ const args = _yargs
|
|
|
192
193
|
})
|
|
193
194
|
.wrap(Math.min(120, yargs().terminalWidth())).argv;
|
|
194
195
|
|
|
196
|
+
// stdout carries the payload and nothing else; every diagnostic goes to the
|
|
197
|
+
// live region's stream. Without the shim a `--print`/`--json` document shares
|
|
198
|
+
// stdout with progress messages and cannot be piped into a parser.
|
|
199
|
+
installConsoleShim();
|
|
200
|
+
process.once("exit", restoreConsole);
|
|
201
|
+
|
|
195
202
|
if (args.help) {
|
|
196
203
|
console.log(`${retrieveCdxgenVersion()}\n`);
|
|
197
204
|
_yargs.showHelp();
|
|
@@ -334,8 +341,9 @@ async function loadBomFromInputFile(inputFile) {
|
|
|
334
341
|
function printHbomDiagnosticsReport(bomJson) {
|
|
335
342
|
const hbomSummary = getHbomSummary(bomJson);
|
|
336
343
|
if (options.json) {
|
|
337
|
-
|
|
338
|
-
|
|
344
|
+
// A machine-readable report is a payload too, not a diagnostic.
|
|
345
|
+
process.stdout.write(
|
|
346
|
+
`${JSON.stringify(
|
|
339
347
|
{
|
|
340
348
|
actionableDiagnosticCount: hbomSummary.actionableDiagnosticCount,
|
|
341
349
|
architecture: hbomSummary.architecture,
|
|
@@ -359,7 +367,7 @@ function printHbomDiagnosticsReport(bomJson) {
|
|
|
359
367
|
},
|
|
360
368
|
null,
|
|
361
369
|
2,
|
|
362
|
-
)
|
|
370
|
+
)}\n`,
|
|
363
371
|
);
|
|
364
372
|
return;
|
|
365
373
|
}
|
|
@@ -459,7 +467,8 @@ async function runDiagnosticsCommand() {
|
|
|
459
467
|
}
|
|
460
468
|
const output = JSON.stringify(bomJson, null, options.pretty ? 2 : null);
|
|
461
469
|
if (options.print) {
|
|
462
|
-
console.
|
|
470
|
+
// The document is the payload, so it bypasses the console shim.
|
|
471
|
+
process.stdout.write(`${output}\n`);
|
|
463
472
|
} else {
|
|
464
473
|
const outputDirectory = getOutputDirectory(options.output);
|
|
465
474
|
if (outputDirectory && !safeExistsSync(outputDirectory)) {
|
package/bin/tracebom.js
CHANGED
|
@@ -7,6 +7,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
7
7
|
|
|
8
8
|
import { validateSpecVersion } from "../lib/cli/cliOptions.js";
|
|
9
9
|
import { createDynamicBom } from "../lib/cli/index.js";
|
|
10
|
+
import { installConsoleShim, restoreConsole } from "../lib/core/ui.js";
|
|
10
11
|
import {
|
|
11
12
|
DEBUG_MODE,
|
|
12
13
|
retrieveCdxgenVersion,
|
|
@@ -200,6 +201,12 @@ const args = _yargs
|
|
|
200
201
|
})
|
|
201
202
|
.wrap(Math.min(120, yargs().terminalWidth())).argv;
|
|
202
203
|
|
|
204
|
+
// stdout carries the payload and nothing else; every diagnostic goes to the
|
|
205
|
+
// live region's stream. Without the shim a `--print`/`--json` document shares
|
|
206
|
+
// stdout with progress messages and cannot be piped into a parser.
|
|
207
|
+
installConsoleShim();
|
|
208
|
+
process.once("exit", restoreConsole);
|
|
209
|
+
|
|
203
210
|
if (args.help) {
|
|
204
211
|
console.log(`${retrieveCdxgenVersion()}\n`);
|
|
205
212
|
_yargs.showHelp();
|
|
@@ -274,7 +281,8 @@ const options = {
|
|
|
274
281
|
const jsonPayload = JSON.stringify(bomJson, null, DEBUG_MODE ? 2 : null);
|
|
275
282
|
|
|
276
283
|
if (args.print) {
|
|
277
|
-
console.
|
|
284
|
+
// The document is the payload, so it bypasses the console shim.
|
|
285
|
+
process.stdout.write(`${jsonPayload}\n`);
|
|
278
286
|
}
|
|
279
287
|
|
|
280
288
|
safeWriteSync(options.output, jsonPayload);
|
package/data/component-tags.json
CHANGED
|
@@ -76,6 +76,56 @@
|
|
|
76
76
|
"pkg:pypi/langchain",
|
|
77
77
|
"pkg:pypi/llama",
|
|
78
78
|
"pkg:pypi/sqlalchemy",
|
|
79
|
+
"pkg:pypi/starlette",
|
|
80
|
+
"pkg:pypi/quart",
|
|
81
|
+
"pkg:pypi/litestar",
|
|
82
|
+
"pkg:pypi/blacksheep",
|
|
83
|
+
"pkg:pypi/robyn",
|
|
84
|
+
"pkg:pypi/connexion",
|
|
85
|
+
"pkg:pypi/werkzeug",
|
|
86
|
+
"pkg:pypi/asgiref",
|
|
87
|
+
"pkg:pypi/djangorestframework",
|
|
88
|
+
"pkg:pypi/scrapy",
|
|
89
|
+
"pkg:pypi/streamlit",
|
|
90
|
+
"pkg:pypi/gradio",
|
|
91
|
+
"pkg:pypi/dash",
|
|
92
|
+
"pkg:pypi/nicegui",
|
|
93
|
+
"pkg:pypi/reflex",
|
|
94
|
+
"pkg:pypi/pydantic",
|
|
95
|
+
"pkg:pypi/sqlmodel",
|
|
96
|
+
"pkg:pypi/tortoise-orm",
|
|
97
|
+
"pkg:pypi/peewee",
|
|
98
|
+
"pkg:pypi/mongoengine",
|
|
99
|
+
"pkg:pypi/beanie",
|
|
100
|
+
"pkg:pypi/marshmallow",
|
|
101
|
+
"pkg:pypi/strawberry-graphql",
|
|
102
|
+
"pkg:pypi/graphene",
|
|
103
|
+
"pkg:pypi/ariadne",
|
|
104
|
+
"pkg:pypi/grpcio",
|
|
105
|
+
"pkg:pypi/thrift",
|
|
106
|
+
"pkg:pypi/mcp",
|
|
107
|
+
"pkg:pypi/fastmcp",
|
|
108
|
+
"pkg:pypi/openai",
|
|
109
|
+
"pkg:pypi/anthropic",
|
|
110
|
+
"pkg:pypi/litellm",
|
|
111
|
+
"pkg:pypi/langgraph",
|
|
112
|
+
"pkg:pypi/haystack-ai",
|
|
113
|
+
"pkg:pypi/autogen",
|
|
114
|
+
"pkg:pypi/pyautogen",
|
|
115
|
+
"pkg:pypi/crewai",
|
|
116
|
+
"pkg:pypi/semantic-kernel",
|
|
117
|
+
"pkg:pypi/transformers",
|
|
118
|
+
"pkg:pypi/sentence-transformers",
|
|
119
|
+
"pkg:pypi/huggingface-hub",
|
|
120
|
+
"pkg:pypi/celery",
|
|
121
|
+
"pkg:pypi/kombu",
|
|
122
|
+
"pkg:pypi/dramatiq",
|
|
123
|
+
"pkg:pypi/huey",
|
|
124
|
+
"pkg:pypi/jinja2",
|
|
125
|
+
"pkg:pypi/mako",
|
|
126
|
+
"pkg:pypi/chameleon",
|
|
127
|
+
"pkg:pypi/genshi",
|
|
128
|
+
"pkg:pypi/twisted",
|
|
79
129
|
"vibora",
|
|
80
130
|
"koa",
|
|
81
131
|
"-sdk",
|
|
@@ -214,6 +264,41 @@
|
|
|
214
264
|
"pkg:gem/volt",
|
|
215
265
|
"pkg:gem/trailblazer",
|
|
216
266
|
"pkg:gem/ramaze",
|
|
217
|
-
"pkg:gem/scorched"
|
|
267
|
+
"pkg:gem/scorched",
|
|
268
|
+
"Grpc.AspNetCore",
|
|
269
|
+
"Microsoft.AspNetCore.SignalR",
|
|
270
|
+
"Microsoft.Azure.Functions.Worker",
|
|
271
|
+
"Microsoft.NET.Sdk.Functions",
|
|
272
|
+
"Amazon.Lambda.Core",
|
|
273
|
+
"MassTransit",
|
|
274
|
+
"NServiceBus",
|
|
275
|
+
"MediatR",
|
|
276
|
+
"Rebus",
|
|
277
|
+
"HotChocolate.AspNetCore",
|
|
278
|
+
"GraphQL",
|
|
279
|
+
"Microsoft.AspNetCore.OData",
|
|
280
|
+
"ModelContextProtocol",
|
|
281
|
+
"ModelContextProtocol.AspNetCore",
|
|
282
|
+
"Microsoft.SemanticKernel",
|
|
283
|
+
"Microsoft.Extensions.AI",
|
|
284
|
+
"OpenAI",
|
|
285
|
+
"Azure.AI.OpenAI",
|
|
286
|
+
"Anthropic.SDK",
|
|
287
|
+
"AWSSDK.BedrockRuntime",
|
|
288
|
+
"Hangfire.AspNetCore",
|
|
289
|
+
"Quartz",
|
|
290
|
+
"FastEndpoints",
|
|
291
|
+
"Carter",
|
|
292
|
+
"ServiceStack",
|
|
293
|
+
"Nancy",
|
|
294
|
+
"Microsoft.ML",
|
|
295
|
+
"Microsoft.ML.OnnxRuntime",
|
|
296
|
+
"TorchSharp",
|
|
297
|
+
"LLamaSharp",
|
|
298
|
+
"Qdrant.Client",
|
|
299
|
+
"Milvus.Client",
|
|
300
|
+
"Pinecone.NET",
|
|
301
|
+
"Dapr.AspNetCore",
|
|
302
|
+
"Confluent.Kafka"
|
|
218
303
|
]
|
|
219
304
|
}
|