@cyclonedx/cdxgen 11.4.0 → 11.4.2
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 +4 -1
- package/bin/cdxgen.js +32 -9
- package/bin/evinse.js +2 -0
- package/bin/repl.js +12 -4
- package/bin/verify.js +2 -0
- package/lib/cli/index.js +71 -57
- package/lib/evinser/evinser.js +26 -20
- package/lib/evinser/evinser.test.js +2 -2
- package/lib/evinser/swiftsem.js +1 -0
- package/lib/evinser/swiftsem.test.js +2 -2
- package/lib/helpers/analyzer.js +5 -4
- package/lib/helpers/cbomutils.js +2 -0
- package/lib/helpers/db.js +1 -0
- package/lib/helpers/display.js +1 -0
- package/lib/helpers/display.test.js +2 -0
- package/lib/helpers/envcontext.js +10 -8
- package/lib/helpers/envcontext.test.js +3 -1
- package/lib/helpers/logger.js +70 -10
- package/lib/helpers/protobom.js +29 -16
- package/lib/helpers/protobom.test.js +4 -1
- package/lib/helpers/utils.js +276 -106
- package/lib/helpers/utils.test.js +41 -11
- package/lib/helpers/validator.js +5 -5
- package/lib/managers/binary.js +17 -15
- package/lib/managers/docker.js +33 -31
- package/lib/managers/docker.test.js +2 -0
- package/lib/managers/oci.js +2 -1
- package/lib/managers/piptree.js +1 -0
- package/lib/server/server.js +90 -27
- package/lib/server/server.test.js +126 -0
- package/lib/stages/postgen/annotator.js +1 -0
- package/lib/stages/postgen/annotator.test.js +2 -2
- package/lib/stages/postgen/postgen.js +14 -6
- package/lib/stages/postgen/postgen.test.js +3 -2
- package/lib/stages/pregen/pregen.js +4 -3
- package/package.json +12 -11
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/cbomutils.d.ts.map +1 -1
- package/types/lib/helpers/db.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/envcontext.d.ts.map +1 -1
- package/types/lib/helpers/logger.d.ts +9 -0
- package/types/lib/helpers/logger.d.ts.map +1 -1
- package/types/lib/helpers/protobom.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +6 -3
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/managers/piptree.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +11 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -152,7 +152,8 @@ Options:
|
|
|
152
152
|
--validate Validate the generated SBOM using json schema. Defaults to true. Pass --no-validate to di
|
|
153
153
|
sable. [boolean] [default: true]
|
|
154
154
|
--evidence Generate SBOM with evidence for supported languages. [boolean] [default: false]
|
|
155
|
-
--spec-version CycloneDX Specification version to use. Defaults to 1.6
|
|
155
|
+
--spec-version CycloneDX Specification version to use. Defaults to 1.6
|
|
156
|
+
[number] [choices: 1.4, 1.5, 1.6] [default: 1.6]
|
|
156
157
|
--filter Filter components containing this word in purl or component.properties.value. Multiple va
|
|
157
158
|
lues allowed. [array]
|
|
158
159
|
--only Include components only containing this word in purl. Useful to generate BOM with first p
|
|
@@ -163,6 +164,8 @@ Options:
|
|
|
163
164
|
[choices: "appsec", "research", "operational", "threat-modeling", "license-compliance", "generic", "machine-learning",
|
|
164
165
|
"ml", "deep-learning", "ml-deep", "ml-tiny"] [default: "generic"]
|
|
165
166
|
--exclude Additional glob pattern(s) to ignore [array]
|
|
167
|
+
--export-proto Serialize and export BOM as protobuf binary. [boolean] [default: false]
|
|
168
|
+
--proto-bin-file Path for the serialized protobuf binary. [default: "bom.cdx"]
|
|
166
169
|
--include-formulation Generate formulation section with git metadata and build tools. Defaults to false.
|
|
167
170
|
[boolean] [default: false]
|
|
168
171
|
--include-crypto Include crypto libraries as components. [boolean] [default: false]
|
package/bin/cdxgen.js
CHANGED
|
@@ -4,11 +4,13 @@ import crypto from "node:crypto";
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
6
|
import process from "node:process";
|
|
7
|
+
|
|
7
8
|
import globalAgent from "global-agent";
|
|
8
9
|
import jws from "jws";
|
|
9
10
|
import { parse as _load } from "yaml";
|
|
10
11
|
import yargs from "yargs";
|
|
11
12
|
import { hideBin } from "yargs/helpers";
|
|
13
|
+
|
|
12
14
|
import { createBom, submitBom } from "../lib/cli/index.js";
|
|
13
15
|
import {
|
|
14
16
|
printCallStack,
|
|
@@ -21,15 +23,17 @@ import {
|
|
|
21
23
|
printSummary,
|
|
22
24
|
printTable,
|
|
23
25
|
} from "../lib/helpers/display.js";
|
|
24
|
-
import { thoughtEnd, thoughtLog } from "../lib/helpers/logger.js";
|
|
26
|
+
import { TRACE_MODE, thoughtEnd, thoughtLog } from "../lib/helpers/logger.js";
|
|
25
27
|
import {
|
|
26
28
|
ATOM_DB,
|
|
29
|
+
commandsExecuted,
|
|
27
30
|
DEBUG_MODE,
|
|
28
31
|
dirNameStr,
|
|
29
32
|
getTmpDir,
|
|
30
33
|
isMac,
|
|
31
34
|
isSecureMode,
|
|
32
35
|
isWin,
|
|
36
|
+
remoteHostsAccessed,
|
|
33
37
|
safeExistsSync,
|
|
34
38
|
} from "../lib/helpers/utils.js";
|
|
35
39
|
import { validateBom } from "../lib/helpers/validator.js";
|
|
@@ -57,7 +61,7 @@ for (const configPattern of configPaths) {
|
|
|
57
61
|
} else {
|
|
58
62
|
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
59
63
|
}
|
|
60
|
-
} catch (
|
|
64
|
+
} catch (_e) {
|
|
61
65
|
console.log("Invalid config file", configPath);
|
|
62
66
|
}
|
|
63
67
|
}
|
|
@@ -264,12 +268,10 @@ const args = yargs(hideBin(process.argv))
|
|
|
264
268
|
type: "boolean",
|
|
265
269
|
default: false,
|
|
266
270
|
description: "Serialize and export BOM as protobuf binary.",
|
|
267
|
-
hidden: true,
|
|
268
271
|
})
|
|
269
272
|
.option("proto-bin-file", {
|
|
270
273
|
description: "Path for the serialized protobuf binary.",
|
|
271
274
|
default: "bom.cdx",
|
|
272
|
-
hidden: true,
|
|
273
275
|
})
|
|
274
276
|
.option("include-formulation", {
|
|
275
277
|
type: "boolean",
|
|
@@ -832,7 +834,7 @@ const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
|
832
834
|
const jsonFile = options.output;
|
|
833
835
|
// Create bom json file
|
|
834
836
|
if (bomNSData.bomJson) {
|
|
835
|
-
let jsonPayload
|
|
837
|
+
let jsonPayload;
|
|
836
838
|
if (
|
|
837
839
|
typeof bomNSData.bomJson === "string" ||
|
|
838
840
|
bomNSData.bomJson instanceof String
|
|
@@ -859,9 +861,9 @@ const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
|
859
861
|
if (alg.includes("none")) {
|
|
860
862
|
alg = "RS512";
|
|
861
863
|
}
|
|
862
|
-
let privateKeyToUse
|
|
863
|
-
let jwkPublicKey
|
|
864
|
-
let publicKeyFile
|
|
864
|
+
let privateKeyToUse;
|
|
865
|
+
let jwkPublicKey;
|
|
866
|
+
let publicKeyFile;
|
|
865
867
|
if (options.generateKeyAndSign) {
|
|
866
868
|
const jdirName = dirname(jsonFile);
|
|
867
869
|
publicKeyFile = join(jdirName, "public.key");
|
|
@@ -1058,7 +1060,7 @@ const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
|
1058
1060
|
if (!validateBom(bomNSData.bomJson)) {
|
|
1059
1061
|
process.exit(1);
|
|
1060
1062
|
}
|
|
1061
|
-
thoughtLog("BOM file looks valid.
|
|
1063
|
+
thoughtLog("✅ BOM file looks valid.");
|
|
1062
1064
|
}
|
|
1063
1065
|
thoughtEnd();
|
|
1064
1066
|
// Automatically submit the bom data
|
|
@@ -1075,6 +1077,7 @@ const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
|
1075
1077
|
if (options.exportProto) {
|
|
1076
1078
|
const protobomModule = await import("../lib/helpers/protobom.js");
|
|
1077
1079
|
protobomModule.writeBinary(bomNSData.bomJson, options.protoBinFile);
|
|
1080
|
+
thoughtLog("BOM file is also available in .proto format!");
|
|
1078
1081
|
}
|
|
1079
1082
|
if (options.print && bomNSData.bomJson && bomNSData.bomJson.components) {
|
|
1080
1083
|
printSummary(bomNSData.bomJson);
|
|
@@ -1089,4 +1092,24 @@ const needsBomSigning = ({ generateKeyAndSign }) =>
|
|
|
1089
1092
|
printDependencyTree(bomNSData.bomJson, "provides");
|
|
1090
1093
|
}
|
|
1091
1094
|
}
|
|
1095
|
+
if (
|
|
1096
|
+
(DEBUG_MODE || TRACE_MODE) &&
|
|
1097
|
+
(!process.env?.CDXGEN_ALLOWED_HOSTS ||
|
|
1098
|
+
!process.env?.CDXGEN_ALLOWED_COMMANDS)
|
|
1099
|
+
) {
|
|
1100
|
+
let allowListSuggestion = "";
|
|
1101
|
+
const envPrefix = isWin ? "set $env:" : "export ";
|
|
1102
|
+
if (remoteHostsAccessed.size) {
|
|
1103
|
+
allowListSuggestion = `${envPrefix}CDXGEN_ALLOWED_HOSTS="${Array.from(remoteHostsAccessed).join(",")}"\n`;
|
|
1104
|
+
}
|
|
1105
|
+
if (commandsExecuted.size) {
|
|
1106
|
+
allowListSuggestion = `${allowListSuggestion}${envPrefix}CDXGEN_ALLOWED_COMMANDS="${Array.from(commandsExecuted).join(",")}"\n`;
|
|
1107
|
+
}
|
|
1108
|
+
if (allowListSuggestion) {
|
|
1109
|
+
console.log(
|
|
1110
|
+
"SECURE MODE: cdxgen supports allowlists for remote hosts and external commands. Set the following environment variables to get started.",
|
|
1111
|
+
);
|
|
1112
|
+
console.log(allowListSuggestion);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1092
1115
|
})();
|
package/bin/evinse.js
CHANGED
package/bin/repl.js
CHANGED
|
@@ -5,6 +5,7 @@ import { homedir } from "node:os";
|
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import process from "node:process";
|
|
7
7
|
import repl from "node:repl";
|
|
8
|
+
|
|
8
9
|
import jsonata from "jsonata";
|
|
9
10
|
|
|
10
11
|
import { createBom } from "../lib/cli/index.js";
|
|
@@ -12,13 +13,14 @@ import {
|
|
|
12
13
|
printCallStack,
|
|
13
14
|
printDependencyTree,
|
|
14
15
|
printFormulation,
|
|
15
|
-
printOSTable,
|
|
16
16
|
printOccurrences,
|
|
17
|
+
printOSTable,
|
|
17
18
|
printServices,
|
|
18
19
|
printSummary,
|
|
19
20
|
printTable,
|
|
20
21
|
printVulnerabilities,
|
|
21
22
|
} from "../lib/helpers/display.js";
|
|
23
|
+
import { readBinary } from "../lib/helpers/protobom.js";
|
|
22
24
|
import { getTmpDir } from "../lib/helpers/utils.js";
|
|
23
25
|
import { validateBom } from "../lib/helpers/validator.js";
|
|
24
26
|
|
|
@@ -50,15 +52,15 @@ if (process.env?.CDXGEN_NODE_OPTIONS) {
|
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
// The current sbom is stored here
|
|
53
|
-
let sbom
|
|
55
|
+
let sbom;
|
|
54
56
|
|
|
55
|
-
let historyFile
|
|
57
|
+
let historyFile;
|
|
56
58
|
const historyConfigDir = join(homedir(), ".config", ".cdxgen");
|
|
57
59
|
if (!process.env.CDXGEN_REPL_HISTORY && !fs.existsSync(historyConfigDir)) {
|
|
58
60
|
try {
|
|
59
61
|
fs.mkdirSync(historyConfigDir, { recursive: true });
|
|
60
62
|
historyFile = join(historyConfigDir, ".repl_history");
|
|
61
|
-
} catch (
|
|
63
|
+
} catch (_e) {
|
|
62
64
|
// ignore
|
|
63
65
|
}
|
|
64
66
|
} else {
|
|
@@ -78,6 +80,12 @@ export const importSbom = (sbomOrPath) => {
|
|
|
78
80
|
} catch (e) {
|
|
79
81
|
console.log(`⚠ Unable to import the BOM from ${sbomOrPath} due to ${e}`);
|
|
80
82
|
}
|
|
83
|
+
} else if (
|
|
84
|
+
(sbomOrPath?.endsWith(".cdx") || sbomOrPath?.endsWith(".proto")) &&
|
|
85
|
+
fs.existsSync(sbomOrPath)
|
|
86
|
+
) {
|
|
87
|
+
sbom = readBinary(sbomOrPath, true);
|
|
88
|
+
printSummary(sbom);
|
|
81
89
|
} else {
|
|
82
90
|
console.log(`⚠ ${sbomOrPath} is invalid.`);
|
|
83
91
|
}
|
package/bin/verify.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
|
+
|
|
6
7
|
import jws from "jws";
|
|
7
8
|
import yargs from "yargs";
|
|
8
9
|
import { hideBin } from "yargs/helpers";
|
|
10
|
+
|
|
9
11
|
import { dirNameStr } from "../lib/helpers/utils.js";
|
|
10
12
|
import { getBomWithOras } from "../lib/managers/oci.js";
|
|
11
13
|
|
package/lib/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
import {
|
|
3
|
-
constants,
|
|
4
3
|
accessSync,
|
|
4
|
+
constants,
|
|
5
5
|
existsSync,
|
|
6
6
|
lstatSync,
|
|
7
7
|
mkdtempSync,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { platform as _platform, arch, homedir } from "node:os";
|
|
15
15
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
16
16
|
import process from "node:process";
|
|
17
|
+
|
|
17
18
|
import got from "got";
|
|
18
19
|
import { PackageURL } from "packageurl-js";
|
|
19
20
|
import { gte, lte } from "semver";
|
|
@@ -21,6 +22,7 @@ import { parse } from "ssri";
|
|
|
21
22
|
import { table } from "table";
|
|
22
23
|
import { v4 as uuidv4 } from "uuid";
|
|
23
24
|
import { parse as loadYaml } from "yaml";
|
|
25
|
+
|
|
24
26
|
import { findJSImportsExports } from "../helpers/analyzer.js";
|
|
25
27
|
import { collectOSCryptoLibs } from "../helpers/cbomutils.js";
|
|
26
28
|
import {
|
|
@@ -32,21 +34,14 @@ import {
|
|
|
32
34
|
} from "../helpers/envcontext.js";
|
|
33
35
|
import { thoughtLog } from "../helpers/logger.js";
|
|
34
36
|
import {
|
|
35
|
-
CARGO_CMD,
|
|
36
|
-
CLJ_CMD,
|
|
37
|
-
DEBUG_MODE,
|
|
38
|
-
LEIN_CMD,
|
|
39
|
-
MAX_BUFFER,
|
|
40
|
-
PREFER_MAVEN_DEPS_TREE,
|
|
41
|
-
PROJECT_TYPE_ALIASES,
|
|
42
|
-
SWIFT_CMD,
|
|
43
|
-
TIMEOUT_MS,
|
|
44
37
|
addEvidenceForDotnet,
|
|
45
38
|
addEvidenceForImports,
|
|
46
39
|
addPlugin,
|
|
47
40
|
buildGradleCommandArguments,
|
|
48
41
|
buildObjectForCocoaPod,
|
|
49
42
|
buildObjectForGradleModule,
|
|
43
|
+
CARGO_CMD,
|
|
44
|
+
CLJ_CMD,
|
|
50
45
|
checksumFile,
|
|
51
46
|
cleanupPlugin,
|
|
52
47
|
collectGemModuleNames,
|
|
@@ -56,6 +51,7 @@ import {
|
|
|
56
51
|
convertJarNSToPackages,
|
|
57
52
|
convertOSQueryResults,
|
|
58
53
|
createUVLock,
|
|
54
|
+
DEBUG_MODE,
|
|
59
55
|
determineSbtVersion,
|
|
60
56
|
dirNameStr,
|
|
61
57
|
encodeForPurl,
|
|
@@ -87,6 +83,10 @@ import {
|
|
|
87
83
|
isPartialTree,
|
|
88
84
|
isSecureMode,
|
|
89
85
|
isValidIriReference,
|
|
86
|
+
LEIN_CMD,
|
|
87
|
+
MAX_BUFFER,
|
|
88
|
+
PREFER_MAVEN_DEPS_TREE,
|
|
89
|
+
PROJECT_TYPE_ALIASES,
|
|
90
90
|
parseBazelActionGraph,
|
|
91
91
|
parseBazelSkyframe,
|
|
92
92
|
parseBdistMetadata,
|
|
@@ -117,8 +117,8 @@ import {
|
|
|
117
117
|
parseGoListDep,
|
|
118
118
|
parseGoModData,
|
|
119
119
|
parseGoModGraph,
|
|
120
|
-
parseGoModWhy,
|
|
121
120
|
parseGoModulesTxt,
|
|
121
|
+
parseGoModWhy,
|
|
122
122
|
parseGopkgData,
|
|
123
123
|
parseGosumData,
|
|
124
124
|
parseGradleDep,
|
|
@@ -160,11 +160,13 @@ import {
|
|
|
160
160
|
parseYarnLock,
|
|
161
161
|
readZipEntry,
|
|
162
162
|
recomputeScope,
|
|
163
|
+
SWIFT_CMD,
|
|
163
164
|
safeExistsSync,
|
|
164
165
|
safeMkdirSync,
|
|
165
166
|
safeSpawnSync,
|
|
166
167
|
shouldFetchLicense,
|
|
167
168
|
splitOutputByGradleProjects,
|
|
169
|
+
TIMEOUT_MS,
|
|
168
170
|
} from "../helpers/utils.js";
|
|
169
171
|
import {
|
|
170
172
|
executeOsQuery,
|
|
@@ -283,7 +285,7 @@ const createDefaultParentComponent = (
|
|
|
283
285
|
};
|
|
284
286
|
|
|
285
287
|
const determineParentComponent = (options) => {
|
|
286
|
-
let parentComponent
|
|
288
|
+
let parentComponent;
|
|
287
289
|
if (options.parentComponent && Object.keys(options.parentComponent).length) {
|
|
288
290
|
return options.parentComponent;
|
|
289
291
|
}
|
|
@@ -551,7 +553,7 @@ const addFormulationSection = (options, context) => {
|
|
|
551
553
|
if (!environmentVars.length) {
|
|
552
554
|
environmentVars = undefined;
|
|
553
555
|
}
|
|
554
|
-
let sourceInput
|
|
556
|
+
let sourceInput;
|
|
555
557
|
if (environmentVars) {
|
|
556
558
|
sourceInput = { environmentVars };
|
|
557
559
|
}
|
|
@@ -889,7 +891,7 @@ function addMetadata(parentComponent = {}, options = {}, context = {}) {
|
|
|
889
891
|
name: `oci:image:bundles:${sdkName}Sdk`,
|
|
890
892
|
value: "true",
|
|
891
893
|
});
|
|
892
|
-
} catch (
|
|
894
|
+
} catch (_e) {
|
|
893
895
|
// ignore
|
|
894
896
|
}
|
|
895
897
|
}
|
|
@@ -1227,7 +1229,7 @@ function determinePackageType(pkg) {
|
|
|
1227
1229
|
return "framework";
|
|
1228
1230
|
}
|
|
1229
1231
|
}
|
|
1230
|
-
} catch (
|
|
1232
|
+
} catch (_e) {
|
|
1231
1233
|
// continue regardless of error
|
|
1232
1234
|
}
|
|
1233
1235
|
} else if (pkg.group) {
|
|
@@ -1235,19 +1237,19 @@ function determinePackageType(pkg) {
|
|
|
1235
1237
|
return "application";
|
|
1236
1238
|
}
|
|
1237
1239
|
}
|
|
1238
|
-
if (Object.
|
|
1240
|
+
if (Object.hasOwn(pkg, "description")) {
|
|
1239
1241
|
if (pkg.description?.toLowerCase().includes("framework")) {
|
|
1240
1242
|
return "framework";
|
|
1241
1243
|
}
|
|
1242
1244
|
}
|
|
1243
|
-
if (Object.
|
|
1245
|
+
if (Object.hasOwn(pkg, "keywords")) {
|
|
1244
1246
|
for (const keyword of pkg.keywords) {
|
|
1245
1247
|
if (keyword && keyword.toLowerCase() === "framework") {
|
|
1246
1248
|
return "framework";
|
|
1247
1249
|
}
|
|
1248
1250
|
}
|
|
1249
1251
|
}
|
|
1250
|
-
if (Object.
|
|
1252
|
+
if (Object.hasOwn(pkg, "tags")) {
|
|
1251
1253
|
for (const tag of pkg.tags) {
|
|
1252
1254
|
if (tag && tag.toLowerCase() === "framework") {
|
|
1253
1255
|
return "framework";
|
|
@@ -1275,16 +1277,16 @@ function processHashes(pkg, component) {
|
|
|
1275
1277
|
const integrity = parse(pkg._integrity) || {};
|
|
1276
1278
|
// Components may have multiple hashes with various lengths. Check each one
|
|
1277
1279
|
// that is supported by the CycloneDX specification.
|
|
1278
|
-
if (Object.
|
|
1280
|
+
if (Object.hasOwn(integrity, "sha512")) {
|
|
1279
1281
|
addComponentHash("SHA-512", integrity.sha512[0].digest, component);
|
|
1280
1282
|
}
|
|
1281
|
-
if (Object.
|
|
1283
|
+
if (Object.hasOwn(integrity, "sha384")) {
|
|
1282
1284
|
addComponentHash("SHA-384", integrity.sha384[0].digest, component);
|
|
1283
1285
|
}
|
|
1284
|
-
if (Object.
|
|
1286
|
+
if (Object.hasOwn(integrity, "sha256")) {
|
|
1285
1287
|
addComponentHash("SHA-256", integrity.sha256[0].digest, component);
|
|
1286
1288
|
}
|
|
1287
|
-
if (Object.
|
|
1289
|
+
if (Object.hasOwn(integrity, "sha1")) {
|
|
1288
1290
|
addComponentHash("SHA-1", integrity.sha1[0].digest, component);
|
|
1289
1291
|
}
|
|
1290
1292
|
}
|
|
@@ -1494,7 +1496,7 @@ export async function createJavaBom(path, options) {
|
|
|
1494
1496
|
let parentComponent = {};
|
|
1495
1497
|
// Support for tracking all the tools that created the BOM
|
|
1496
1498
|
// For java, this would correctly include the cyclonedx maven plugin.
|
|
1497
|
-
let tools
|
|
1499
|
+
let tools;
|
|
1498
1500
|
let possible_misses = false;
|
|
1499
1501
|
// war/ear mode
|
|
1500
1502
|
if (path.endsWith(".war") || path.endsWith(".jar")) {
|
|
@@ -1577,7 +1579,7 @@ export async function createJavaBom(path, options) {
|
|
|
1577
1579
|
}
|
|
1578
1580
|
}
|
|
1579
1581
|
}
|
|
1580
|
-
let result
|
|
1582
|
+
let result;
|
|
1581
1583
|
let mvnArgs;
|
|
1582
1584
|
if (isQuarkus) {
|
|
1583
1585
|
thoughtLog(
|
|
@@ -1660,10 +1662,7 @@ export async function createJavaBom(path, options) {
|
|
|
1660
1662
|
// Use the cyclonedx maven plugin if there is no preference for maven deps tree
|
|
1661
1663
|
if (!useMavenDepsTree) {
|
|
1662
1664
|
thoughtLog("The user wants me to use the cyclonedx-maven plugin.");
|
|
1663
|
-
console.log(
|
|
1664
|
-
`Executing '${mavenCmd} ${mvnArgs.join(" ")}' in`,
|
|
1665
|
-
basePath,
|
|
1666
|
-
);
|
|
1665
|
+
console.log(`Executing '${mavenCmd}' in`, basePath);
|
|
1667
1666
|
result = safeSpawnSync(mavenCmd, mvnArgs, {
|
|
1668
1667
|
cwd: basePath,
|
|
1669
1668
|
shell: true,
|
|
@@ -1698,8 +1697,9 @@ export async function createJavaBom(path, options) {
|
|
|
1698
1697
|
const tempMvnTree = join(tempDir, "mvn-tree.txt");
|
|
1699
1698
|
const tempMvnParentTree = join(tempDir, "mvn-parent-tree.txt");
|
|
1700
1699
|
let mvnTreeArgs = ["dependency:tree", `-DoutputFile=${tempMvnTree}`];
|
|
1700
|
+
let addArgs = "";
|
|
1701
1701
|
if (process.env.MVN_ARGS) {
|
|
1702
|
-
|
|
1702
|
+
addArgs = process.env.MVN_ARGS.split(" ");
|
|
1703
1703
|
mvnTreeArgs = mvnTreeArgs.concat(addArgs);
|
|
1704
1704
|
}
|
|
1705
1705
|
// Automatically use settings.xml to improve the success for fallback
|
|
@@ -1713,17 +1713,21 @@ export async function createJavaBom(path, options) {
|
|
|
1713
1713
|
thoughtLog(
|
|
1714
1714
|
"What is the parent component here? Let's use maven command to find out.",
|
|
1715
1715
|
);
|
|
1716
|
-
|
|
1717
|
-
"
|
|
1718
|
-
|
|
1719
|
-
{
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1716
|
+
let findParentComponentArgs = [
|
|
1717
|
+
"dependency:tree",
|
|
1718
|
+
"-N",
|
|
1719
|
+
`-DoutputFile=${tempMvnParentTree}`,
|
|
1720
|
+
];
|
|
1721
|
+
if (addArgs) {
|
|
1722
|
+
findParentComponentArgs = findParentComponentArgs.concat(addArgs);
|
|
1723
|
+
}
|
|
1724
|
+
result = safeSpawnSync("mvn", findParentComponentArgs, {
|
|
1725
|
+
cwd: basePath,
|
|
1726
|
+
shell: true,
|
|
1727
|
+
encoding: "utf-8",
|
|
1728
|
+
timeout: TIMEOUT_MS,
|
|
1729
|
+
maxBuffer: MAX_BUFFER,
|
|
1730
|
+
});
|
|
1727
1731
|
if (result.status === 0) {
|
|
1728
1732
|
if (safeExistsSync(tempMvnParentTree)) {
|
|
1729
1733
|
const mvnTreeString = readFileSync(tempMvnParentTree, {
|
|
@@ -1768,8 +1772,13 @@ export async function createJavaBom(path, options) {
|
|
|
1768
1772
|
// Our approach to recursively invoking the maven plugin for each sub-module is bound to result in failures
|
|
1769
1773
|
// These could be due to a range of reasons that are covered below.
|
|
1770
1774
|
if (pomFiles.length === 1 || DEBUG_MODE || PREFER_MAVEN_DEPS_TREE) {
|
|
1771
|
-
|
|
1772
|
-
|
|
1775
|
+
if (result.stdout) {
|
|
1776
|
+
console.log(result.stdout);
|
|
1777
|
+
}
|
|
1778
|
+
if (result.stderr) {
|
|
1779
|
+
console.log(result.stderr);
|
|
1780
|
+
console.log("The above build errors could be due to:\n");
|
|
1781
|
+
}
|
|
1773
1782
|
if (
|
|
1774
1783
|
result.stdout &&
|
|
1775
1784
|
(result.stdout.includes("Non-resolvable parent POM") ||
|
|
@@ -1868,7 +1877,7 @@ export async function createJavaBom(path, options) {
|
|
|
1868
1877
|
// Locate and parse all bom.json files from the maven plugin
|
|
1869
1878
|
if (!useMavenDepsTree) {
|
|
1870
1879
|
for (const abjson of bomJsonFiles) {
|
|
1871
|
-
let bomJsonObj
|
|
1880
|
+
let bomJsonObj;
|
|
1872
1881
|
try {
|
|
1873
1882
|
if (DEBUG_MODE) {
|
|
1874
1883
|
console.log(`Extracting data from generated bom file ${abjson}`);
|
|
@@ -2003,7 +2012,7 @@ export async function createJavaBom(path, options) {
|
|
|
2003
2012
|
);
|
|
2004
2013
|
if (process.env.GRADLE_INCLUDED_BUILDS === undefined) {
|
|
2005
2014
|
const outputLines = parallelPropTaskOut.split("\n");
|
|
2006
|
-
for (const [
|
|
2015
|
+
for (const [_i, line] of outputLines.entries()) {
|
|
2007
2016
|
if (line.startsWith("Root project '") || line.startsWith("Project '")) {
|
|
2008
2017
|
break;
|
|
2009
2018
|
}
|
|
@@ -3144,6 +3153,10 @@ export async function createNodejsBom(path, options) {
|
|
|
3144
3153
|
const basePath = dirname(f);
|
|
3145
3154
|
// Determine the parent component
|
|
3146
3155
|
const packageJsonF = join(basePath, "package.json");
|
|
3156
|
+
const pnpmHooks = join(basePath, ".pnpmfile.cjs");
|
|
3157
|
+
if (safeExistsSync(pnpmHooks)) {
|
|
3158
|
+
thoughtLog("Wait, this pnpm project uses install hooks.");
|
|
3159
|
+
}
|
|
3147
3160
|
if (!Object.keys(parentComponent).length) {
|
|
3148
3161
|
if (safeExistsSync(packageJsonF)) {
|
|
3149
3162
|
const pcs = await parsePkgJson(packageJsonF, true);
|
|
@@ -3832,7 +3845,7 @@ export async function createPythonBom(path, options) {
|
|
|
3832
3845
|
}
|
|
3833
3846
|
for (const f of reqFiles) {
|
|
3834
3847
|
const basePath = dirname(f);
|
|
3835
|
-
let reqData
|
|
3848
|
+
let reqData;
|
|
3836
3849
|
let frozen = false;
|
|
3837
3850
|
// Attempt to pip freeze in a virtualenv to improve precision
|
|
3838
3851
|
if (options.installDeps) {
|
|
@@ -3896,7 +3909,7 @@ export async function createPythonBom(path, options) {
|
|
|
3896
3909
|
* The order of preference is pyproject.toml (newer) and then setup.py
|
|
3897
3910
|
*/
|
|
3898
3911
|
if (options.installDeps) {
|
|
3899
|
-
let pkgMap
|
|
3912
|
+
let pkgMap;
|
|
3900
3913
|
if (pyProjectMode && !poetryMode) {
|
|
3901
3914
|
pkgMap = getPipFrozenTree(
|
|
3902
3915
|
path,
|
|
@@ -4093,7 +4106,7 @@ export async function createGoBom(path, options) {
|
|
|
4093
4106
|
let maybeBinary;
|
|
4094
4107
|
try {
|
|
4095
4108
|
maybeBinary = statSync(path).isFile();
|
|
4096
|
-
} catch (
|
|
4109
|
+
} catch (_err) {
|
|
4097
4110
|
maybeBinary = false;
|
|
4098
4111
|
}
|
|
4099
4112
|
if (maybeBinary || options?.lifecycle?.includes("post-build")) {
|
|
@@ -4501,7 +4514,7 @@ export async function createRustBom(path, options) {
|
|
|
4501
4514
|
let maybeBinary;
|
|
4502
4515
|
try {
|
|
4503
4516
|
maybeBinary = statSync(path).isFile();
|
|
4504
|
-
} catch (
|
|
4517
|
+
} catch (_err) {
|
|
4505
4518
|
maybeBinary = false;
|
|
4506
4519
|
}
|
|
4507
4520
|
if (maybeBinary || options?.lifecycle?.includes("post-build")) {
|
|
@@ -4706,7 +4719,7 @@ export async function createDartBom(path, options) {
|
|
|
4706
4719
|
* @param {Object} options Parse options from the cli
|
|
4707
4720
|
*/
|
|
4708
4721
|
export function createCppBom(path, options) {
|
|
4709
|
-
let parentComponent
|
|
4722
|
+
let parentComponent;
|
|
4710
4723
|
let dependencies = [];
|
|
4711
4724
|
const addedParentComponentsMap = {};
|
|
4712
4725
|
const conanLockFiles = getAllFiles(
|
|
@@ -5313,7 +5326,7 @@ export async function createSwiftBom(path, options) {
|
|
|
5313
5326
|
if (completedPath.includes(basePath)) {
|
|
5314
5327
|
continue;
|
|
5315
5328
|
}
|
|
5316
|
-
let treeData
|
|
5329
|
+
let treeData;
|
|
5317
5330
|
let packageArgs = ["package"];
|
|
5318
5331
|
// Additional arguments to pass to the swift package command.
|
|
5319
5332
|
// Example: --swift-sdks-path <swift-sdks-path> --jobs <jobs>
|
|
@@ -5939,11 +5952,11 @@ export function createPHPBom(path, options) {
|
|
|
5939
5952
|
}
|
|
5940
5953
|
options.failOnError && process.exit(1);
|
|
5941
5954
|
}
|
|
5942
|
-
let composerVersion
|
|
5955
|
+
let composerVersion;
|
|
5943
5956
|
if (DEBUG_MODE) {
|
|
5944
5957
|
console.log("Parsing version", versionResult.stdout);
|
|
5945
5958
|
}
|
|
5946
|
-
let tmpV
|
|
5959
|
+
let tmpV;
|
|
5947
5960
|
if (versionResult?.stdout) {
|
|
5948
5961
|
tmpV = versionResult.stdout.split(" ");
|
|
5949
5962
|
}
|
|
@@ -6274,7 +6287,7 @@ export async function createRubyBom(path, options) {
|
|
|
6274
6287
|
*/
|
|
6275
6288
|
export async function createCsharpBom(path, options) {
|
|
6276
6289
|
let manifestFiles = [];
|
|
6277
|
-
let pkgData
|
|
6290
|
+
let pkgData;
|
|
6278
6291
|
let dependencies = [];
|
|
6279
6292
|
if (options?.lifecycle?.includes("post-build")) {
|
|
6280
6293
|
return createBinaryBom(path, options);
|
|
@@ -6957,7 +6970,7 @@ export function dedupeBom(options, components, parentComponent, dependencies) {
|
|
|
6957
6970
|
export async function createMultiXBom(pathList, options) {
|
|
6958
6971
|
let components = [];
|
|
6959
6972
|
let dependencies = [];
|
|
6960
|
-
let bomData
|
|
6973
|
+
let bomData;
|
|
6961
6974
|
let parentComponent = determineParentComponent(options) || {};
|
|
6962
6975
|
let parentSubComponents = [];
|
|
6963
6976
|
options.createMultiXBom = true;
|
|
@@ -7727,7 +7740,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7727
7740
|
export async function createXBom(path, options) {
|
|
7728
7741
|
try {
|
|
7729
7742
|
accessSync(path, constants.R_OK);
|
|
7730
|
-
} catch (
|
|
7743
|
+
} catch (_err) {
|
|
7731
7744
|
return undefined;
|
|
7732
7745
|
}
|
|
7733
7746
|
if (
|
|
@@ -8059,7 +8072,7 @@ export async function createBom(path, options) {
|
|
|
8059
8072
|
if (!projectType) {
|
|
8060
8073
|
projectType = [];
|
|
8061
8074
|
}
|
|
8062
|
-
let exportData
|
|
8075
|
+
let exportData;
|
|
8063
8076
|
let isContainerMode = false;
|
|
8064
8077
|
// Docker and image archive support
|
|
8065
8078
|
// TODO: Support any source archive
|
|
@@ -8385,13 +8398,14 @@ export async function submitBom(args, bomContents) {
|
|
|
8385
8398
|
"with --skip-dt-tls-check argument: Skip DT TLS check.",
|
|
8386
8399
|
);
|
|
8387
8400
|
}
|
|
8401
|
+
// See issue #1963 regarding CRLF hardening
|
|
8388
8402
|
return await got(serverUrl, {
|
|
8389
8403
|
method: "PUT",
|
|
8390
8404
|
https: {
|
|
8391
8405
|
rejectUnauthorized: !args.skipDtTlsCheck,
|
|
8392
8406
|
},
|
|
8393
8407
|
headers: {
|
|
8394
|
-
"X-Api-Key": args.apiKey,
|
|
8408
|
+
"X-Api-Key": (args.apiKey || "").replace(/[\r\n]/g, ""),
|
|
8395
8409
|
"Content-Type": "application/json",
|
|
8396
8410
|
"user-agent": `@CycloneDX/cdxgen ${_version}`,
|
|
8397
8411
|
},
|