@cyclonedx/cdxgen 9.6.1 → 9.7.1

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 CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  cdxgen is a cli tool, library, [REPL](./ADVANCED.md) and server to create a valid and compliant [CycloneDX][cyclonedx-homepage] Software Bill-of-Materials (SBOM) containing an aggregate of all project dependencies for c/c++, node.js, php, python, ruby, rust, java, .Net, dart, haskell, elixir, and Go projects in JSON format. CycloneDX 1.5 is a lightweight SBOM specification that is easily created, human and machine-readable, and simple to parse.
6
6
 
7
- When used with plugins, cdxgen could generate an SBoM for Linux docker images and even VMs running Linux or Windows operating system. cdxgen also includes a tool called `evinse` that can generate component evidences for some languages.
7
+ When used with plugins, cdxgen could generate an OBoM for Linux docker images and even VMs running Linux or Windows operating system. cdxgen also includes a tool called `evinse` that can generate component evidences and SaaSBoM for some languages.
8
8
 
9
9
  NOTE:
10
10
 
@@ -90,6 +90,12 @@ sudo npm install -g @cyclonedx/cdxgen
90
90
  sudo npm install -g @cyclonedx/cdxgen@8.6.0
91
91
  ```
92
92
 
93
+ If you are a [Homebrew](https://brew.sh/) user, you can also install [cdxgen](https://formulae.brew.sh/formula/cdxgen) via:
94
+
95
+ ```shell
96
+ $ brew install cdxgen
97
+ ```
98
+
93
99
  Deno install is also supported.
94
100
 
95
101
  ```shell
@@ -127,9 +133,7 @@ Options:
127
133
  -r, --recurse Recurse mode suitable for mono-repos. Defaults to
128
134
  true. Pass --no-recurse to disable.
129
135
  [boolean] [default: true]
130
- -p, --print Print the SBoM as a table with tree. Defaults to
131
- true if output file is not specified with -o
132
- [boolean]
136
+ -p, --print Print the SBoM as a table with tree. [boolean]
133
137
  -c, --resolve-class Resolve class names for packages. jars only for n
134
138
  ow. [boolean]
135
139
  --deep Perform deep searches for components. Useful whil
@@ -163,8 +167,8 @@ Options:
163
167
  [boolean] [default: true]
164
168
  --spec-version CycloneDX Specification version to use. Defaults
165
169
  to 1.5 [default: 1.5]
166
- --version Show version number [boolean]
167
- -h Show help [boolean]
170
+ -h, --help Show help [boolean]
171
+ -v, --version Show version number [boolean]
168
172
  ```
169
173
 
170
174
  All boolean arguments accepts `--no` prefix to toggle the behavior.
@@ -294,6 +298,8 @@ cdxgen can retain the dependency tree under the `dependencies` attribute for a s
294
298
  | MVN_CMD | Set to override maven command |
295
299
  | MVN_ARGS | Set to pass additional arguments such as profile or settings to maven |
296
300
  | MAVEN_HOME | Specify maven home |
301
+ | MAVEN_CENTRAL_URL | Specify URL of Maven Central for metadata fetching (e.g. when private repo is used) |
302
+ | BAZEL_STRIP_MAVEN_PREFIX | Strip Maven group prefix (e.g. useful when private repo is used, defaults to `/maven2/`) |
297
303
  | GRADLE_CACHE_DIR | Specify gradle cache directory. Useful for class name resolving |
298
304
  | GRADLE_MULTI_PROJECT_MODE | Unused. Automatically handled |
299
305
  | GRADLE_ARGS | Set to pass additional arguments such as profile or settings to gradle (all tasks). Eg: --configuration runtimeClassPath |
@@ -366,15 +372,17 @@ systemctl --user start podman.socket
366
372
  podman system service -t 0 &
367
373
  ```
368
374
 
369
- ### Generate SBoM for a live system
375
+ ### Generate OBoM for a live system
370
376
 
371
- You can use cdxgen to generate SBoM for a live system or a VM for compliance and vulnerability management purposes by passing the argument `-t os`.
377
+ You can use the `obom` command to generate an OBoM for a live system or a VM for compliance and vulnerability management purposes. Windows and Linux operating systems are supported in this mode.
372
378
 
