@cyclonedx/cdxgen 8.6.0 → 9.0.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
@@ -2,46 +2,45 @@
2
2
 
3
3
  ![cdxgen logo](cdxgen.png)
4
4
 
5
- This tool creates 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 XML and JSON format. CycloneDX 1.4 is a lightweight SBOM specification that is easily created, human and machine-readable, and simple to parse.
5
+ This tool creates 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 XML and 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
7
  When used with plugins, cdxgen could generate an SBoM for Linux docker images and even VMs running Linux or Windows operating system.
8
8
 
9
9
  ## Supported languages and package format
10
10
 
11
- | Language/Platform | Package format | Transitive dependencies |
12
- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
13
- | node.js | npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock, rush.js, bower.json, .min.js | Yes except .min.js |
14
- | java | maven (pom.xml [1]), gradle (build.gradle, .kts), scala (sbt), bazel | Yes unless pom.xml is manually parsed due to unavailability of maven or errors |
15
- | php | composer.lock | Yes |
16
- | python | pyproject.toml, setup.py, requirements.txt [2], Pipfile.lock, poetry.lock, bdist_wheel, .whl, .egg-info | Yes using the automatic pip install/freeze. When disabled, only with Pipfile.lock and poetry.lock |
17
- | go | binary, go.mod, go.sum, Gopkg.lock | Yes except binary |
18
- | ruby | Gemfile.lock, gemspec | Only for Gemfile.lock |
19
- | rust | binary, Cargo.toml, Cargo.lock | Only for Cargo.lock |
20
- | .Net | .csproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg | Only for project.assets.json, packages.lock.json |
21
- | dart | pubspec.lock, pubspec.yaml | Only for pubspec.lock |
22
- | haskell | cabal.project.freeze | Yes |
23
- | elixir | mix.lock | Yes |
24
- | c/c++ | conan.lock, conanfile.txt | Yes only for conan.lock |
25
- | clojure | Clojure CLI (deps.edn), Leiningen (project.clj) | Yes unless the files are parsed manually due to lack of clojure cli or leiningen command |
26
- | swift | Package.resolved, Package.swift (swiftpm) | Yes |
27
- | docker / oci image | All supported languages. Linux OS packages with plugins [4] | Best effort based on lock files |
28
- | GitHub Actions | .github/workflows/\*.yml | N/A |
29
- | Linux | All supported languages. Linux OS packages with plugins [5] | Best effort based on lock files |
30
- | Windows | All supported languages. OS packages with best effort [5] | Best effort based on lock files |
31
- | Jenkins Plugins | .hpi files | |
32
- | Helm Charts | .yaml | N/A |
33
- | Skaffold | .yaml | N/A |
34
- | kustomization | .yaml | N/A |
35
- | Tekton tasks | .yaml | N/A |
36
- | Kubernetes | .yaml | N/A |
37
- | Maven Cache | $HOME/.m2/repository/\*\*/\*.jar | N/A |
38
- | SBT Cache | $HOME/.ivy2/cache/\*\*/\*.jar | N/A |
39
- | Gradle Cache | $HOME/caches/modules-2/files-2.1/\*\*/\*.jar | N/A |
40
- | Helm Index | $HOME/.cache/helm/repository/\*\*/\*.yaml | N/A |
41
- | Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A |
42
- | Google CloudBuild configuration | cloudbuild.yaml | N/A |
43
- | OpenAPI | openapi\*.json, openapi\*.yaml | N/A |
44
- | [Privado](https://www.privado.ai?utm_source=cyclonedx) | privado.json | Data and service information will be included. Use with universal mode. |
11
+ | Language/Platform | Package format | Transitive dependencies |
12
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
13
+ | node.js | npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock, rush.js, bower.json, .min.js | Yes except .min.js |
14
+ | java | maven (pom.xml [1]), gradle (build.gradle, .kts), scala (sbt), bazel | Yes unless pom.xml is manually parsed due to unavailability of maven or errors |
15
+ | php | composer.lock | Yes |
16
+ | python | pyproject.toml, setup.py, requirements.txt [2], Pipfile.lock, poetry.lock, bdist_wheel, .whl, .egg-info | Yes using the automatic pip install/freeze. When disabled, only with Pipfile.lock and poetry.lock |
17
+ | go | binary, go.mod, go.sum, Gopkg.lock | Yes except binary |
18
+ | ruby | Gemfile.lock, gemspec | Only for Gemfile.lock |
19
+ | rust | binary, Cargo.toml, Cargo.lock | Only for Cargo.lock |
20
+ | .Net | .csproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg | Only for project.assets.json, packages.lock.json |
21
+ | dart | pubspec.lock, pubspec.yaml | Only for pubspec.lock |
22
+ | haskell | cabal.project.freeze | Yes |
23
+ | elixir | mix.lock | Yes |
24
+ | c/c++ | conan.lock, conanfile.txt | Yes only for conan.lock |
25
+ | clojure | Clojure CLI (deps.edn), Leiningen (project.clj) | Yes unless the files are parsed manually due to lack of clojure cli or leiningen command |
26
+ | swift | Package.resolved, Package.swift (swiftpm) | Yes |
27
+ | docker / oci image | All supported languages. Linux OS packages with plugins [4] | Best effort based on lock files |
28
+ | GitHub Actions | .github/workflows/\*.yml | N/A |
29
+ | Linux | All supported languages. Linux OS packages with plugins [5] | Best effort based on lock files |
30
+ | Windows | All supported languages. OS packages with best effort [5] | Best effort based on lock files |
31
+ | Jenkins Plugins | .hpi files | |
32
+ | Helm Charts | .yaml | N/A |
33
+ | Skaffold | .yaml | N/A |
34
+ | kustomization | .yaml | N/A |
35
+ | Tekton tasks | .yaml | N/A |
36
+ | Kubernetes | .yaml | N/A |
37
+ | Maven Cache | $HOME/.m2/repository/\*\*/\*.jar | N/A |
38
+ | SBT Cache | $HOME/.ivy2/cache/\*\*/\*.jar | N/A |
39
+ | Gradle Cache | $HOME/caches/modules-2/files-2.1/\*\*/\*.jar | N/A |
40
+ | Helm Index | $HOME/.cache/helm/repository/\*\*/\*.yaml | N/A |
41
+ | Docker compose | docker-compose\*.yml. Images would also be scanned. | N/A |
42
+ | Google CloudBuild configuration | cloudbuild.yaml | N/A |
43
+ | OpenAPI | openapi\*.json, openapi\*.yaml | N/A |
45
44
 
46
45
  NOTE:
47
46
 
@@ -133,10 +132,6 @@ Minimal example.
133
132
  cdxgen -o bom.json
134
133
  ```
135
134
 
136
- NOTE:
137
-
138
- cdxgen would always produce bom in both xml and json format as per CycloneDX 1.4 specification. json is the recommended format.
139
-
140
135
  For a java project. This would automatically detect maven, gradle or sbt and build bom accordingly
141
136
 
142
137
  ```shell
@@ -200,17 +195,6 @@ git clone https://github.com/cyclonedx/cdxgen.git
200
195
  docker compose up
201
196
  ```
202
197
 
203
- ## Privado.ai support
204
-
205
- In universal mode, cdxgen can look for any [Privado](https://www.privado.ai?utm_source=cyclonedx) scan reports and enrich the SBoM with data (flow and classification), endpoints, and leakage information. Such an SBoM would help with privacy compliance and use cases.
206
-
207
- Invoke privado scan first to generate this report followed by an invocation of cdxgen in universal mode as shown.
208
-
209
- ```shell
210
- privado scan --enable-javascript <directory>
211
- cdxgen -t universal <directory> -o bom.json
212
- ```
213
-
214
198
  ## War file support
215
199
 
216
200
  cdxgen can generate a BoM file from a given war file.
@@ -362,6 +346,24 @@ Permission to modify and redistribute is granted under the terms of the Apache 2
362
346
  [license]: https://github.com/cyclonedx/cdxgen/blob/master/LICENSE
363
347
  [cyclonedx-homepage]: https://cyclonedx.org
364
348
 
349
+ ## Integration as library
350
+
351
+ This project is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) and requires Node.js >= 16
352
+
353
+ Minimal example:
354
+
355
+ ```javascript
356
+ import { createBom, submitBom } from "@cyclonedx/cdxgen";
357
+ // bomNSData would contain bomJson, bomXml
358
+ const bomNSData = await createBom(filePath, options);
359
+ // Submission to dependency track server
360
+ const dbody = await submitBom(args, bomNSData.bomXml);
361
+ ```
362
+
363
+ ## Node.js >= 20 permission model
364
+
365
+ Refer to the [permissions document](./docs/PERMISSIONS.md)
366
+
365
367
  ## Contributing
366
368
 
367
369
  Follow the usual PR process but prior to raising a PR run the following commands.
package/analyzer.js CHANGED
@@ -1,8 +1,8 @@
1
- const babelParser = require("@babel/parser");
2
- const babelTraverse = require("@babel/traverse").default;
3
- const { join } = require("path");
4
- const fs = require("fs");
5
- const path = require("path");
1
+ import { parse } from "@babel/parser";
2
+ import babelTraverse from "@babel/traverse";
3
+ import { join } from "path";
4
+ import { readdirSync, statSync, readFileSync } from "fs";
5
+ import { basename, resolve, isAbsolute } from "path";
6
6
 
7
7
  const IGNORE_DIRS = [
8
8
  "node_modules",
@@ -28,7 +28,7 @@ const IGNORE_FILE_PATTERN = new RegExp(
28
28
  );
29
29
 
30
30
  const getAllFiles = (dir, extn, files, result, regex) => {
31
- files = files || fs.readdirSync(dir);
31
+ files = files || readdirSync(dir);
32
32
  result = result || [];
33
33
  regex = regex || new RegExp(`\\${extn}$`);
34
34
 
@@ -37,9 +37,9 @@ const getAllFiles = (dir, extn, files, result, regex) => {
37
37
  continue;
38
38
  }
39
39
  let file = join(dir, files[i]);
40
- if (fs.statSync(file).isDirectory()) {
40
+ if (statSync(file).isDirectory()) {
41
41
  // Ignore directories
42
- const dirName = path.basename(file);
42
+ const dirName = basename(file);
43
43
  if (
44
44
  dirName.startsWith(".") ||
45
45
  IGNORE_DIRS.includes(dirName.toLowerCase())
@@ -47,7 +47,7 @@ const getAllFiles = (dir, extn, files, result, regex) => {
47
47
  continue;
48
48
  }
49
49
  try {
50
- result = getAllFiles(file, extn, fs.readdirSync(file), result, regex);
50
+ result = getAllFiles(file, extn, readdirSync(file), result, regex);
51
51
  } catch (error) {
52
52
  continue;
53
53
  }
@@ -95,11 +95,11 @@ const setFileRef = (allImports, file, pathway) => {
95
95
  // replace relative imports with full path
96
96
  let module = pathway;
97
97
  if (/\.\//g.test(pathway) || /\.\.\//g.test(pathway)) {
98
- module = path.resolve(file, "..", pathway);
98
+ module = resolve(file, "..", pathway);
99
99
  }
100
100
 
101
101
  // initialise or increase reference count for file
102
- if (allImports.hasOwnProperty(module)) {
102
+ if (Object.prototype.hasOwnProperty.call(allImports, module)) {
103
103
  allImports[module] = allImports[module] + 1;
104
104
  } else {
105
105
  allImports[module] = 1;
@@ -107,9 +107,9 @@ const setFileRef = (allImports, file, pathway) => {
107
107
 
108
108
  // Handle module package name
109
109
  // Eg: zone.js/dist/zone will be referred to as zone.js in package.json
110
- if (!path.isAbsolute(module) && module.includes("/")) {
110
+ if (!isAbsolute(module) && module.includes("/")) {
111
111
  const modPkg = module.split("/")[0];
112
- if (allImports.hasOwnProperty(modPkg)) {
112
+ if (Object.prototype.hasOwnProperty.call(allImports, modPkg)) {
113
113
  allImports[modPkg] = allImports[modPkg] + 1;
114
114
  } else {
115
115
  allImports[modPkg] = 1;
@@ -122,10 +122,7 @@ const setFileRef = (allImports, file, pathway) => {
122
122
  * references for any import, require or dynamic import files.
123
123
  */
124
124
  const parseFileASTTree = (file, allImports) => {
125
- const ast = babelParser.parse(
126
- fs.readFileSync(file, "utf-8"),
127
- babelParserOptions
128
- );
125
+ const ast = parse(readFileSync(file, "utf-8"), babelParserOptions);
129
126
  babelTraverse(ast, {
130
127
  // Used for all ES6 import statements
131
128
  ImportDeclaration: (path) => {
@@ -177,7 +174,7 @@ const getAllSrcJSAndTSFiles = (src) =>
177
174
  /**
178
175
  * Where Node CLI runs from.
179
176
  */
180
- const findJSImports = async (src) => {
177
+ export const findJSImports = async (src) => {
181
178
  const allImports = {};
182
179
  const errFiles = [];
183
180
  try {
@@ -195,4 +192,3 @@ const findJSImports = async (src) => {
195
192
  return allImports;
196
193
  }
197
194
  };
198
- exports.findJSImports = findJSImports;
@@ -1,13 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const bom = require("../index.js");
4
- const fs = require("fs");
5
- const path = require("path");
6
- const jws = require("jws");
7
- const crypto = require("crypto");
8
- const bomServer = require("../server.js");
3
+ import { createBom, submitBom } from "../index.js";
4
+ import fs from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { basename, dirname, join, resolve } from "node:path";
7
+ import jws from "jws";
8
+ import crypto from "crypto";
9
+ import { start as _serverStart } from "../server.js";
10
+ import { fileURLToPath } from "node:url";
11
+ import globalAgent from "global-agent";
12
+ import { table } from "table";
13
+ import process from "node:process";
9
14
 
10
- const args = require("yargs")
15
+ let url = import.meta.url;
16
+ if (!url.startsWith("file://")) {
17
+ url = new URL(`file://${import.meta.url}`).toString();
18
+ }
19
+ const dirName = import.meta ? dirname(fileURLToPath(url)) : __dirname;
20
+
21
+ import yargs from "yargs";
22
+ import { hideBin } from "yargs/helpers";
23
+
24
+ const args = yargs(hideBin(process.argv))
11
25
  .option("output", {
12
26
  alias: "o",
13
27
  description: "Output file for bom.xml or bom.json. Default bom.json"
@@ -99,7 +113,7 @@ const args = require("yargs")
99
113
 
100
114
  if (args.version) {
101
115
  const packageJsonAsString = fs.readFileSync(
102
- path.join(__dirname, "../", "package.json"),
116
+ join(dirName, "..", "package.json"),
103
117
  "utf-8"
104
118
  );
105
119
  const packageJson = JSON.parse(packageJsonAsString);
@@ -113,16 +127,15 @@ if (process.env.GLOBAL_AGENT_HTTP_PROXY || process.env.HTTP_PROXY) {
113
127
  if (!process.env.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE) {
114
128
  process.env.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE = "";
115
129
  }
116
- const globalAgent = require("global-agent");
117
130
  globalAgent.bootstrap();
118
131
  }
119
132
 
120
133
  let filePath = args._[0] || ".";
121
134
  if (!args.projectName) {
122
135
  if (filePath !== ".") {
123
- args.projectName = path.basename(filePath);
136
+ args.projectName = basename(filePath);
124
137
  } else {
125
- args.projectName = path.basename(path.resolve(filePath));
138
+ args.projectName = basename(resolve(filePath));
126
139
  }
127
140
  }
128
141
 
@@ -150,15 +163,51 @@ let options = {
150
163
  serverPort: args.serverPort
151
164
  };
152
165
 
166
+ /**
167
+ * Check for node >= 20 permissions
168
+ *
169
+ * @param {string} filePath File path
170
+ * @returns
171
+ */
172
+ const checkPermissions = (filePath) => {
173
+ if (!process.permission) {
174
+ return true;
175
+ }
176
+ if (!process.permission.has("fs.read", filePath)) {
177
+ console.log(
178
+ `FileSystemRead permission required. Please invoke with the argument --allow-fs-read="${resolve(
179
+ filePath
180
+ )}"`
181
+ );
182
+ return false;
183
+ }
184
+ if (!process.permission.has("fs.write", tmpdir())) {
185
+ console.log(
186
+ `FileSystemWrite permission required. Please invoke with the argument --allow-fs-write="${tmpdir()}"`
187
+ );
188
+ return false;
189
+ }
190
+ if (!process.permission.has("child")) {
191
+ console.log(
192
+ "ChildProcess permission is missing. This is required to spawn commands for some languages. Please invoke with the argument --allow-child-process"
193
+ );
194
+ }
195
+ return true;
196
+ };
197
+
153
198
  /**
154
199
  * Method to start the bom creation process
155
200
  */
156
201
  (async () => {
157
202
  // Start SBoM server
158
203
  if (args.server) {
159
- return await bomServer.start(options);
204
+ return await _serverStart(options);
205
+ }
206
+ // Check if cdxgen has the required permissions
207
+ if (!checkPermissions(filePath)) {
208
+ return;
160
209
  }
161
- const bomNSData = (await bom.createBom(filePath, options)) || {};
210
+ const bomNSData = (await createBom(filePath, options)) || {};
162
211
  if (!args.output) {
163
212
  args.output = "bom.json";
164
213
  args.print = true;
@@ -172,7 +221,7 @@ let options = {
172
221
  } else {
173
222
  const jsonFile = args.output.replace(".xml", ".json");
174
223
  // Create bom json file
175
- if (bomNSData.bomJson) {
224
+ if (!args.output.endsWith(".xml") && bomNSData.bomJson) {
176
225
  let jsonPayload = undefined;
177
226
  if (
178
227
  typeof bomNSData.bomJson === "string" ||
@@ -199,9 +248,9 @@ let options = {
199
248
  let privateKeyToUse = undefined;
200
249
  let jwkPublicKey = undefined;
201
250
  if (args.generateKeyAndSign) {
202
- const dirName = path.dirname(jsonFile);
203
- const publicKeyFile = path.join(dirName, "public.key");
204
- const privateKeyFile = path.join(dirName, "private.key");
251
+ const jdirName = dirname(jsonFile);
252
+ const publicKeyFile = join(jdirName, "public.key");
253
+ const privateKeyFile = join(jdirName, "private.key");
205
254
  const { privateKey, publicKey } = crypto.generateKeyPairSync(
206
255
  "rsa",
207
256
  {
@@ -271,9 +320,8 @@ let options = {
271
320
  }
272
321
  }
273
322
  // Create bom xml file
274
- if (bomNSData.bomXml) {
275
- const xmlFile = args.output.replace(".json", ".xml");
276
- fs.writeFileSync(xmlFile, bomNSData.bomXml);
323
+ if (args.output.endsWith(".xml") && bomNSData.bomXml) {
324
+ fs.writeFileSync(args.output, bomNSData.bomXml);
277
325
  }
278
326
  //
279
327
  if (bomNSData.nsMapping && Object.keys(bomNSData.nsMapping).length) {
@@ -296,8 +344,7 @@ let options = {
296
344
  // Automatically submit the bom data
297
345
  if (args.serverUrl && args.serverUrl != true && args.apiKey) {
298
346
  try {
299
- // TODO: Need to use json format for v9
300
- const dbody = await bom.submitBom(args, bomNSData.bomXml);
347
+ const dbody = await submitBom(args, bomNSData.bomJson);
301
348
  console.log("Response from server", dbody);
302
349
  } catch (err) {
303
350
  console.log(err);
@@ -305,7 +352,6 @@ let options = {
305
352
  }
306
353
 
307
354
  if (args.print && bomNSData.bomJson && bomNSData.bomJson.components) {
308
- const { table } = require("table");
309
355
  const data = [["Group", "Name", "Version", "Scope"]];
310
356
  for (let comp of bomNSData.bomJson.components) {
311
357
  data.push([comp.group || "", comp.name, comp.version, comp.scope || ""]);
package/binary.js CHANGED
@@ -1,9 +1,19 @@
1
- const os = require("os");
2
- const fs = require("fs");
3
- const path = require("path");
4
- const { spawnSync } = require("child_process");
5
- const { PackageURL } = require("packageurl-js");
6
- const isWin = require("os").platform() === "win32";
1
+ import { platform as _platform, arch as _arch, tmpdir } from "node:os";
2
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
3
+ import { join, dirname, basename } from "node:path";
4
+ import { spawnSync } from "node:child_process";
5
+ import { PackageURL } from "packageurl-js";
6
+
7
+ import { fileURLToPath } from "node:url";
8
+ import path from "node:path";
9
+
10
+ let url = import.meta.url;
11
+ if (!url.startsWith("file://")) {
12
+ url = new URL(`file://${import.meta.url}`).toString();
13
+ }
14
+ const dirName = import.meta ? path.dirname(fileURLToPath(url)) : __dirname;
15
+
16
+ const isWin = _platform() === "win32";
7
17
 
8
18
  // Debug mode flag
9
19
  const DEBUG_MODE =
@@ -12,14 +22,14 @@ const DEBUG_MODE =
12
22
  process.env.SHIFTLEFT_LOGGING_LEVEL === "debug" ||
13
23
  process.env.NODE_ENV === "development";
14
24
 
15
- let platform = os.platform();
25
+ let platform = _platform();
16
26
  let extn = "";
17
27
  if (platform == "win32") {
18
28
  platform = "windows";
19
29
  extn = ".exe";
20
30
  }
21
31
 
22
- let arch = os.arch();
32
+ let arch = _arch();
23
33
  switch (arch) {
24
34
  case "x32":
25
35
  arch = "386";
@@ -34,26 +44,20 @@ let CDXGEN_PLUGINS_DIR = process.env.CDXGEN_PLUGINS_DIR;
34
44
  // Is there a non-empty local plugins directory
35
45
  if (
36
46
  !CDXGEN_PLUGINS_DIR &&
37
- fs.existsSync(path.join(__dirname, "plugins")) &&
38
- fs.existsSync(path.join(__dirname, "plugins", "goversion"))
47
+ existsSync(join(dirName, "plugins")) &&
48
+ existsSync(join(dirName, "plugins", "goversion"))
39
49
  ) {
40
- CDXGEN_PLUGINS_DIR = path.join(__dirname, "plugins");
50
+ CDXGEN_PLUGINS_DIR = join(dirName, "plugins");
41
51
  }
42
52
  // Is there a non-empty local node_modules directory
43
53
  if (
44
54
  !CDXGEN_PLUGINS_DIR &&
45
- fs.existsSync(
46
- path.join(
47
- __dirname,
48
- "node_modules",
49
- "@cyclonedx",
50
- "cdxgen-plugins-bin",
51
- "plugins"
52
- )
55
+ existsSync(
56
+ join(dirName, "node_modules", "@cyclonedx", "cdxgen-plugins-bin", "plugins")
53
57
  ) &&
54
- fs.existsSync(
55
- path.join(
56
- __dirname,
58
+ existsSync(
59
+ join(
60
+ dirName,
57
61
  "node_modules",
58
62
  "@cyclonedx",
59
63
  "cdxgen-plugins-bin",
@@ -62,8 +66,8 @@ if (
62
66
  )
63
67
  )
64
68
  ) {
65
- CDXGEN_PLUGINS_DIR = path.join(
66
- __dirname,
69
+ CDXGEN_PLUGINS_DIR = join(
70
+ dirName,
67
71
  "node_modules",
68
72
  "@cyclonedx",
69
73
  "cdxgen-plugins-bin",
@@ -88,13 +92,13 @@ if (!CDXGEN_PLUGINS_DIR) {
88
92
  }
89
93
  }
90
94
  }
91
- const globalPlugins = path.join(
95
+ const globalPlugins = join(
92
96
  globalNodePath,
93
97
  "@cyclonedx",
94
98
  "cdxgen-plugins-bin",
95
99
  "plugins"
96
100
  );
97
- if (fs.existsSync(globalPlugins)) {
101
+ if (existsSync(globalPlugins)) {
98
102
  CDXGEN_PLUGINS_DIR = globalPlugins;
99
103
  if (DEBUG_MODE) {
100
104
  console.log("Found global plugins", CDXGEN_PLUGINS_DIR);
@@ -111,16 +115,16 @@ if (!CDXGEN_PLUGINS_DIR) {
111
115
  CDXGEN_PLUGINS_DIR = "";
112
116
  }
113
117
  let GOVERSION_BIN = null;
114
- if (fs.existsSync(path.join(CDXGEN_PLUGINS_DIR, "goversion"))) {
115
- GOVERSION_BIN = path.join(
118
+ if (existsSync(join(CDXGEN_PLUGINS_DIR, "goversion"))) {
119
+ GOVERSION_BIN = join(
116
120
  CDXGEN_PLUGINS_DIR,
117
121
  "goversion",
118
122
  "goversion-" + platform + "-" + arch + extn
119
123
  );
120
124
  }
121
125
  let TRIVY_BIN = null;
122
- if (fs.existsSync(path.join(CDXGEN_PLUGINS_DIR, "trivy"))) {
123
- TRIVY_BIN = path.join(
126
+ if (existsSync(join(CDXGEN_PLUGINS_DIR, "trivy"))) {
127
+ TRIVY_BIN = join(
124
128
  CDXGEN_PLUGINS_DIR,
125
129
  "trivy",
126
130
  "trivy-cdxgen-" + platform + "-" + arch + extn
@@ -129,8 +133,8 @@ if (fs.existsSync(path.join(CDXGEN_PLUGINS_DIR, "trivy"))) {
129
133
  TRIVY_BIN = process.env.TRIVY_CMD;
130
134
  }
131
135
  let CARGO_AUDITABLE_BIN = null;
132
- if (fs.existsSync(path.join(CDXGEN_PLUGINS_DIR, "cargo-auditable"))) {
133
- CARGO_AUDITABLE_BIN = path.join(
136
+ if (existsSync(join(CDXGEN_PLUGINS_DIR, "cargo-auditable"))) {
137
+ CARGO_AUDITABLE_BIN = join(
134
138
  CDXGEN_PLUGINS_DIR,
135
139
  "cargo-auditable",
136
140
  "cargo-auditable-cdxgen-" + platform + "-" + arch + extn
@@ -139,8 +143,8 @@ if (fs.existsSync(path.join(CDXGEN_PLUGINS_DIR, "cargo-auditable"))) {
139
143
  CARGO_AUDITABLE_BIN = process.env.CARGO_AUDITABLE_CMD;
140
144
  }
141
145
  let OSQUERY_BIN = null;
142
- if (fs.existsSync(path.join(CDXGEN_PLUGINS_DIR, "osquery"))) {
143
- OSQUERY_BIN = path.join(
146
+ if (existsSync(join(CDXGEN_PLUGINS_DIR, "osquery"))) {
147
+ OSQUERY_BIN = join(
144
148
  CDXGEN_PLUGINS_DIR,
145
149
  "osquery",
146
150
  "osqueryi-" + platform + "-" + arch + extn
@@ -213,7 +217,7 @@ const OS_DISTRO_ALIAS = {
213
217
  "debian-1.1": "buzz"
214
218
  };
215
219
 
216
- const getGoBuildInfo = (src) => {
220
+ export const getGoBuildInfo = (src) => {
217
221
  if (GOVERSION_BIN) {
218
222
  let result = spawnSync(GOVERSION_BIN, [src], {
219
223
  encoding: "utf-8"
@@ -244,9 +248,8 @@ const getGoBuildInfo = (src) => {
244
248
  }
245
249
  return undefined;
246
250
  };
247
- exports.getGoBuildInfo = getGoBuildInfo;
248
251
 
249
- const getCargoAuditableInfo = (src) => {
252
+ export const getCargoAuditableInfo = (src) => {
250
253
  if (CARGO_AUDITABLE_BIN) {
251
254
  let result = spawnSync(CARGO_AUDITABLE_BIN, [src], {
252
255
  encoding: "utf-8"
@@ -266,18 +269,17 @@ const getCargoAuditableInfo = (src) => {
266
269
  }
267
270
  return undefined;
268
271
  };
269
- exports.getCargoAuditableInfo = getCargoAuditableInfo;
270
272
 
271
- const getOSPackages = (src) => {
273
+ export const getOSPackages = (src) => {
272
274
  const pkgList = [];
273
275
  const allTypes = new Set();
274
276
  if (TRIVY_BIN) {
275
277
  let imageType = "image";
276
- if (fs.existsSync(src)) {
278
+ if (existsSync(src)) {
277
279
  imageType = "rootfs";
278
280
  }
279
- let tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "trivy-cdxgen-"));
280
- const bomJsonFile = path.join(tempDir, "trivy-bom.json");
281
+ let tempDir = mkdtempSync(join(tmpdir(), "trivy-cdxgen-"));
282
+ const bomJsonFile = join(tempDir, "trivy-bom.json");
281
283
  const args = [
282
284
  imageType,
283
285
  "--skip-db-update",
@@ -305,11 +307,11 @@ const getOSPackages = (src) => {
305
307
  console.error(result.stdout, result.stderr);
306
308
  }
307
309
  }
308
- if (fs.existsSync(bomJsonFile)) {
310
+ if (existsSync(bomJsonFile)) {
309
311
  let tmpBom = {};
310
312
  try {
311
313
  tmpBom = JSON.parse(
312
- fs.readFileSync(bomJsonFile, {
314
+ readFileSync(bomJsonFile, {
313
315
  encoding: "utf-8"
314
316
  })
315
317
  );
@@ -317,12 +319,12 @@ const getOSPackages = (src) => {
317
319
  // ignore errors
318
320
  }
319
321
  // Clean up
320
- if (tempDir && tempDir.startsWith(os.tmpdir())) {
322
+ if (tempDir && tempDir.startsWith(tmpdir())) {
321
323
  if (DEBUG_MODE) {
322
324
  console.log(`Cleaning up ${tempDir}`);
323
325
  }
324
- if (fs.rmSync) {
325
- fs.rmSync(tempDir, { recursive: true, force: true });
326
+ if (rmSync) {
327
+ rmSync(tempDir, { recursive: true, force: true });
326
328
  }
327
329
  }
328
330
  if (tmpBom && tmpBom.components) {
@@ -347,8 +349,8 @@ const getOSPackages = (src) => {
347
349
  continue;
348
350
  }
349
351
  // Fix the group
350
- let group = path.dirname(comp.name);
351
- let name = path.basename(comp.name);
352
+ let group = dirname(comp.name);
353
+ let name = basename(comp.name);
352
354
  let purlObj = undefined;
353
355
  let distro_codename = "";
354
356
  if (group === ".") {
@@ -483,9 +485,8 @@ const getOSPackages = (src) => {
483
485
  }
484
486
  return { osPackages: pkgList, allTypes: Array.from(allTypes) };
485
487
  };
486
- exports.getOSPackages = getOSPackages;
487
488
 
488
- const executeOsQuery = (query) => {
489
+ export const executeOsQuery = (query) => {
489
490
  if (OSQUERY_BIN) {
490
491
  if (!query.endsWith(";")) {
491
492
  query = query + ";";
@@ -515,4 +516,3 @@ const executeOsQuery = (query) => {
515
516
  }
516
517
  return undefined;
517
518
  };
518
- exports.executeOsQuery = executeOsQuery;