@cdxgen/cdxgen 13.1.0 → 13.3.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 +32 -15
- package/bin/cdxgen.js +243 -122
- package/bin/evinse.js +7 -0
- package/bin/sign.js +88 -14
- package/bin/tracebom.js +64 -4
- package/bin/validate.js +29 -7
- package/bin/verify.js +79 -39
- package/data/crypto-oid.json +88 -12
- package/data/remediations.json +47 -0
- package/data/rules/ai-bom.yaml +78 -0
- package/data/rules/cargo-rust.yaml +132 -0
- package/data/rules/mcp-servers.yaml +122 -0
- package/lib/audit/targets.js +6 -1
- package/lib/cli/bomAssembly.js +117 -15
- package/lib/cli/cliOptions.js +93 -1
- package/lib/cli/index.js +235 -5
- package/lib/cli/jsBom.js +108 -26
- package/lib/cli/jvmBom.js +68 -12
- package/lib/cli/managedBom.js +264 -41
- package/lib/cli/nativeBom.js +923 -15
- package/lib/core/activity.js +120 -2
- package/lib/core/env.js +44 -7
- package/lib/core/fs.js +174 -6
- package/lib/core/metadataProperties.js +97 -0
- package/lib/core/projectConfig.js +31 -4
- package/lib/core/userAgent.js +151 -0
- package/lib/ecosystems/bunutils.js +269 -101
- package/lib/ecosystems/cargoCache.js +364 -0
- package/lib/ecosystems/caxa.js +447 -7
- package/lib/ecosystems/cmakeResolver.js +66 -0
- package/lib/ecosystems/cppEvidence.js +104 -33
- package/lib/ecosystems/ecosystems.js +260 -99
- package/lib/ecosystems/golem.js +11 -1
- package/lib/ecosystems/gradleutils.js +185 -9
- package/lib/ecosystems/jsEvidence.js +19 -20
- package/lib/ecosystems/kosi.js +1263 -0
- package/lib/ecosystems/npmutils.js +110 -9
- package/lib/ecosystems/parsers-crystal.js +179 -0
- package/lib/ecosystems/parsers-dotnet.js +120 -49
- package/lib/ecosystems/parsers-elm.js +816 -0
- package/lib/ecosystems/parsers-gleam.js +1 -1
- package/lib/ecosystems/parsers-go.js +47 -9
- package/lib/ecosystems/parsers-js.js +171 -50
- package/lib/ecosystems/parsers-julia.js +268 -0
- package/lib/ecosystems/parsers-lua.js +218 -0
- package/lib/ecosystems/parsers-misc.js +919 -161
- package/lib/ecosystems/parsers-nim.js +221 -0
- package/lib/ecosystems/parsers-opam.js +180 -0
- package/lib/ecosystems/parsers-perl.js +277 -0
- package/lib/ecosystems/parsers-python.js +27 -15
- package/lib/ecosystems/parsers-r.js +148 -0
- package/lib/ecosystems/parsers-rebar.js +411 -0
- package/lib/ecosystems/parsers-rust.js +954 -33
- package/lib/ecosystems/parsers-spack.js +204 -0
- package/lib/ecosystems/parsers-stack.js +264 -0
- package/lib/ecosystems/parsers-terraform.js +194 -0
- package/lib/ecosystems/rubyutils.js +1426 -166
- package/lib/ecosystems/rusi.js +158 -7
- package/lib/evinser/evinser.js +547 -129
- package/lib/evinser/swiftsem.js +1914 -302
- package/lib/helpers/agenticToolutils.js +925 -0
- package/lib/helpers/bomSigner.js +652 -221
- package/lib/inventory/agentFormulationParser.js +57 -4
- package/lib/inventory/aiCollector.js +504 -10
- package/lib/inventory/aiInventory.js +12 -0
- package/lib/inventory/analyzer.js +488 -30
- package/lib/inventory/astWorker.js +6 -0
- package/lib/inventory/atomUtils.js +568 -31
- package/lib/inventory/auditCategories.js +8 -0
- package/lib/inventory/cbomutils.js +30 -0
- package/lib/inventory/cdxrs.js +110 -14
- package/lib/inventory/communityAiConfigParser.js +215 -2
- package/lib/inventory/depsUtils.js +183 -11
- package/lib/inventory/display.js +4 -5
- package/lib/inventory/dosai.js +627 -13
- package/lib/inventory/dynamic.js +39 -1
- package/lib/inventory/envcontext.js +9 -6
- package/lib/inventory/evidenceUtils.js +26 -5
- package/lib/inventory/fetchBatch.js +190 -19
- package/lib/inventory/fetchRate.js +74 -11
- package/lib/inventory/forgeEnricher.js +3 -2
- package/lib/inventory/jvmToolEnv.js +6 -5
- package/lib/inventory/mcpConfigParser.js +166 -2
- package/lib/inventory/mcpDiscovery.js +11 -0
- package/lib/inventory/mcpServerManifest.js +389 -0
- package/lib/inventory/mcpbBundle.js +419 -0
- package/lib/inventory/plugins.js +3 -0
- package/lib/inventory/protobom.js +62 -89
- package/lib/inventory/protobomLoader.js +4 -0
- package/lib/inventory/purl.js +152 -3
- package/lib/inventory/rustFormulationParser.js +1 -1
- package/lib/inventory/sbomDocument.js +2 -70
- package/lib/inventory/source.js +47 -23
- package/lib/inventory/stylePackageRefs.js +41 -0
- package/lib/inventory/svelteUtils.js +524 -0
- package/lib/inventory/traceRunner.js +210 -21
- package/lib/managers/binary.js +115 -24
- package/lib/managers/docker.js +440 -20
- package/lib/managers/oci.js +39 -1
- package/lib/parsers/cmakeLists.js +452 -0
- package/lib/parsers/huggingfaceUtils.js +15 -7
- package/lib/parsers/largeJson.js +454 -0
- package/lib/parsers/npmrc.js +19 -1
- package/lib/parsers/onnx.js +294 -0
- package/lib/parsers/safetensors.js +114 -0
- package/lib/stages/postgen/introspection/markers.js +29 -6
- package/lib/stages/postgen/postgen.js +237 -16
- package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +462 -0
- package/lib/validator/bomValidator.js +6 -16
- package/lib/validator/index.js +48 -10
- package/lib/validator/reporters/console.js +3 -0
- package/lib/validator/reporters/json.js +1 -0
- package/lib/validator/reporters/sarif.js +7 -0
- package/package.json +27 -27
- package/types/lib/audit/targets.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +2 -1
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +33 -1
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +2 -2
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +23 -0
- 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 +33 -0
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts +88 -8
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/activity.d.ts.map +1 -1
- package/types/lib/core/env.d.ts +21 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +55 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/metadataProperties.d.ts +39 -0
- package/types/lib/core/metadataProperties.d.ts.map +1 -0
- package/types/lib/core/projectConfig.d.ts +6 -2
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/userAgent.d.ts +56 -0
- package/types/lib/core/userAgent.d.ts.map +1 -0
- package/types/lib/ecosystems/bunutils.d.ts +12 -5
- package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
- package/types/lib/ecosystems/cargoCache.d.ts +75 -0
- package/types/lib/ecosystems/cargoCache.d.ts.map +1 -0
- package/types/lib/ecosystems/caxa.d.ts +14 -0
- package/types/lib/ecosystems/caxa.d.ts.map +1 -1
- package/types/lib/ecosystems/cmakeResolver.d.ts +23 -0
- package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
- package/types/lib/ecosystems/cppEvidence.d.ts +2 -2
- package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/ecosystems.d.ts +15 -1
- package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +40 -4
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +5 -2
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts +86 -0
- package/types/lib/ecosystems/kosi.d.ts.map +1 -0
- package/types/lib/ecosystems/npmutils.d.ts +42 -0
- package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-crystal.d.ts +27 -0
- package/types/lib/ecosystems/parsers-crystal.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts +19 -0
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-elm.d.ts +79 -0
- package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-go.d.ts +10 -0
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-js.d.ts +10 -4
- package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-julia.d.ts +57 -0
- package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-lua.d.ts +50 -0
- package/types/lib/ecosystems/parsers-lua.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-misc.d.ts +90 -3
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-nim.d.ts +43 -0
- package/types/lib/ecosystems/parsers-nim.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-opam.d.ts +31 -0
- package/types/lib/ecosystems/parsers-opam.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-perl.d.ts +36 -0
- package/types/lib/ecosystems/parsers-perl.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-r.d.ts +35 -0
- package/types/lib/ecosystems/parsers-r.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rebar.d.ts +42 -0
- package/types/lib/ecosystems/parsers-rebar.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-rust.d.ts +199 -0
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-spack.d.ts +33 -0
- package/types/lib/ecosystems/parsers-spack.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-stack.d.ts +35 -0
- package/types/lib/ecosystems/parsers-stack.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-terraform.d.ts +34 -0
- package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -0
- package/types/lib/ecosystems/pythonutils.d.ts +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts +143 -2
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts +13 -0
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +81 -2
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +280 -15
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +87 -0
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -0
- package/types/lib/helpers/bomSigner.d.ts +106 -13
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/analyzer.d.ts.map +1 -1
- package/types/lib/inventory/atomUtils.d.ts +145 -3
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/auditCategories.d.ts +4 -0
- package/types/lib/inventory/auditCategories.d.ts.map +1 -1
- package/types/lib/inventory/cbomutils.d.ts.map +1 -1
- package/types/lib/inventory/cdxrs.d.ts +8 -3
- package/types/lib/inventory/cdxrs.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/depsUtils.d.ts +15 -0
- package/types/lib/inventory/depsUtils.d.ts.map +1 -1
- package/types/lib/inventory/display.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +87 -1
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/fetchBatch.d.ts +34 -0
- package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
- package/types/lib/inventory/fetchRate.d.ts +9 -6
- package/types/lib/inventory/fetchRate.d.ts.map +1 -1
- package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
- package/types/lib/inventory/jvmToolEnv.d.ts +5 -4
- package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -1
- package/types/lib/inventory/mcpServerManifest.d.ts +19 -0
- package/types/lib/inventory/mcpServerManifest.d.ts.map +1 -0
- package/types/lib/inventory/mcpbBundle.d.ts +19 -0
- package/types/lib/inventory/mcpbBundle.d.ts.map +1 -0
- package/types/lib/inventory/plugins.d.ts.map +1 -1
- package/types/lib/inventory/protobom.d.ts +18 -13
- package/types/lib/inventory/protobom.d.ts.map +1 -1
- package/types/lib/inventory/protobomLoader.d.ts.map +1 -1
- package/types/lib/inventory/purl.d.ts +71 -2
- package/types/lib/inventory/purl.d.ts.map +1 -1
- package/types/lib/inventory/sbomDocument.d.ts.map +1 -1
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/stylePackageRefs.d.ts +17 -0
- package/types/lib/inventory/stylePackageRefs.d.ts.map +1 -0
- package/types/lib/inventory/svelteUtils.d.ts +124 -0
- package/types/lib/inventory/svelteUtils.d.ts.map +1 -0
- package/types/lib/inventory/traceRunner.d.ts +47 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +30 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +29 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts +14 -0
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/parsers/cmakeLists.d.ts +76 -0
- package/types/lib/parsers/cmakeLists.d.ts.map +1 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts +8 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/largeJson.d.ts +52 -0
- package/types/lib/parsers/largeJson.d.ts.map +1 -0
- package/types/lib/parsers/npmrc.d.ts +5 -0
- package/types/lib/parsers/npmrc.d.ts.map +1 -1
- package/types/lib/parsers/onnx.d.ts +28 -0
- package/types/lib/parsers/onnx.d.ts.map +1 -0
- package/types/lib/parsers/safetensors.d.ts +22 -0
- package/types/lib/parsers/safetensors.d.ts.map +1 -0
- package/types/lib/stages/postgen/introspection/markers.d.ts +3 -2
- package/types/lib/stages/postgen/introspection/markers.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +33 -0
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -1
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/console.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
- package/types/lib/validator/reporters/sarif.d.ts.map +1 -1
package/bin/cdxgen.js
CHANGED
|
@@ -19,6 +19,7 @@ import { parse as _load } from "yaml";
|
|
|
19
19
|
import yargs from "yargs";
|
|
20
20
|
import { hideBin } from "yargs/helpers";
|
|
21
21
|
|
|
22
|
+
import { getExactAiInventoryType } from "../lib/cli/bomAssembly.js";
|
|
22
23
|
import {
|
|
23
24
|
applyAdvancedOptions as applyAdvancedOptionsImpl,
|
|
24
25
|
buildOptionsFromArgs,
|
|
@@ -71,7 +72,11 @@ import {
|
|
|
71
72
|
setDryRunMode,
|
|
72
73
|
shouldRunPredictiveBomAudit,
|
|
73
74
|
} from "../lib/ecosystems/utils.js";
|
|
74
|
-
import {
|
|
75
|
+
import {
|
|
76
|
+
generateSigningKeyPair,
|
|
77
|
+
signBom,
|
|
78
|
+
verifyBom,
|
|
79
|
+
} from "../lib/helpers/bomSigner.js";
|
|
75
80
|
import {
|
|
76
81
|
createOutputPlan,
|
|
77
82
|
getOutputDirectory,
|
|
@@ -80,7 +85,6 @@ import {
|
|
|
80
85
|
DEFAULT_CDX_SPEC_VERSION,
|
|
81
86
|
getSupportedCycloneDxComponentTypes,
|
|
82
87
|
isCycloneDxBom,
|
|
83
|
-
isCycloneDxComponentTypeEnabled,
|
|
84
88
|
normalizeCycloneDxComponentTypeFilter,
|
|
85
89
|
toCycloneDxSpecVersionString,
|
|
86
90
|
} from "../lib/inventory/bomUtils.js";
|
|
@@ -123,7 +127,10 @@ import {
|
|
|
123
127
|
} from "../lib/inventory/source.js";
|
|
124
128
|
import { executeOsQuery } from "../lib/managers/binary.js";
|
|
125
129
|
import { getBomWithOras } from "../lib/managers/oci.js";
|
|
126
|
-
import {
|
|
130
|
+
import {
|
|
131
|
+
applyEvidenceBasedFilter,
|
|
132
|
+
postProcess,
|
|
133
|
+
} from "../lib/stages/postgen/postgen.js";
|
|
127
134
|
import { convertCycloneDxToSpdx } from "../lib/stages/postgen/spdxConverter.js";
|
|
128
135
|
import { auditEnvironment } from "../lib/stages/pregen/envAudit.js";
|
|
129
136
|
import { prepareEnv } from "../lib/stages/pregen/pregen.js";
|
|
@@ -160,6 +167,11 @@ for (const configPattern of PROJECT_CONFIG_FILENAMES) {
|
|
|
160
167
|
`Config file '${configPath}' sets '${foundKey}'. Verify this is intentional.`,
|
|
161
168
|
);
|
|
162
169
|
}
|
|
170
|
+
for (const propertyName of sanitized.reservedProperties) {
|
|
171
|
+
console.warn(
|
|
172
|
+
`\x1b[1;35mConfig file '${configPath}' sets the metadata property '${propertyName}', whose namespace cdxgen reserves for its own findings. Ignoring it. Pass the property with --metadata-property if this is intentional.\x1b[0m`,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
163
175
|
} catch (_e) {
|
|
164
176
|
console.log("Invalid config file", configPath);
|
|
165
177
|
}
|
|
@@ -248,6 +260,16 @@ const args = _yargs
|
|
|
248
260
|
description:
|
|
249
261
|
"Perform deep searches for components. Useful while scanning C/C++ apps, live OS and oci images.",
|
|
250
262
|
})
|
|
263
|
+
.option("cmake-cache", {
|
|
264
|
+
type: "string",
|
|
265
|
+
description:
|
|
266
|
+
"Path to the CMakeCache.txt of a configured C/C++ build. Overrides the lookup under build/, out/ and cmake-build-*/.",
|
|
267
|
+
})
|
|
268
|
+
.option("compile-commands", {
|
|
269
|
+
type: "string",
|
|
270
|
+
description:
|
|
271
|
+
"Path to the compile_commands.json of a C/C++ build, or a directory holding one. atom then parses each file with its build's include paths, macros and language. Overrides the lookup in the project root, build/, out/, builddir/ and cmake-build-*/, which is skipped in secure mode.",
|
|
272
|
+
})
|
|
251
273
|
.option("git-branch", {
|
|
252
274
|
description: "Git branch to clone when the source is a git URL or purl",
|
|
253
275
|
type: "string",
|
|
@@ -395,7 +417,7 @@ const args = _yargs
|
|
|
395
417
|
.option("generate-key-and-sign", {
|
|
396
418
|
type: "boolean",
|
|
397
419
|
description:
|
|
398
|
-
"Generate
|
|
420
|
+
"Generate a public/private key pair for SBOM_SIGN_ALGORITHM (RS512 by default) and then sign the generated SBOM using the JSON Signature Format (JSF).",
|
|
399
421
|
})
|
|
400
422
|
.option("server", {
|
|
401
423
|
type: "boolean",
|
|
@@ -561,6 +583,11 @@ const args = _yargs
|
|
|
561
583
|
default: false,
|
|
562
584
|
description: "Disable default ignore lists during scanning.",
|
|
563
585
|
})
|
|
586
|
+
.option("caxa-app-dir", {
|
|
587
|
+
type: "string",
|
|
588
|
+
description:
|
|
589
|
+
"Directory of the app a caxa binary extracts. With -t caxa, also records the native tools, the vendored PHP, Ruby and Java packages, and the npm integrity hashes found there.",
|
|
590
|
+
})
|
|
564
591
|
.option("export-proto", {
|
|
565
592
|
type: "boolean",
|
|
566
593
|
default: false,
|
|
@@ -601,6 +628,12 @@ const args = _yargs
|
|
|
601
628
|
default: false,
|
|
602
629
|
description: "Synthesize custom LicenseRef IDs for unresolved licenses.",
|
|
603
630
|
})
|
|
631
|
+
.option("metadata-property", {
|
|
632
|
+
description:
|
|
633
|
+
"Custom property to add to the BOM metadata, as name=value. Repeat the flag for several properties. Combined with the properties of the CDXGEN_METADATA_PROPERTIES environment variable and of a config file.",
|
|
634
|
+
nargs: 1,
|
|
635
|
+
type: "array",
|
|
636
|
+
})
|
|
604
637
|
.option("standard", {
|
|
605
638
|
description:
|
|
606
639
|
"The list of standards which may consist of regulations, industry or organizational-specific standards, maturity models, best practices, or any other requirements which can be evaluated against or attested to.",
|
|
@@ -1043,6 +1076,7 @@ const { options, warnings: phase3Warnings } = buildOptionsFromArgs(args, {
|
|
|
1043
1076
|
userSetSpecVersion,
|
|
1044
1077
|
isDryRun,
|
|
1045
1078
|
isSecureMode,
|
|
1079
|
+
projectConfig: config,
|
|
1046
1080
|
});
|
|
1047
1081
|
// Exit status reserved for the introspection CI gate: the BOM was generated
|
|
1048
1082
|
// and written, but its introspection score missed the configured threshold.
|
|
@@ -1406,6 +1440,8 @@ const checkPermissions = (filePath, options) => {
|
|
|
1406
1440
|
return true;
|
|
1407
1441
|
};
|
|
1408
1442
|
|
|
1443
|
+
let warnedAboutSigningAlgorithm = false;
|
|
1444
|
+
|
|
1409
1445
|
const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
1410
1446
|
generateKeyAndSign ||
|
|
1411
1447
|
(() => {
|
|
@@ -1423,11 +1459,19 @@ const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
|
1423
1459
|
sensitive: true,
|
|
1424
1460
|
},
|
|
1425
1461
|
);
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1462
|
+
const keyConfigured = Boolean(
|
|
1463
|
+
sbomSignPrivateKey || sbomSignPrivateKeyBase64,
|
|
1464
|
+
);
|
|
1465
|
+
if (keyConfigured && !sbomSignAlgorithm && !warnedAboutSigningAlgorithm) {
|
|
1466
|
+
warnedAboutSigningAlgorithm = true;
|
|
1467
|
+
console.warn(
|
|
1468
|
+
"SBOM_SIGN_PRIVATE_KEY is set without SBOM_SIGN_ALGORITHM, so the BOM is not signed. Set SBOM_SIGN_ALGORITHM (for example RS512) to sign it, or SBOM_SIGN_ALGORITHM=none to silence this warning.",
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
// A configured key file that is missing counts as a signing request, so
|
|
1472
|
+
// that signing fails loudly instead of being skipped.
|
|
1473
|
+
return Boolean(
|
|
1474
|
+
sbomSignAlgorithm && sbomSignAlgorithm !== "none" && keyConfigured,
|
|
1431
1475
|
);
|
|
1432
1476
|
})();
|
|
1433
1477
|
|
|
@@ -1436,28 +1480,20 @@ const stringifyJson = (jsonPayload, jsonPretty) =>
|
|
|
1436
1480
|
? jsonPayload
|
|
1437
1481
|
: JSON.stringify(jsonPayload, null, jsonPretty ? 2 : null);
|
|
1438
1482
|
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
recordActivity({
|
|
1454
|
-
kind: "sign",
|
|
1455
|
-
reason: "Dry run mode skips BOM signing and key generation.",
|
|
1456
|
-
status: "blocked",
|
|
1457
|
-
target: jsonFile,
|
|
1458
|
-
});
|
|
1459
|
-
return jsonPayload;
|
|
1460
|
-
}
|
|
1483
|
+
const SIGNING_HINT =
|
|
1484
|
+
"Check that the private key is in PEM format and that SBOM_SIGN_ALGORITHM matches its key type.";
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* Signs a CycloneDX payload with the configured or generated key.
|
|
1488
|
+
*
|
|
1489
|
+
* @param {string} jsonPayload Serialized CycloneDX BOM
|
|
1490
|
+
* @param {string|undefined} keyDir Directory for --generate-key-and-sign keys
|
|
1491
|
+
* @param {string} target Output the signed BOM is written to (for the activity log)
|
|
1492
|
+
* @param {Object} options CLI options
|
|
1493
|
+
* @returns {Object} Signed BOM
|
|
1494
|
+
* @throws {Error} When signing was requested but cannot be completed
|
|
1495
|
+
*/
|
|
1496
|
+
const signCycloneDxPayload = (jsonPayload, keyDir, target, options) => {
|
|
1461
1497
|
const sbomSignAlgorithm = readEnvironmentVariable("SBOM_SIGN_ALGORITHM");
|
|
1462
1498
|
const sbomSignPrivateKey = readEnvironmentVariable("SBOM_SIGN_PRIVATE_KEY", {
|
|
1463
1499
|
sensitive: true,
|
|
@@ -1472,29 +1508,20 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1472
1508
|
const sbomSignPublicKeyBase64 = readEnvironmentVariable(
|
|
1473
1509
|
"SBOM_SIGN_PUBLIC_KEY_BASE64",
|
|
1474
1510
|
);
|
|
1475
|
-
|
|
1476
|
-
if (alg.includes("none")) {
|
|
1477
|
-
alg = "RS512";
|
|
1478
|
-
}
|
|
1511
|
+
const alg = sbomSignAlgorithm || "RS512";
|
|
1479
1512
|
let privateKeyToUse;
|
|
1480
1513
|
let jwkPublicKey;
|
|
1481
1514
|
let publicKeyFile;
|
|
1482
1515
|
if (options.generateKeyAndSign) {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
},
|
|
1493
|
-
privateKeyEncoding: {
|
|
1494
|
-
type: "pkcs8",
|
|
1495
|
-
format: "pem",
|
|
1496
|
-
},
|
|
1497
|
-
});
|
|
1516
|
+
if (!keyDir) {
|
|
1517
|
+
throw new Error(
|
|
1518
|
+
"--generate-key-and-sign needs a file output (-o) to write the generated keys next to.",
|
|
1519
|
+
);
|
|
1520
|
+
}
|
|
1521
|
+
publicKeyFile = join(keyDir, "public.key");
|
|
1522
|
+
const privateKeyFile = join(keyDir, "private.key");
|
|
1523
|
+
const privateKeyB64File = join(keyDir, "private.key.base64");
|
|
1524
|
+
const { privateKey, publicKey } = generateSigningKeyPair(alg);
|
|
1498
1525
|
safeWriteSync(publicKeyFile, publicKey);
|
|
1499
1526
|
safeWriteSync(privateKeyFile, privateKey);
|
|
1500
1527
|
safeWriteSync(
|
|
@@ -1511,69 +1538,129 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1511
1538
|
jwkPublicKey = crypto.createPublicKey(publicKey).export({ format: "jwk" });
|
|
1512
1539
|
} else {
|
|
1513
1540
|
if (sbomSignPrivateKey) {
|
|
1541
|
+
if (!safeExistsSync(sbomSignPrivateKey)) {
|
|
1542
|
+
throw new Error(
|
|
1543
|
+
`The SBOM_SIGN_PRIVATE_KEY file '${sbomSignPrivateKey}' was not found.`,
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1514
1546
|
recordSensitiveFileRead(sbomSignPrivateKey, {
|
|
1515
1547
|
label: "SBOM signing private key",
|
|
1516
1548
|
});
|
|
1517
|
-
privateKeyToUse = fs.readFileSync(sbomSignPrivateKey
|
|
1549
|
+
privateKeyToUse = fs.readFileSync(sbomSignPrivateKey);
|
|
1518
1550
|
} else if (sbomSignPrivateKeyBase64) {
|
|
1519
|
-
privateKeyToUse = Buffer.from(
|
|
1520
|
-
sbomSignPrivateKeyBase64,
|
|
1521
|
-
"base64",
|
|
1522
|
-
).toString("utf8");
|
|
1551
|
+
privateKeyToUse = Buffer.from(sbomSignPrivateKeyBase64, "base64");
|
|
1523
1552
|
}
|
|
1524
1553
|
if (sbomSignPublicKey && safeExistsSync(sbomSignPublicKey)) {
|
|
1525
1554
|
jwkPublicKey = crypto
|
|
1526
1555
|
.createPublicKey(fs.readFileSync(sbomSignPublicKey, "utf8"))
|
|
1527
1556
|
.export({ format: "jwk" });
|
|
1528
1557
|
} else if (sbomSignPublicKeyBase64) {
|
|
1529
|
-
jwkPublicKey =
|
|
1530
|
-
"
|
|
1558
|
+
jwkPublicKey = crypto
|
|
1559
|
+
.createPublicKey(Buffer.from(sbomSignPublicKeyBase64, "base64"))
|
|
1560
|
+
.export({ format: "jwk" });
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
thoughtLog(`Signing the BOM for "${target}".`);
|
|
1564
|
+
const signedBom = signBom(JSON.parse(jsonPayload), {
|
|
1565
|
+
privateKey: privateKeyToUse,
|
|
1566
|
+
algorithm: alg,
|
|
1567
|
+
publicKeyJwk: jwkPublicKey,
|
|
1568
|
+
mode: readEnvironmentVariable("SBOM_SIGN_MODE") || "replace",
|
|
1569
|
+
signComponents: true,
|
|
1570
|
+
signServices: true,
|
|
1571
|
+
signAnnotations: true,
|
|
1572
|
+
});
|
|
1573
|
+
if (publicKeyFile) {
|
|
1574
|
+
if (!verifyBom(signedBom, fs.readFileSync(publicKeyFile, "utf8"))) {
|
|
1575
|
+
throw new Error(
|
|
1576
|
+
`The new signature does not verify with ${publicKeyFile}.`,
|
|
1531
1577
|
);
|
|
1532
1578
|
}
|
|
1579
|
+
console.log(
|
|
1580
|
+
"SBOM signature is verifiable natively with the public key and the algorithm",
|
|
1581
|
+
publicKeyFile,
|
|
1582
|
+
alg,
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1585
|
+
recordActivity({
|
|
1586
|
+
kind: "sign",
|
|
1587
|
+
status: "completed",
|
|
1588
|
+
target,
|
|
1589
|
+
});
|
|
1590
|
+
return signedBom;
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1593
|
+
/**
|
|
1594
|
+
* Signs the BOM for an output when signing is configured. A failure is
|
|
1595
|
+
* recorded and returned so that the caller can stop with a non-zero exit
|
|
1596
|
+
* instead of publishing an unsigned BOM.
|
|
1597
|
+
*
|
|
1598
|
+
* @returns {{ bomJson: Object, jsonPayload: string, signingError?: Error }}
|
|
1599
|
+
*/
|
|
1600
|
+
const signForOutput = (bomJson, jsonPayload, keyDir, target, options) => {
|
|
1601
|
+
if (!jsonPayload || !needsBomSigning(options)) {
|
|
1602
|
+
return { bomJson, jsonPayload };
|
|
1603
|
+
}
|
|
1604
|
+
if (isDryRun) {
|
|
1605
|
+
recordActivity({
|
|
1606
|
+
kind: "sign",
|
|
1607
|
+
reason: "Dry run mode skips BOM signing and key generation.",
|
|
1608
|
+
status: "blocked",
|
|
1609
|
+
target,
|
|
1610
|
+
});
|
|
1611
|
+
return { bomJson, jsonPayload };
|
|
1533
1612
|
}
|
|
1534
1613
|
try {
|
|
1535
|
-
const
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1614
|
+
const signedBom = signCycloneDxPayload(
|
|
1615
|
+
jsonPayload,
|
|
1616
|
+
keyDir,
|
|
1617
|
+
target,
|
|
1618
|
+
options,
|
|
1619
|
+
);
|
|
1620
|
+
return {
|
|
1621
|
+
bomJson: signedBom,
|
|
1622
|
+
jsonPayload: JSON.stringify(
|
|
1623
|
+
signedBom,
|
|
1624
|
+
null,
|
|
1625
|
+
options.jsonPretty ? 2 : null,
|
|
1626
|
+
),
|
|
1544
1627
|
};
|
|
1545
|
-
|
|
1628
|
+
} catch (err) {
|
|
1546
1629
|
recordActivity({
|
|
1547
1630
|
kind: "sign",
|
|
1548
|
-
|
|
1549
|
-
|
|
1631
|
+
reason: err.message,
|
|
1632
|
+
status: "failed",
|
|
1633
|
+
target,
|
|
1550
1634
|
});
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1635
|
+
return { bomJson, jsonPayload, signingError: err };
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
|
|
1639
|
+
const reportSigningFailure = (signingError, target) => {
|
|
1640
|
+
console.error(`SBOM signing was unsuccessful: ${signingError.message}`);
|
|
1641
|
+
console.error(SIGNING_HINT);
|
|
1642
|
+
if (target !== "stdout") {
|
|
1643
|
+
console.error(`The BOM at '${target}' was written without a signature.`);
|
|
1644
|
+
}
|
|
1645
|
+
};
|
|
1646
|
+
|
|
1647
|
+
const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
1648
|
+
const result = signForOutput(
|
|
1649
|
+
bomJson,
|
|
1650
|
+
stringifyJson(bomJson, options.jsonPretty),
|
|
1651
|
+
dirname(jsonFile),
|
|
1652
|
+
jsonFile,
|
|
1653
|
+
options,
|
|
1654
|
+
);
|
|
1655
|
+
safeWriteSync(jsonFile, result.jsonPayload);
|
|
1656
|
+
if (jsonFile.endsWith("bom.json")) {
|
|
1657
|
+
thoughtLog(
|
|
1658
|
+
`Let's save the file to "${jsonFile}". Should I suggest the '.cdx.json' file extension for better semantics?`,
|
|
1574
1659
|
);
|
|
1660
|
+
} else {
|
|
1661
|
+
thoughtLog(`Let's save the file to "${jsonFile}".`);
|
|
1575
1662
|
}
|
|
1576
|
-
return
|
|
1663
|
+
return result;
|
|
1577
1664
|
};
|
|
1578
1665
|
|
|
1579
1666
|
/**
|
|
@@ -1601,7 +1688,14 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
1601
1688
|
}
|
|
1602
1689
|
let sourcePath = filePath;
|
|
1603
1690
|
let purlResolution;
|
|
1604
|
-
|
|
1691
|
+
// Direct HuggingFace interpretation of the source path is opt-in: bare
|
|
1692
|
+
// `owner/repo`-shaped values are ordinary relative paths (eg: repotests/
|
|
1693
|
+
// sveltejs-realworld) unless an AI inventory type such as `-t ai` is
|
|
1694
|
+
// explicitly selected. Unambiguous purls and huggingface.co URLs always
|
|
1695
|
+
// resolve.
|
|
1696
|
+
const directHuggingFaceSource = normalizeHuggingFaceReference(sourcePath, {
|
|
1697
|
+
explicitOnly: getExactAiInventoryType(options) !== "ai",
|
|
1698
|
+
});
|
|
1605
1699
|
if (isDryRun && directHuggingFaceSource) {
|
|
1606
1700
|
recordActivity({
|
|
1607
1701
|
kind: "read",
|
|
@@ -2044,27 +2138,11 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2044
2138
|
});
|
|
2045
2139
|
const evinserModule = await import("../lib/evinser/evinser.js");
|
|
2046
2140
|
options.projectType = options.projectType || ["java"];
|
|
2047
|
-
const evinseOptions =
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
skipMavenCollector: false,
|
|
2053
|
-
force: false,
|
|
2054
|
-
withReachables: options.deep,
|
|
2055
|
-
usagesSlicesFile: options.usagesSlicesFile,
|
|
2056
|
-
dataFlowSlicesFile: options.dataFlowSlicesFile,
|
|
2057
|
-
reachablesSlicesFile: options.reachablesSlicesFile,
|
|
2058
|
-
semanticsSlicesFile: options.semanticsSlicesFile,
|
|
2059
|
-
openapiSpecFile: options.openapiSpecFile,
|
|
2060
|
-
componentType: options.componentType,
|
|
2061
|
-
includeCrypto:
|
|
2062
|
-
options.includeCrypto &&
|
|
2063
|
-
isCycloneDxComponentTypeEnabled("cryptographic-asset", options),
|
|
2064
|
-
specVersion: options.specVersion,
|
|
2065
|
-
profile: options.profile,
|
|
2066
|
-
jsonPretty: options.jsonPretty,
|
|
2067
|
-
};
|
|
2141
|
+
const evinseOptions = evinserModule.buildEvinseOptions(
|
|
2142
|
+
options,
|
|
2143
|
+
args,
|
|
2144
|
+
internalCycloneDxInputPath || options.output,
|
|
2145
|
+
);
|
|
2068
2146
|
const dbObjMap = await evinserModule.prepareDB(evinseOptions);
|
|
2069
2147
|
if (dbObjMap) {
|
|
2070
2148
|
const sliceArtefacts = await evinserModule.analyzeProject(
|
|
@@ -2075,7 +2153,9 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2075
2153
|
sliceArtefacts,
|
|
2076
2154
|
evinseOptions,
|
|
2077
2155
|
);
|
|
2078
|
-
|
|
2156
|
+
// The scope filter is deferred until here so the analyzers get to
|
|
2157
|
+
// prove that an optional dependency is actually used.
|
|
2158
|
+
bomNSData.bomJson = applyEvidenceBasedFilter(evinseJson, options);
|
|
2079
2159
|
if (options.print && evinseJson) {
|
|
2080
2160
|
printOccurrences(evinseJson);
|
|
2081
2161
|
printCallStack(evinseJson);
|
|
@@ -2151,10 +2231,27 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2151
2231
|
}
|
|
2152
2232
|
if (outputIsStdout) {
|
|
2153
2233
|
if (!isDryRun && bomNSData.bomJson) {
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2234
|
+
let payload;
|
|
2235
|
+
if (outputPlan.formats.has("spdx") && bomNSData.spdxJson) {
|
|
2236
|
+
payload = stringifyJson(bomNSData.spdxJson, options.jsonPretty);
|
|
2237
|
+
} else {
|
|
2238
|
+
const result = signForOutput(
|
|
2239
|
+
bomNSData.bomJson,
|
|
2240
|
+
stringifyJson(bomNSData.bomJson, options.jsonPretty),
|
|
2241
|
+
undefined,
|
|
2242
|
+
"stdout",
|
|
2243
|
+
options,
|
|
2244
|
+
);
|
|
2245
|
+
if (result.signingError) {
|
|
2246
|
+
reportSigningFailure(result.signingError, "stdout");
|
|
2247
|
+
if (cleanup) {
|
|
2248
|
+
cleanupSourceDir(srcDir);
|
|
2249
|
+
}
|
|
2250
|
+
process.exit(1);
|
|
2251
|
+
}
|
|
2252
|
+
bomNSData.bomJson = result.bomJson;
|
|
2253
|
+
payload = result.jsonPayload;
|
|
2254
|
+
}
|
|
2158
2255
|
process.stdout.write(payload);
|
|
2159
2256
|
} else if (isDryRun) {
|
|
2160
2257
|
recordActivity({
|
|
@@ -2169,11 +2266,20 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2169
2266
|
(typeof options.output === "string" || options.output instanceof String)
|
|
2170
2267
|
) {
|
|
2171
2268
|
if (!isDryRun && outputPlan.outputs.cyclonedx && bomNSData.bomJson) {
|
|
2172
|
-
writeCycloneDxOutput(
|
|
2269
|
+
const result = writeCycloneDxOutput(
|
|
2173
2270
|
outputPlan.outputs.cyclonedx,
|
|
2174
2271
|
bomNSData.bomJson,
|
|
2175
2272
|
options,
|
|
2176
2273
|
);
|
|
2274
|
+
if (result.signingError) {
|
|
2275
|
+
reportSigningFailure(result.signingError, outputPlan.outputs.cyclonedx);
|
|
2276
|
+
if (cleanup) {
|
|
2277
|
+
cleanupSourceDir(srcDir);
|
|
2278
|
+
}
|
|
2279
|
+
process.exit(1);
|
|
2280
|
+
}
|
|
2281
|
+
// Later consumers, such as the Dependency-Track upload, get the signed BOM.
|
|
2282
|
+
bomNSData.bomJson = result.bomJson;
|
|
2177
2283
|
if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
|
|
2178
2284
|
const nsFile = `${outputPlan.outputs.cyclonedx}.map`;
|
|
2179
2285
|
safeWriteSync(nsFile, JSON.stringify(bomNSData.nsMapping));
|
|
@@ -2204,7 +2310,22 @@ const writeCycloneDxOutput = (jsonFile, bomJson, options) => {
|
|
|
2204
2310
|
if (outputPlan.formats.has("spdx") && bomNSData?.spdxJson) {
|
|
2205
2311
|
console.log(stringifyJson(bomNSData.spdxJson, options.jsonPretty));
|
|
2206
2312
|
} else if (bomNSData.bomJson) {
|
|
2207
|
-
|
|
2313
|
+
const result = signForOutput(
|
|
2314
|
+
bomNSData.bomJson,
|
|
2315
|
+
stringifyJson(bomNSData.bomJson, options.jsonPretty),
|
|
2316
|
+
undefined,
|
|
2317
|
+
"stdout",
|
|
2318
|
+
options,
|
|
2319
|
+
);
|
|
2320
|
+
if (result.signingError) {
|
|
2321
|
+
reportSigningFailure(result.signingError, "stdout");
|
|
2322
|
+
if (cleanup) {
|
|
2323
|
+
cleanupSourceDir(srcDir);
|
|
2324
|
+
}
|
|
2325
|
+
process.exit(1);
|
|
2326
|
+
}
|
|
2327
|
+
bomNSData.bomJson = result.bomJson;
|
|
2328
|
+
console.log(result.jsonPayload);
|
|
2208
2329
|
} else {
|
|
2209
2330
|
console.log("Unable to produce BOM for", filePath);
|
|
2210
2331
|
console.log("Try running the command with -t <type> or -r argument");
|
package/bin/evinse.js
CHANGED
|
@@ -45,6 +45,8 @@ const args = yargs(hideBin(process.argv))
|
|
|
45
45
|
choices: [
|
|
46
46
|
"java",
|
|
47
47
|
"jar",
|
|
48
|
+
"kotlin",
|
|
49
|
+
"kt",
|
|
48
50
|
"js",
|
|
49
51
|
"ts",
|
|
50
52
|
"javascript",
|
|
@@ -87,6 +89,11 @@ const args = yargs(hideBin(process.argv))
|
|
|
87
89
|
default: false,
|
|
88
90
|
type: "boolean",
|
|
89
91
|
})
|
|
92
|
+
.option("compile-commands", {
|
|
93
|
+
description:
|
|
94
|
+
"Path to the compile_commands.json of a C/C++ build, or a directory holding one, for atom to parse each file as its build does. Overrides the lookup in the project root, build/, out/, builddir/ and cmake-build-*/, which is skipped in secure mode.",
|
|
95
|
+
type: "string",
|
|
96
|
+
})
|
|
90
97
|
.option("golem-command", {
|
|
91
98
|
description: "Use a specific golem binary for Go Evinse analysis.",
|
|
92
99
|
default: readEnvironmentVariable("GOLEM_CMD"),
|