373
379
  ```shell
374
- cdxgen -t os
380
+ # obom is an alias for cdxgen -t os
381
+ obom
382
+ # cdxgen -t os
375
383
  ```
376
384
 
377
- This feature is powered by osquery which is [installed](https://github.com/cyclonedx/cdxgen-plugins-bin/blob/main/build.sh#L8) along with the binary plugins. cdxgen would opportunistically try to detect as many components, apps and extensions as possible using the [default queries](queries.json). The process would take several minutes and result in an SBoM file with thousands of components.
385
+ This feature is powered by osquery which is [installed](https://github.com/cyclonedx/cdxgen-plugins-bin/blob/main/build.sh#L8) along with the binary plugins. cdxgen would opportunistically try to detect as many components, apps and extensions as possible using the [default queries](queries.json). The process would take several minutes and result in an SBoM file with thousands of components of various types such as operating-system, device-drivers, files, and data.
378
386
 
379
387
  ## Generating SaaSBoM and component evidences
380
388
 
package/bin/cdxgen.js CHANGED
@@ -41,8 +41,7 @@ const args = yargs(hideBin(process.argv))
41
41
  .option("print", {
42
42
  alias: "p",
43
43
  type: "boolean",
44
- description:
45
- "Print the SBoM as a table with tree. Defaults to true if output file is not specified with -o"
44
+ description: "Print the SBoM as a table with tree."
46
45
  })
47
46
  .option("resolve-class", {
48
47
  alias: "c",
@@ -122,7 +121,9 @@ const args = yargs(hideBin(process.argv))
122
121
  })
123
122
  .scriptName("cdxgen")
124
123
  .version()
125
- .help("h").argv;
124
+ .alias("v", "version")
125
+ .help("h")
126
+ .alias("h", "help").argv;
126
127
 
127
128
  if (args.version) {
128
129
  const packageJsonAsString = fs.readFileSync(
@@ -157,6 +158,11 @@ if (args.serverUrl || args.apiKey) {
157
158
  args.specVersion = 1.4;
158
159
  }
159
160
 
161
+ // Support for obom aliases
162
+ if (process.argv[1].includes("obom") && !args.type) {
163
+ args.type = "os";
164
+ }
165
+
160
166
  /**
161
167
  * projectType: python, nodejs, java, golang
162
168
  * multiProject: Boolean to indicate monorepo or multi-module projects
@@ -229,7 +235,6 @@ const checkPermissions = (filePath) => {
229
235
  const bomNSData = (await createBom(filePath, options)) || {};
230
236
  if (!args.output) {
231
237
  args.output = "bom.json";
232
- args.print = true;
233
238
  }
234
239
  if (
235
240
  args.output &&
package/bin/repl.js CHANGED
@@ -12,6 +12,7 @@ import { validateBom } from "../validator.js";
12
12
  import {
13
13
  printCallStack,
14
14
  printOccurrences,
15
+ printOSTable,
15
16
  printTable,
16
17
  printDependencyTree,
17
18
  printServices
@@ -32,8 +33,8 @@ process.env.NODE_NO_READLINE = 1;
32
33
  const cdxArt = `
33
34
  ██████╗██████╗ ██╗ ██╗
34
35
  ██╔════╝██╔══██╗╚██╗██╔╝
35
- ██║ ██║ ██║ ╚███╔╝
36
- ██║ ██║ ██║ ██╔██╗
36
+ ██║ ██║ ██║ ╚███╔╝
37
+ ██║ ██║ ██║ ██╔██╗
37
38
  ╚██████╗██████╔╝██╔╝ ██╗
38
39
  ╚═════╝╚═════╝ ╚═╝ ╚═╝
39
40
  `;
@@ -109,16 +110,16 @@ cdxgenRepl.defineCommand("create", {
109
110
  });
110
111
  if (bomNSData) {
111
112
  sbom = bomNSData.bomJson;
112
- console.log("✅ SBoM imported successfully.");
113
- console.log("💭 Type .print to view the SBoM as a table");
113
+ console.log("✅ BoM imported successfully.");
114
+ console.log("💭 Type .print to view the BoM as a table");
114
115
  } else {
115
- console.log("SBoM was not generated successfully");
116
+ console.log("BoM was not generated successfully");
116
117
  }
117
118
  this.displayPrompt();
118
119
  }
119
120
  });
120
121
  cdxgenRepl.defineCommand("import", {
121
- help: "import an existing SBoM",
122
+ help: "import an existing BoM",
122
123
  action(sbomOrPath) {
123
124
  this.clearBufferedCommand();
124
125
  importSbom(sbomOrPath);
@@ -138,14 +139,14 @@ cdxgenRepl.defineCommand("sbom", {
138
139
  console.log(sbom);
139
140
  } else {
140
141
  console.log(
141
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
142
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
142
143
  );
143
144
  }
144
145
  this.displayPrompt();
145
146
  }
146
147
  });
147
148
  cdxgenRepl.defineCommand("search", {
148
- help: "search the current sbom. performs case insensitive search on various attributes.",
149
+ help: "search the current bom. performs case insensitive search on various attributes.",
149
150
  async action(searchStr) {
150
151
  if (sbom) {
151
152
  if (searchStr) {
@@ -170,14 +171,14 @@ cdxgenRepl.defineCommand("search", {
170
171
  }
171
172
  } else {
172
173
  console.log(
173
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
174
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
174
175
  );
175
176
  }
176
177
  this.displayPrompt();
177
178
  }
178
179
  });
179
180
  cdxgenRepl.defineCommand("sort", {
180
- help: "sort the current sbom based on the attribute",
181
+ help: "sort the current bom based on the attribute",
181
182
  async action(sortStr) {
182
183
  if (sbom) {
183
184
  if (sortStr) {
@@ -204,14 +205,14 @@ cdxgenRepl.defineCommand("sort", {
204
205
  }
205
206
  } else {
206
207
  console.log(
207
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
208
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
208
209
  );
209
210
  }
210
211
  this.displayPrompt();
211
212
  }
212
213
  });
213
214
  cdxgenRepl.defineCommand("query", {
214
- help: "query the current sbom using jsonata expression",
215
+ help: "query the current bom using jsonata expression",
215
216
  async action(querySpec) {
216
217
  if (sbom) {
217
218
  if (querySpec) {
@@ -228,20 +229,20 @@ cdxgenRepl.defineCommand("query", {
228
229
  }
229
230
  } else {
230
231
  console.log(
231
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
232
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
232
233
  );
233
234
  }
234
235
  this.displayPrompt();
235
236
  }
236
237
  });
237
238
  cdxgenRepl.defineCommand("print", {
238
- help: "print the current sbom as a table",
239
+ help: "print the current bom as a table",
239
240
  action() {
240
241
  if (sbom) {
241
242
  printTable(sbom);
242
243
  } else {
243
244
  console.log(
244
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
245
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
245
246
  );
246
247
  }
247
248
  this.displayPrompt();
@@ -254,14 +255,14 @@ cdxgenRepl.defineCommand("tree", {
254
255
  printDependencyTree(sbom);
255
256
  } else {
256
257
  console.log(
257
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
258
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
258
259
  );
259
260
  }
260
261
  this.displayPrompt();
261
262
  }
262
263
  });
263
264
  cdxgenRepl.defineCommand("validate", {
264
- help: "validate the sbom using jsonschema",
265
+ help: "validate the bom using jsonschema",
265
266
  action() {
266
267
  if (sbom) {
267
268
  const result = validateBom(sbom);
@@ -270,31 +271,31 @@ cdxgenRepl.defineCommand("validate", {
270
271
  }
271
272
  } else {
272
273
  console.log(
273
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
274
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
274
275
  );
275
276
  }
276
277
  this.displayPrompt();
277
278
  }
278
279
  });
279
280
  cdxgenRepl.defineCommand("save", {
280
- help: "save the sbom to a new file",
281
+ help: "save the bom to a new file",
281
282
  action(saveToFile) {
282
283
  if (sbom) {
283
284
  if (!saveToFile) {
284
285
  saveToFile = "bom.json";
285
286
  }
286
287
  fs.writeFileSync(saveToFile, JSON.stringify(sbom, null, 2));
287
- console.log(`SBoM saved successfully to ${saveToFile}`);
288
+ console.log(`BoM saved successfully to ${saveToFile}`);
288
289
  } else {
289
290
  console.log(
290
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
291
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
291
292
  );
292
293
  }
293
294
  this.displayPrompt();
294
295
  }
295
296
  });
296
297
  cdxgenRepl.defineCommand("update", {
297
- help: "update the sbom components based on the given query",
298
+ help: "update the bom components based on the given query",
298
299
  async action(updateSpec) {
299
300
  if (sbom) {
300
301
  if (!updateSpec) {
@@ -312,10 +313,10 @@ cdxgenRepl.defineCommand("update", {
312
313
  if (newSbom && newSbom.components.length <= sbom.components.length) {
313
314
  sbom = newSbom;
314
315
  }
315
- console.log("SBoM updated successfully.");
316
+ console.log("BoM updated successfully.");
316
317
  } else {
317
318
  console.log(
318
- "⚠ No SBoM is loaded. Use .import command to import an existing SBoM"
319
+ "⚠ No BoM is loaded. Use .import command to import an existing BoM"
319
320
  );
320
321
  }
321
322
  this.displayPrompt();
@@ -332,7 +333,7 @@ cdxgenRepl.defineCommand("occurrences", {
332
333
  let components = await expression.evaluate(sbom);
333
334
  if (!components) {
334
335
  console.log(
335
- "No results found. Use evinse command to generate an SBoM with evidence."
336
+ "No results found. Use evinse command to generate an BoM with evidence."
336
337
  );
337
338
  } else {
338
339
  if (!Array.isArray(components)) {
@@ -345,7 +346,7 @@ cdxgenRepl.defineCommand("occurrences", {
345
346
  }
346
347
  } else {
347
348
  console.log(
348
- "⚠ No SBoM is loaded. Use .import command to import an evinse SBoM"
349
+ "⚠ No BoM is loaded. Use .import command to import an evinse BoM"
349
350
  );
350
351
  }
351
352
  this.displayPrompt();
@@ -425,3 +426,130 @@ cdxgenRepl.defineCommand("services", {
425
426
  this.displayPrompt();
426
427
  }
427
428
  });
429
+ cdxgenRepl.defineCommand("osinfocategories", {
430
+ help: "view the category names for the OS info from the obom",
431
+ async action() {
432
+ if (sbom) {
433
+ try {
434
+ const expression = jsonata(
435
+ '$distinct(components.properties[name="cdx:osquery:category"].value)'
436
+ );
437
+ let catgories = await expression.evaluate(sbom);
438
+ if (!catgories) {
439
+ console.log(
440
+ "Unable to retrieve the os info categories. Only OBoMs generated by cdxgen are supported by this tool."
441
+ );
442
+ } else {
443
+ console.log(catgories.join("\n"));
444
+ }
445
+ } catch (e) {
446
+ console.log(e);
447
+ }
448
+ } else {
449
+ console.log(
450
+ "⚠ No OBoM is loaded. Use .import command to import an OBoM"
451
+ );
452
+ }
453
+ this.displayPrompt();
454
+ }
455
+ });
456
+
457
+ // Let's dynamically define more commands from the queries
458
+ [
459
+ "apt_sources",
460
+ "behavioral_reverse_shell",
461
+ "certificates",
462
+ "chrome_extensions",
463
+ "crontab_snapshot",
464
+ "deb_packages",
465
+ "docker_container_ports",
466
+ "docker_containers",
467
+ "docker_networks",
468
+ "docker_volumes",
469
+ "etc_hosts",
470
+ "firefox_addons",
471
+ "homebrew_packages",
472
+ "installed_applications",
473
+ "interface_addresses",
474
+ "kernel_info",
475
+ "kernel_integrity",
476
+ "kernel_modules",
477
+ "ld_preload",
478
+ "listening_ports",
479
+ "os_version",
480
+ "pipes",
481
+ "pipes_snapshot",
482
+ "portage_packages",
483
+ "process_events",
484
+ "processes",
485
+ "python_packages",
486
+ "rpm_packages",
487
+ "scheduled_tasks",
488
+ "services_snapshot",
489
+ "startup_items",
490
+ "system_info_snapshot",
491
+ "windows_drivers",
492
+ "windows_patches",
493
+ "windows_programs",
494
+ "windows_shared_resources",
495
+ "yum_sources",
496
+ "appcompat_shims",
497
+ "atom_packages",
498
+ "browser_plugins",
499
+ "certificates",
500
+ "chocolatey_packages",
501
+ "chrome_extensions",
502
+ "etc_hosts",
503
+ "firefox_addons",
504
+ "ie_extensions",
505
+ "kernel_info",
506
+ "npm_packages",
507
+ "opera_extensions",
508
+ "pipes_snapshot",
509
+ "process_open_sockets",
510
+ "safari_extensions",
511
+ "scheduled_tasks",
512
+ "services_snapshot",
513
+ "startup_items",
514
+ "routes",
515
+ "system_info_snapshot",
516
+ "win_version",
517
+ "windows_firewall_rules",
518
+ "windows_optional_features",
519
+ "windows_programs",
520
+ "windows_shared_resources",
521
+ "windows_update_history",
522
+ "wmi_cli_event_consumers",
523
+ "wmi_cli_event_consumers_snapshot",
524
+ "wmi_event_filters",
525
+ "wmi_filter_consumer_binding"
526
+ ].forEach((c) => {
527
+ cdxgenRepl.defineCommand(c, {
528
+ help: `query the ${c} category from the OS info`,
529
+ async action() {
530
+ if (sbom) {
531
+ try {
532
+ const expression = jsonata(
533
+ `components[properties[name="cdx:osquery:category" and value="${c}"]]`
534
+ );
535
+ let components = await expression.evaluate(sbom);
536
+ if (!components) {
537
+ console.log("No results found.");
538
+ } else {
539
+ if (!Array.isArray(components)) {
540
+ components = [components];
541
+ }
542
+ printOSTable({ components });
543
+ }
544
+ } catch (e) {
545
+ console.log(e);
546
+ }
547
+ } else {
548
+ console.log(
549
+ "⚠ No OBoM is loaded. Use .import command to import an OBoM"
550
+ );
551
+ }
552
+ this.displayPrompt();
553
+ }
554
+ });
555
+ });
package/bin/verify.js CHANGED
@@ -40,6 +40,25 @@ if (args.version) {
40
40
  }
41
41
 
42
42
  const bomJson = JSON.parse(fs.readFileSync(args.input, "utf8"));
43
+ let hasInvalidComp = false;
44
+ // Validate any component signature
45
+ for (const comp of bomJson.components) {
46
+ if (comp.signature) {
47
+ const compSignature = comp.signature.value;
48
+ const validationResult = jws.verify(
49
+ compSignature,
50
+ comp.signature.algorithm,
51
+ fs.readFileSync(args.publicKey, "utf8")
52
+ );
53
+ if (!validationResult) {
54
+ console.log(`${comp["bom-ref"]} signature is invalid!`);
55
+ hasInvalidComp = true;
56
+ }
57
+ }
58
+ }
59
+ if (hasInvalidComp) {
60
+ process.exit(1);
61
+ }
43
62
  const bomSignature =
44
63
  bomJson.signature && bomJson.signature.value
45
64
  ? bomJson.signature.value
package/binary.js CHANGED
@@ -17,6 +17,7 @@ const isWin = _platform() === "win32";
17
17
 
18
18
  let platform = _platform();
19
19
  let extn = "";
20
+ let pluginsBinSuffix = "";
20
21
  if (platform == "win32") {
21
22
  platform = "windows";
22
23
  extn = ".exe";
@@ -30,6 +31,13 @@ switch (arch) {
30
31
  case "x64":
31
32
  arch = "amd64";
32
33
  break;
34
+ case "arm64":
35
+ pluginsBinSuffix = "-arm64";
36
+ break;
37
+ case "ppc64":
38
+ arch = "ppc64le";
39
+ pluginsBinSuffix = "-ppc64";
40
+ break;
33
41
  }
34
42
 
35
43
  // Retrieve the cdxgen plugins directory
@@ -46,14 +54,20 @@ if (
46
54
  if (
47
55
  !CDXGEN_PLUGINS_DIR &&
48
56
  existsSync(
49
- join(dirName, "node_modules", "@cyclonedx", "cdxgen-plugins-bin", "plugins")
57
+ join(
58
+ dirName,
59
+ "node_modules",
60
+ "@cyclonedx",
61
+ "cdxgen-plugins-bin" + pluginsBinSuffix,
62
+ "plugins"
63
+ )
50
64
  ) &&
51
65
  existsSync(
52
66
  join(
53
67
  dirName,
54
68
  "node_modules",
55
69
  "@cyclonedx",
56
- "cdxgen-plugins-bin",
70
+ "cdxgen-plugins-bin" + pluginsBinSuffix,
57
71
  "plugins",
58
72
  "goversion"
59
73
  )
@@ -63,7 +77,7 @@ if (
63
77
  dirName,
64
78
  "node_modules",
65
79
  "@cyclonedx",
66
- "cdxgen-plugins-bin",
80
+ "cdxgen-plugins-bin" + pluginsBinSuffix,
67
81
  "plugins"
68
82
  );
69
83
  }
@@ -88,7 +102,7 @@ if (!CDXGEN_PLUGINS_DIR) {
88
102
  const globalPlugins = join(
89
103
  globalNodePath,
90
104
  "@cyclonedx",
91
- "cdxgen-plugins-bin",
105
+ "cdxgen-plugins-bin" + pluginsBinSuffix,
92
106
  "plugins"
93
107
  );
94
108
  if (existsSync(globalPlugins)) {
@@ -323,15 +337,21 @@ export const getOSPackages = (src) => {
323
337
  }
324
338
  }
325
339
  const osReleaseData = {};
326
- // Let's try to read the os-release file
327
- if (existsSync(join(src, "usr", "lib", "os-release"))) {
340
+ let osReleaseFile = undefined;
341
+ // Let's try to read the os-release file from various locations
342
+ if (existsSync(join(src, "etc", "os-release"))) {
343
+ osReleaseFile = join(src, "etc", "os-release");
344
+ } else if (existsSync(join(src, "usr", "lib", "os-release"))) {
345
+ osReleaseFile = join(src, "usr", "lib", "os-release");
346
+ }
347
+ if (osReleaseFile) {
328
348
  const osReleaseInfo = readFileSync(
329
349
  join(src, "usr", "lib", "os-release"),
330
350
  "utf-8"
331
351
  );
332
352
  if (osReleaseInfo) {
333
353
  osReleaseInfo.split("\n").forEach((l) => {
334
- if (l.includes("=")) {
354
+ if (!l.startsWith("#") && l.includes("=")) {
335
355
  const tmpA = l.split("=");
336
356
  osReleaseData[tmpA[0]] = tmpA[1].replace(/"/g, "");
337
357
  }
@@ -592,10 +612,11 @@ export const executeOsQuery = (query) => {
592
612
  }
593
613
  const args = ["--json", query];
594
614
  if (DEBUG_MODE) {
595
- console.log("Execuing", OSQUERY_BIN, args.join(" "));
615
+ console.log("Executing", OSQUERY_BIN, args.join(" "));
596
616
  }
597
617
  const result = spawnSync(OSQUERY_BIN, args, {
598
- encoding: "utf-8"
618
+ encoding: "utf-8",
619
+ maxBuffer: 50 * 1024 * 1024
599
620
  });
600
621
  if (result.status !== 0 || result.error) {
601
622
  if (DEBUG_MODE && result.error) {
@@ -607,7 +628,17 @@ export const executeOsQuery = (query) => {
607
628
  if (stdout) {
608
629
  const cmdOutput = Buffer.from(stdout).toString();
609
630
  if (cmdOutput !== "") {
610
- return JSON.parse(cmdOutput);
631
+ try {
632
+ return JSON.parse(cmdOutput);
633
+ } catch (err) {
634
+ // ignore
635
+ if (DEBUG_MODE) {
636
+ console.log("Unable to parse the output from query", query);
637
+ console.log(
638
+ "This could be due to the amount of data returned or the query being invalid for the given platform."
639
+ );
640
+ }
641
+ }
611
642
  }
612
643
  return undefined;
613
644
  }