@cyclonedx/cdxgen 9.11.6 → 10.0.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.
@@ -5,7 +5,7 @@
5
5
  "purlType": "deb"
6
6
  },
7
7
  "portage_packages": {
8
- "query": "select * from portage_packages where name like '%dev%' OR name like '%header%';",
8
+ "query": "select * from portage_packages where package like '%dev%' OR package like '%header%';",
9
9
  "description": "Retrieves all the installed packages on the target Linux system.",
10
10
  "purlType": "ebuild"
11
11
  },
package/display.js CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync } from "fs";
1
+ import { existsSync, readFileSync } from "node:fs";
2
2
  import { createStream, table } from "table";
3
3
 
4
4
  // https://github.com/yangshun/tree-node-cli/blob/master/src/index.js
@@ -166,7 +166,7 @@ export const printCallStack = (bomJson) => {
166
166
  )
167
167
  )
168
168
  ).sort(locationComparator);
169
- let frameDisplay = [frames[0]];
169
+ const frameDisplay = [frames[0]];
170
170
  if (frames.length > 1) {
171
171
  for (let i = 1; i < frames.length - 1; i++) {
172
172
  frameDisplay.push(`${SYMBOLS_ANSI.BRANCH} ${frames[i]}`);
package/docker.js CHANGED
@@ -2,6 +2,8 @@ import got from "got";
2
2
  import { globSync } from "glob";
3
3
  import { parse } from "node:url";
4
4
  import stream from "node:stream/promises";
5
+ import process from "node:process";
6
+ import { Buffer } from "node:buffer";
5
7
  import {
6
8
  existsSync,
7
9
  readdirSync,
@@ -498,7 +500,7 @@ export const getImage = async (fullImageName) => {
498
500
  let localData = undefined;
499
501
  let pullData = undefined;
500
502
  const { registry, repo, tag, digest } = parseImageName(fullImageName);
501
- let repoWithTag =
503
+ const repoWithTag =
502
504
  registry && registry !== "docker.io"
503
505
  ? fullImageName
504
506
  : `${repo}:${tag !== "" ? tag : ":latest"}`;
@@ -718,7 +720,7 @@ export const extractTar = async (fullImageName, dir) => {
718
720
  "Please run cdxgen from a powershell terminal with admin privileges to create symlinks."
719
721
  );
720
722
  console.log(err);
721
- } else if (err.code !== "TAR_BAD_ARCHIVE") {
723
+ } else if (!["TAR_BAD_ARCHIVE", "TAR_ENTRY_INFO"].includes(err.code)) {
722
724
  console.log(
723
725
  `Error while extracting image ${fullImageName} to ${dir}. Please file this bug to the cdxgen repo. https://github.com/CycloneDX/cdxgen/issues`
724
726
  );
package/envcontext.js ADDED
@@ -0,0 +1,302 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import {
3
+ isWin,
4
+ PYTHON_CMD,
5
+ JAVA_CMD,
6
+ DOTNET_CMD,
7
+ NODE_CMD,
8
+ NPM_CMD,
9
+ GCC_CMD,
10
+ GO_CMD,
11
+ RUSTC_CMD,
12
+ CARGO_CMD
13
+ } from "./utils.js";
14
+ import process from "node:process";
15
+ import { Buffer } from "node:buffer";
16
+
17
+ const GIT_COMMAND = process.env.GIT_CMD || "git";
18
+
19
+ /**
20
+ * Retrieves a git config item
21
+ * @param {string} configKey Git config key
22
+ * @param {string} dir repo directory
23
+ *
24
+ * @returns Output from git config or undefined
25
+ */
26
+ export const getGitConfig = (configKey, dir) => {
27
+ return execGitCommand(dir, ["config", "--get", configKey]);
28
+ };
29
+
30
+ /**
31
+ * Retrieves the git origin url
32
+ * @param {string} dir repo directory
33
+ *
34
+ * @returns Output from git config or undefined
35
+ */
36
+ export const getOriginUrl = (dir) => {
37
+ return getGitConfig("remote.origin.url", dir);
38
+ };
39
+
40
+ /**
41
+ * Retrieves the git branch name
42
+ * @param {string} configKey Git config key
43
+ * @param {string} dir repo directory
44
+ *
45
+ * @returns Output from git config or undefined
46
+ */
47
+ export const getBranch = (configKey, dir) => {
48
+ return execGitCommand(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
49
+ };
50
+
51
+ /**
52
+ * Retrieves the files list from git
53
+ * @param {string} dir repo directory
54
+ *
55
+ * @returns Output from git config or undefined
56
+ */
57
+ export const listFiles = (dir) => {
58
+ const filesList = [];
59
+ const output = execGitCommand(dir, [
60
+ "ls-tree",
61
+ "-l",
62
+ "-r",
63
+ "--full-tree",
64
+ "HEAD"
65
+ ]);
66
+ if (output) {
67
+ output.split("\n").forEach((l) => {
68
+ l = l.replace("\r", "");
69
+ if (l === "\n" || l.startsWith("#")) {
70
+ return;
71
+ }
72
+ const tmpA = l.split(" ");
73
+ if (tmpA && tmpA.length >= 5) {
74
+ const lastParts = tmpA[tmpA.length - 1].split("\t");
75
+ filesList.push({
76
+ hash: tmpA[2],
77
+ name: lastParts[lastParts.length - 1]
78
+ });
79
+ }
80
+ });
81
+ }
82
+ return filesList;
83
+ };
84
+
85
+ /**
86
+ * Execute a git command
87
+ *
88
+ * @param {string} dir Repo directory
89
+ * @param {Array} args arguments to git command
90
+ *
91
+ * @returns Output from the git command
92
+ */
93
+ export const execGitCommand = (dir, args) => {
94
+ return getCommandOutput(GIT_COMMAND, dir, args);
95
+ };
96
+
97
+ /**
98
+ * Collect Java version and installed modules
99
+ *
100
+ * @param {string} dir Working directory
101
+ * @returns Object containing the java details
102
+ */
103
+ export const collectJavaInfo = (dir) => {
104
+ const versionDesc = getCommandOutput(JAVA_CMD, dir, ["--version"]);
105
+ const moduleDesc = getCommandOutput(JAVA_CMD, dir, ["--list-modules"]) || "";
106
+ if (versionDesc) {
107
+ return {
108
+ type: "platform",
109
+ name: "java",
110
+ version: versionDesc.split("\n")[0].replace("java ", ""),
111
+ description: versionDesc,
112
+ properties: [
113
+ {
114
+ name: "java:modules",
115
+ value: moduleDesc.replaceAll("\n", ", ")
116
+ }
117
+ ]
118
+ };
119
+ }
120
+ return undefined;
121
+ };
122
+
123
+ /**
124
+ * Collect dotnet version
125
+ *
126
+ * @param {string} dir Working directory
127
+ * @returns Object containing dotnet details
128
+ */
129
+ export const collectDotnetInfo = (dir) => {
130
+ const versionDesc = getCommandOutput(DOTNET_CMD, dir, ["--version"]);
131
+ const moduleDesc =
132
+ getCommandOutput(DOTNET_CMD, dir, ["--list-runtimes"]) || "";
133
+ if (versionDesc) {
134
+ return {
135
+ type: "platform",
136
+ name: "dotnet",
137
+ version: versionDesc.trim(),
138
+ description: moduleDesc.replaceAll("\n", "\\n")
139
+ };
140
+ }
141
+ return undefined;
142
+ };
143
+
144
+ /**
145
+ * Collect python version
146
+ *
147
+ * @param {string} dir Working directory
148
+ * @returns Object containing python details
149
+ */
150
+ export const collectPythonInfo = (dir) => {
151
+ const versionDesc = getCommandOutput(PYTHON_CMD, dir, ["--version"]);
152
+ const moduleDesc =
153
+ getCommandOutput(PYTHON_CMD, dir, ["-m", "pip", "--version"]) || "";
154
+ if (versionDesc) {
155
+ return {
156
+ type: "platform",
157
+ name: "python",
158
+ version: versionDesc.replace("Python ", ""),
159
+ description: moduleDesc.replaceAll("\n", "\\n")
160
+ };
161
+ }
162
+ return undefined;
163
+ };
164
+
165
+ /**
166
+ * Collect node version
167
+ *
168
+ * @param {string} dir Working directory
169
+ * @returns Object containing node details
170
+ */
171
+ export const collectNodeInfo = (dir) => {
172
+ const versionDesc = getCommandOutput(NODE_CMD, dir, ["--version"]);
173
+ let moduleDesc = getCommandOutput(NPM_CMD, dir, ["--version"]);
174
+ if (moduleDesc) {
175
+ moduleDesc = `npm: ${moduleDesc}`;
176
+ }
177
+ if (versionDesc) {
178
+ return {
179
+ type: "platform",
180
+ name: "node",
181
+ version: versionDesc.trim(),
182
+ description: moduleDesc
183
+ };
184
+ }
185
+ return undefined;
186
+ };
187
+
188
+ /**
189
+ * Collect gcc version
190
+ *
191
+ * @param {string} dir Working directory
192
+ * @returns Object containing gcc details
193
+ */
194
+ export const collectGccInfo = (dir) => {
195
+ const versionDesc = getCommandOutput(GCC_CMD, dir, ["--version"]);
196
+ const moduleDesc = getCommandOutput(GCC_CMD, dir, ["-print-search-dirs"]);
197
+ if (versionDesc) {
198
+ return {
199
+ type: "platform",
200
+ name: "gcc",
201
+ version: versionDesc.split("\n")[0],
202
+ description: moduleDesc.replaceAll("\n", "\\n")
203
+ };
204
+ }
205
+ return undefined;
206
+ };
207
+
208
+ /**
209
+ * Collect rust version
210
+ *
211
+ * @param {string} dir Working directory
212
+ * @returns Object containing rust details
213
+ */
214
+ export const collectRustInfo = (dir) => {
215
+ const versionDesc = getCommandOutput(RUSTC_CMD, dir, ["--version"]);
216
+ const moduleDesc = getCommandOutput(CARGO_CMD, dir, ["--version"]);
217
+ if (versionDesc) {
218
+ return {
219
+ type: "platform",
220
+ name: "rustc",
221
+ version: versionDesc.trim(),
222
+ description: moduleDesc.trim()
223
+ };
224
+ }
225
+ return undefined;
226
+ };
227
+
228
+ /**
229
+ * Collect go version
230
+ *
231
+ * @param {string} dir Working directory
232
+ * @returns Object containing go details
233
+ */
234
+ export const collectGoInfo = (dir) => {
235
+ const versionDesc = getCommandOutput(GO_CMD, dir, ["version"]);
236
+ if (versionDesc) {
237
+ return {
238
+ type: "platform",
239
+ name: "go",
240
+ version: versionDesc.trim()
241
+ };
242
+ }
243
+ return undefined;
244
+ };
245
+
246
+ export const collectEnvInfo = (dir) => {
247
+ const infoComponents = [];
248
+ let cmp = collectJavaInfo(dir);
249
+ if (cmp) {
250
+ infoComponents.push(cmp);
251
+ }
252
+ cmp = collectDotnetInfo(dir);
253
+ if (cmp) {
254
+ infoComponents.push(cmp);
255
+ }
256
+ cmp = collectPythonInfo(dir);
257
+ if (cmp) {
258
+ infoComponents.push(cmp);
259
+ }
260
+ cmp = collectNodeInfo(dir);
261
+ if (cmp) {
262
+ infoComponents.push(cmp);
263
+ }
264
+ cmp = collectGccInfo(dir);
265
+ if (cmp) {
266
+ infoComponents.push(cmp);
267
+ }
268
+ cmp = collectRustInfo(dir);
269
+ if (cmp) {
270
+ infoComponents.push(cmp);
271
+ }
272
+ cmp = collectGoInfo(dir);
273
+ if (cmp) {
274
+ infoComponents.push(cmp);
275
+ }
276
+ return infoComponents;
277
+ };
278
+
279
+ /**
280
+ * Execute any command to retrieve the output
281
+ *
282
+ * @param {*} cmd Command to execute
283
+ * @param {*} dir working directory
284
+ * @param {*} args arguments
285
+ * @returns String output from the command or undefined in case of error
286
+ */
287
+ const getCommandOutput = (cmd, dir, args) => {
288
+ const result = spawnSync(cmd, args, {
289
+ cwd: dir,
290
+ encoding: "utf-8",
291
+ shell: isWin
292
+ });
293
+ if (result.status !== 0 || result.error) {
294
+ return undefined;
295
+ } else {
296
+ const stdout = result.stdout;
297
+ if (stdout) {
298
+ const cmdOutput = Buffer.from(stdout).toString();
299
+ return cmdOutput.trim();
300
+ }
301
+ }
302
+ };
@@ -0,0 +1,31 @@
1
+ import { expect, test } from "@jest/globals";
2
+
3
+ import {
4
+ getBranch,
5
+ getOriginUrl,
6
+ listFiles,
7
+ collectJavaInfo,
8
+ collectDotnetInfo,
9
+ collectPythonInfo,
10
+ collectNodeInfo,
11
+ collectGccInfo,
12
+ collectRustInfo,
13
+ collectGoInfo
14
+ } from "./envcontext.js";
15
+
16
+ test("git tests", () => {
17
+ expect(getBranch()).toBeDefined();
18
+ expect(getOriginUrl()).toBeDefined();
19
+ const files = listFiles();
20
+ expect(files.length).toBeGreaterThan(10);
21
+ });
22
+
23
+ test("tools tests", () => {
24
+ expect(collectJavaInfo()).toBeDefined();
25
+ expect(collectDotnetInfo()).toBeDefined();
26
+ expect(collectPythonInfo()).toBeDefined();
27
+ expect(collectNodeInfo()).toBeDefined();
28
+ expect(collectGccInfo()).toBeDefined();
29
+ expect(collectRustInfo()).toBeDefined();
30
+ expect(collectGoInfo()).toBeDefined();
31
+ });
package/evinser.js CHANGED
@@ -4,7 +4,8 @@ import {
4
4
  getGradleCommand,
5
5
  getMavenCommand,
6
6
  collectGradleDependencies,
7
- collectMvnDependencies
7
+ collectMvnDependencies,
8
+ DEBUG_MODE
8
9
  } from "./utils.js";
9
10
  import { tmpdir } from "node:os";
10
11
  import path from "node:path";
@@ -98,7 +99,7 @@ export const catalogMavenDeps = async (
98
99
  if (fs.existsSync(path.join(dirPath, "bom.json.map"))) {
99
100
  try {
100
101
  const mapData = JSON.parse(
101
- fs.readFileSync(path.join(dirPath, "bom.json.map"))
102
+ fs.readFileSync(path.join(dirPath, "bom.json.map"), "utf-8")
102
103
  );
103
104
  if (mapData && Object.keys(mapData).length) {
104
105
  jarNSMapping = mapData;
@@ -111,7 +112,7 @@ export const catalogMavenDeps = async (
111
112
  console.log("About to collect jar dependencies for the path", dirPath);
112
113
  const mavenCmd = getMavenCommand(dirPath, dirPath);
113
114
  // collect all jars including from the cache if data-flow mode is enabled
114
- jarNSMapping = collectMvnDependencies(
115
+ jarNSMapping = await collectMvnDependencies(
115
116
  mavenCmd,
116
117
  dirPath,
117
118
  false,
@@ -145,7 +146,7 @@ export const catalogGradleDeps = async (dirPath, purlsJars, Namespaces) => {
145
146
  );
146
147
  const gradleCmd = getGradleCommand(dirPath, dirPath);
147
148
  // collect all jars including from the cache if data-flow mode is enabled
148
- const jarNSMapping = collectGradleDependencies(
149
+ const jarNSMapping = await collectGradleDependencies(
149
150
  gradleCmd,
150
151
  dirPath,
151
152
  false,
@@ -1110,7 +1111,7 @@ export const collectDataFlowFrames = async (
1110
1111
  }
1111
1112
  const paths = dataFlowSlice?.paths || [];
1112
1113
  for (const apath of paths) {
1113
- let aframe = [];
1114
+ const aframe = [];
1114
1115
  let referredPurls = new Set();
1115
1116
  for (const nid of apath) {
1116
1117
  const theNode = nodeCache[nid];
@@ -1163,7 +1164,7 @@ export const collectDataFlowFrames = async (
1163
1164
  referredPurls.add(ns.purl);
1164
1165
  }
1165
1166
  typePurlsCache[typeFullName] = nsHits;
1166
- } else {
1167
+ } else if (DEBUG_MODE) {
1167
1168
  console.log("Unable to identify purl for", typeFullName);
1168
1169
  }
1169
1170
  }
@@ -1213,14 +1214,14 @@ export const collectDataFlowFrames = async (
1213
1214
  * @param {string} language Application language
1214
1215
  * @param {object} reachablesSlice Reachables slice object from atom
1215
1216
  */
1216
- export const collectReachableFrames = async (language, reachablesSlice) => {
1217
+ export const collectReachableFrames = (language, reachablesSlice) => {
1217
1218
  const reachableNodes = reachablesSlice?.reachables || [];
1218
1219
  // purl key and an array of frames array
1219
1220
  // CycloneDX 1.5 currently accepts only 1 frame as evidence
1220
1221
  // so this method is more future-proof
1221
1222
  const dfFrames = {};
1222
1223
  for (const anode of reachableNodes) {
1223
- let aframe = [];
1224
+ const aframe = [];
1224
1225
  let referredPurls = new Set(anode.purls || []);
1225
1226
  for (const fnode of anode.flows) {
1226
1227
  if (!fnode.parentFileName || fnode.parentFileName === "<unknown>") {