@cyclonedx/cdxgen 10.3.5 → 10.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -4
- package/analyzer.js +18 -18
- package/bin/cdxgen.js +78 -77
- package/bin/evinse.js +26 -26
- package/bin/repl.js +56 -62
- package/bin/verify.js +9 -9
- package/binary.js +55 -54
- package/cbomutils.js +6 -6
- package/db.js +17 -17
- package/display.js +30 -30
- package/display.test.js +2 -2
- package/docker.js +92 -89
- package/docker.test.js +30 -30
- package/envcontext.js +15 -15
- package/envcontext.test.js +1 -1
- package/evinser.js +94 -93
- package/evinser.test.js +24 -24
- package/index.js +522 -482
- package/package.json +8 -16
- package/piptree.js +6 -6
- package/postgen.js +2 -2
- package/postgen.test.js +5 -5
- package/protobom.js +37 -7
- package/protobom.test.js +6 -6
- package/server.js +16 -16
- package/types/analyzer.d.ts +7 -4
- package/types/binary.d.ts +12 -8
- package/types/cbomutils.d.ts +1 -1
- package/types/db.d.ts +23 -11
- package/types/display.d.ts +1 -1
- package/types/docker.d.ts +52 -32
- package/types/envcontext.d.ts +40 -40
- package/types/evinser.d.ts +3436 -717
- package/types/index.d.ts +66 -40
- package/types/jest.config.d.ts +2 -2
- package/types/piptree.d.ts +6 -2
- package/types/postgen.d.ts +1 -1
- package/types/protobom.d.ts +7 -3
- package/types/protobom.d.ts.map +1 -1
- package/types/server.d.ts +1 -1
- package/types/utils.d.ts +496 -302
- package/types/validator.d.ts +1 -1
- package/utils.js +742 -675
- package/utils.test.js +716 -674
- package/validator.js +20 -17
package/bin/evinse.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import process from "node:process";
|
|
5
|
+
import { findUpSync } from "find-up";
|
|
6
|
+
import { load as _load } from "js-yaml";
|
|
3
7
|
// Evinse (Evinse Verification Is Nearly SBOM Evidence)
|
|
4
8
|
import yargs from "yargs";
|
|
5
9
|
import { hideBin } from "yargs/helpers";
|
|
6
|
-
import fs from "node:fs";
|
|
7
|
-
import process from "node:process";
|
|
8
|
-
import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
|
|
9
|
-
import { validateBom } from "../validator.js";
|
|
10
10
|
import {
|
|
11
11
|
printCallStack,
|
|
12
12
|
printOccurrences,
|
|
13
13
|
printReachables,
|
|
14
|
-
printServices
|
|
14
|
+
printServices,
|
|
15
15
|
} from "../display.js";
|
|
16
|
+
import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
|
|
16
17
|
import { ATOM_DB } from "../utils.js";
|
|
17
|
-
import {
|
|
18
|
-
import { load as _load } from "js-yaml";
|
|
18
|
+
import { validateBom } from "../validator.js";
|
|
19
19
|
|
|
20
20
|
// Support for config files
|
|
21
21
|
const configPath = findUpSync([
|
|
22
22
|
".cdxgenrc",
|
|
23
23
|
".cdxgen.json",
|
|
24
24
|
".cdxgen.yml",
|
|
25
|
-
".cdxgen.yaml"
|
|
25
|
+
".cdxgen.yaml",
|
|
26
26
|
]);
|
|
27
27
|
let config = {};
|
|
28
28
|
if (configPath) {
|
|
@@ -42,12 +42,12 @@ const args = yargs(hideBin(process.argv))
|
|
|
42
42
|
.option("input", {
|
|
43
43
|
alias: "i",
|
|
44
44
|
description: "Input SBOM file. Default bom.json",
|
|
45
|
-
default: "bom.json"
|
|
45
|
+
default: "bom.json",
|
|
46
46
|
})
|
|
47
47
|
.option("output", {
|
|
48
48
|
alias: "o",
|
|
49
49
|
description: "Output file. Default bom.evinse.json",
|
|
50
|
-
default: "bom.evinse.json"
|
|
50
|
+
default: "bom.evinse.json",
|
|
51
51
|
})
|
|
52
52
|
.option("language", {
|
|
53
53
|
alias: "l",
|
|
@@ -64,72 +64,72 @@ const args = yargs(hideBin(process.argv))
|
|
|
64
64
|
"android",
|
|
65
65
|
"c",
|
|
66
66
|
"cpp",
|
|
67
|
-
"php"
|
|
68
|
-
]
|
|
67
|
+
"php",
|
|
68
|
+
],
|
|
69
69
|
})
|
|
70
70
|
.option("db-path", {
|
|
71
71
|
description: `Atom slices DB path. Default ${ATOM_DB}`,
|
|
72
|
-
default: process.env.ATOM_DB || ATOM_DB
|
|
72
|
+
default: process.env.ATOM_DB || ATOM_DB,
|
|
73
73
|
})
|
|
74
74
|
.option("force", {
|
|
75
75
|
description: "Force creation of the database",
|
|
76
76
|
default: false,
|
|
77
|
-
type: "boolean"
|
|
77
|
+
type: "boolean",
|
|
78
78
|
})
|
|
79
79
|
.option("skip-maven-collector", {
|
|
80
80
|
description:
|
|
81
81
|
"Skip collecting jars from maven and gradle caches. Can speedup re-runs if the data was cached previously.",
|
|
82
82
|
default: false,
|
|
83
|
-
type: "boolean"
|
|
83
|
+
type: "boolean",
|
|
84
84
|
})
|
|
85
85
|
.option("with-deep-jar-collector", {
|
|
86
86
|
description:
|
|
87
87
|
"Enable collection of all jars from maven cache directory. Useful to improve the recall for callstack evidence.",
|
|
88
88
|
default: false,
|
|
89
|
-
type: "boolean"
|
|
89
|
+
type: "boolean",
|
|
90
90
|
})
|
|
91
91
|
.option("annotate", {
|
|
92
92
|
description: "Include contents of atom slices as annotations",
|
|
93
93
|
default: false,
|
|
94
|
-
type: "boolean"
|
|
94
|
+
type: "boolean",
|
|
95
95
|
})
|
|
96
96
|
.option("with-data-flow", {
|
|
97
97
|
description: "Enable inter-procedural data-flow slicing.",
|
|
98
98
|
default: false,
|
|
99
|
-
type: "boolean"
|
|
99
|
+
type: "boolean",
|
|
100
100
|
})
|
|
101
101
|
.option("with-reachables", {
|
|
102
102
|
description:
|
|
103
103
|
"Enable auto-tagged reachable slicing. Requires SBOM generated with --deep mode.",
|
|
104
104
|
default: false,
|
|
105
|
-
type: "boolean"
|
|
105
|
+
type: "boolean",
|
|
106
106
|
})
|
|
107
107
|
.option("usages-slices-file", {
|
|
108
108
|
description: "Use an existing usages slices file.",
|
|
109
|
-
default: "usages.slices.json"
|
|
109
|
+
default: "usages.slices.json",
|
|
110
110
|
})
|
|
111
111
|
.option("data-flow-slices-file", {
|
|
112
112
|
description: "Use an existing data-flow slices file.",
|
|
113
|
-
default: "data-flow.slices.json"
|
|
113
|
+
default: "data-flow.slices.json",
|
|
114
114
|
})
|
|
115
115
|
.option("reachables-slices-file", {
|
|
116
116
|
description: "Use an existing reachables slices file.",
|
|
117
|
-
default: "reachables.slices.json"
|
|
117
|
+
default: "reachables.slices.json",
|
|
118
118
|
})
|
|
119
119
|
.option("print", {
|
|
120
120
|
alias: "p",
|
|
121
121
|
type: "boolean",
|
|
122
|
-
description: "Print the evidences as table"
|
|
122
|
+
description: "Print the evidences as table",
|
|
123
123
|
})
|
|
124
124
|
.example([
|
|
125
125
|
[
|
|
126
126
|
"$0 -i bom.json -o bom.evinse.json -l java .",
|
|
127
|
-
"Generate a Java SBOM with evidence for the current directory"
|
|
127
|
+
"Generate a Java SBOM with evidence for the current directory",
|
|
128
128
|
],
|
|
129
129
|
[
|
|
130
130
|
"$0 -i bom.json -o bom.evinse.json -l java --with-reachables .",
|
|
131
|
-
"Generate a Java SBOM with occurrence and reachable evidence for the current directory"
|
|
132
|
-
]
|
|
131
|
+
"Generate a Java SBOM with occurrence and reachable evidence for the current directory",
|
|
132
|
+
],
|
|
133
133
|
])
|
|
134
134
|
.completion("completion", "Generate bash/zsh completion")
|
|
135
135
|
.epilogue("for documentation, visit https://cyclonedx.github.io/cdxgen")
|
package/bin/repl.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import repl from "node:repl";
|
|
4
|
-
import jsonata from "jsonata";
|
|
5
3
|
import fs from "node:fs";
|
|
6
|
-
import { join } from "node:path";
|
|
7
4
|
import { homedir, tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
8
6
|
import process from "node:process";
|
|
7
|
+
import repl from "node:repl";
|
|
8
|
+
import jsonata from "jsonata";
|
|
9
9
|
|
|
10
|
-
import { createBom } from "../index.js";
|
|
11
|
-
import { validateBom } from "../validator.js";
|
|
12
10
|
import {
|
|
13
11
|
printCallStack,
|
|
14
12
|
printDependencyTree,
|
|
15
13
|
printOSTable,
|
|
16
14
|
printOccurrences,
|
|
17
15
|
printServices,
|
|
18
|
-
printTable
|
|
16
|
+
printTable,
|
|
19
17
|
} from "../display.js";
|
|
18
|
+
import { createBom } from "../index.js";
|
|
19
|
+
import { validateBom } from "../validator.js";
|
|
20
20
|
|
|
21
21
|
const options = {
|
|
22
22
|
useColors: true,
|
|
@@ -24,7 +24,7 @@ const options = {
|
|
|
24
24
|
preview: true,
|
|
25
25
|
prompt: "cdx ↝ ",
|
|
26
26
|
ignoreUndefined: true,
|
|
27
|
-
useGlobal: true
|
|
27
|
+
useGlobal: true,
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
// Use canonical terminal settings to support custom readlines
|
|
@@ -63,9 +63,7 @@ export const importSbom = (sbomOrPath) => {
|
|
|
63
63
|
sbom = JSON.parse(fs.readFileSync(sbomOrPath, "utf-8"));
|
|
64
64
|
console.log(`✅ SBOM imported successfully from ${sbomOrPath}`);
|
|
65
65
|
} catch (e) {
|
|
66
|
-
console.log(
|
|
67
|
-
`⚠ Unable to import the SBOM from ${sbomOrPath} due to ${e}`
|
|
68
|
-
);
|
|
66
|
+
console.log(`⚠ Unable to import the SBOM from ${sbomOrPath} due to ${e}`);
|
|
69
67
|
}
|
|
70
68
|
} else {
|
|
71
69
|
console.log(`⚠ ${sbomOrPath} is invalid.`);
|
|
@@ -91,10 +89,10 @@ if (historyFile) {
|
|
|
91
89
|
(err) => {
|
|
92
90
|
if (err) {
|
|
93
91
|
console.log(
|
|
94
|
-
"⚠ REPL history would not be persisted for this session. Set the environment variable CDXGEN_REPL_HISTORY to specify a custom history file"
|
|
92
|
+
"⚠ REPL history would not be persisted for this session. Set the environment variable CDXGEN_REPL_HISTORY to specify a custom history file",
|
|
95
93
|
);
|
|
96
94
|
}
|
|
97
|
-
}
|
|
95
|
+
},
|
|
98
96
|
);
|
|
99
97
|
}
|
|
100
98
|
cdxgenRepl.defineCommand("create", {
|
|
@@ -106,7 +104,7 @@ cdxgenRepl.defineCommand("create", {
|
|
|
106
104
|
const bomNSData = await createBom(sbomOrPath, {
|
|
107
105
|
multiProject: true,
|
|
108
106
|
installDeps: true,
|
|
109
|
-
output: bomFile
|
|
107
|
+
output: bomFile,
|
|
110
108
|
});
|
|
111
109
|
if (bomNSData) {
|
|
112
110
|
sbom = bomNSData.bomJson;
|
|
@@ -116,7 +114,7 @@ cdxgenRepl.defineCommand("create", {
|
|
|
116
114
|
console.log("BOM was not generated successfully");
|
|
117
115
|
}
|
|
118
116
|
this.displayPrompt();
|
|
119
|
-
}
|
|
117
|
+
},
|
|
120
118
|
});
|
|
121
119
|
cdxgenRepl.defineCommand("import", {
|
|
122
120
|
help: "import an existing BOM",
|
|
@@ -124,13 +122,13 @@ cdxgenRepl.defineCommand("import", {
|
|
|
124
122
|
this.clearBufferedCommand();
|
|
125
123
|
importSbom(sbomOrPath);
|
|
126
124
|
this.displayPrompt();
|
|
127
|
-
}
|
|
125
|
+
},
|
|
128
126
|
});
|
|
129
127
|
cdxgenRepl.defineCommand("exit", {
|
|
130
128
|
help: "exit",
|
|
131
129
|
action() {
|
|
132
130
|
this.close();
|
|
133
|
-
}
|
|
131
|
+
},
|
|
134
132
|
});
|
|
135
133
|
cdxgenRepl.defineCommand("sbom", {
|
|
136
134
|
help: "show the current sbom",
|
|
@@ -139,11 +137,11 @@ cdxgenRepl.defineCommand("sbom", {
|
|
|
139
137
|
console.log(sbom);
|
|
140
138
|
} else {
|
|
141
139
|
console.log(
|
|
142
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
140
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
143
141
|
);
|
|
144
142
|
}
|
|
145
143
|
this.displayPrompt();
|
|
146
|
-
}
|
|
144
|
+
},
|
|
147
145
|
});
|
|
148
146
|
cdxgenRepl.defineCommand("search", {
|
|
149
147
|
help: "search the current bom. performs case insensitive search on various attributes.",
|
|
@@ -165,17 +163,15 @@ cdxgenRepl.defineCommand("search", {
|
|
|
165
163
|
console.log(e);
|
|
166
164
|
}
|
|
167
165
|
} else {
|
|
168
|
-
console.log(
|
|
169
|
-
"⚠ Specify the search string. Eg: .search <search string>"
|
|
170
|
-
);
|
|
166
|
+
console.log("⚠ Specify the search string. Eg: .search <search string>");
|
|
171
167
|
}
|
|
172
168
|
} else {
|
|
173
169
|
console.log(
|
|
174
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
170
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
175
171
|
);
|
|
176
172
|
}
|
|
177
173
|
this.displayPrompt();
|
|
178
|
-
}
|
|
174
|
+
},
|
|
179
175
|
});
|
|
180
176
|
cdxgenRepl.defineCommand("sort", {
|
|
181
177
|
help: "sort the current bom based on the attribute",
|
|
@@ -205,11 +201,11 @@ cdxgenRepl.defineCommand("sort", {
|
|
|
205
201
|
}
|
|
206
202
|
} else {
|
|
207
203
|
console.log(
|
|
208
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
204
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
209
205
|
);
|
|
210
206
|
}
|
|
211
207
|
this.displayPrompt();
|
|
212
|
-
}
|
|
208
|
+
},
|
|
213
209
|
});
|
|
214
210
|
cdxgenRepl.defineCommand("query", {
|
|
215
211
|
help: "query the current bom using jsonata expression",
|
|
@@ -224,16 +220,16 @@ cdxgenRepl.defineCommand("query", {
|
|
|
224
220
|
}
|
|
225
221
|
} else {
|
|
226
222
|
console.log(
|
|
227
|
-
"⚠ Specify the search specification in jsonata format. Eg: .query metadata.component"
|
|
223
|
+
"⚠ Specify the search specification in jsonata format. Eg: .query metadata.component",
|
|
228
224
|
);
|
|
229
225
|
}
|
|
230
226
|
} else {
|
|
231
227
|
console.log(
|
|
232
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
228
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
233
229
|
);
|
|
234
230
|
}
|
|
235
231
|
this.displayPrompt();
|
|
236
|
-
}
|
|
232
|
+
},
|
|
237
233
|
});
|
|
238
234
|
cdxgenRepl.defineCommand("print", {
|
|
239
235
|
help: "print the current bom as a table",
|
|
@@ -242,11 +238,11 @@ cdxgenRepl.defineCommand("print", {
|
|
|
242
238
|
printTable(sbom);
|
|
243
239
|
} else {
|
|
244
240
|
console.log(
|
|
245
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
241
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
246
242
|
);
|
|
247
243
|
}
|
|
248
244
|
this.displayPrompt();
|
|
249
|
-
}
|
|
245
|
+
},
|
|
250
246
|
});
|
|
251
247
|
cdxgenRepl.defineCommand("tree", {
|
|
252
248
|
help: "display the dependency tree",
|
|
@@ -255,11 +251,11 @@ cdxgenRepl.defineCommand("tree", {
|
|
|
255
251
|
printDependencyTree(sbom);
|
|
256
252
|
} else {
|
|
257
253
|
console.log(
|
|
258
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
254
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
259
255
|
);
|
|
260
256
|
}
|
|
261
257
|
this.displayPrompt();
|
|
262
|
-
}
|
|
258
|
+
},
|
|
263
259
|
});
|
|
264
260
|
cdxgenRepl.defineCommand("validate", {
|
|
265
261
|
help: "validate the bom using jsonschema",
|
|
@@ -271,11 +267,11 @@ cdxgenRepl.defineCommand("validate", {
|
|
|
271
267
|
}
|
|
272
268
|
} else {
|
|
273
269
|
console.log(
|
|
274
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
270
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
275
271
|
);
|
|
276
272
|
}
|
|
277
273
|
this.displayPrompt();
|
|
278
|
-
}
|
|
274
|
+
},
|
|
279
275
|
});
|
|
280
276
|
cdxgenRepl.defineCommand("save", {
|
|
281
277
|
help: "save the bom to a new file",
|
|
@@ -288,11 +284,11 @@ cdxgenRepl.defineCommand("save", {
|
|
|
288
284
|
console.log(`BOM saved successfully to ${saveToFile}`);
|
|
289
285
|
} else {
|
|
290
286
|
console.log(
|
|
291
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
287
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
292
288
|
);
|
|
293
289
|
}
|
|
294
290
|
this.displayPrompt();
|
|
295
|
-
}
|
|
291
|
+
},
|
|
296
292
|
});
|
|
297
293
|
cdxgenRepl.defineCommand("update", {
|
|
298
294
|
help: "update the bom components based on the given query",
|
|
@@ -316,11 +312,11 @@ cdxgenRepl.defineCommand("update", {
|
|
|
316
312
|
console.log("BOM updated successfully.");
|
|
317
313
|
} else {
|
|
318
314
|
console.log(
|
|
319
|
-
"⚠ No BOM is loaded. Use .import command to import an existing BOM"
|
|
315
|
+
"⚠ No BOM is loaded. Use .import command to import an existing BOM",
|
|
320
316
|
);
|
|
321
317
|
}
|
|
322
318
|
this.displayPrompt();
|
|
323
|
-
}
|
|
319
|
+
},
|
|
324
320
|
});
|
|
325
321
|
cdxgenRepl.defineCommand("occurrences", {
|
|
326
322
|
help: "view components with evidence.occurrences",
|
|
@@ -328,12 +324,12 @@ cdxgenRepl.defineCommand("occurrences", {
|
|
|
328
324
|
if (sbom) {
|
|
329
325
|
try {
|
|
330
326
|
const expression = jsonata(
|
|
331
|
-
"components[$count(evidence.occurrences) > 0]"
|
|
327
|
+
"components[$count(evidence.occurrences) > 0]",
|
|
332
328
|
);
|
|
333
329
|
let components = await expression.evaluate(sbom);
|
|
334
330
|
if (!components) {
|
|
335
331
|
console.log(
|
|
336
|
-
"No results found. Use evinse command to generate an BOM with evidence."
|
|
332
|
+
"No results found. Use evinse command to generate an BOM with evidence.",
|
|
337
333
|
);
|
|
338
334
|
} else {
|
|
339
335
|
if (!Array.isArray(components)) {
|
|
@@ -346,27 +342,27 @@ cdxgenRepl.defineCommand("occurrences", {
|
|
|
346
342
|
}
|
|
347
343
|
} else {
|
|
348
344
|
console.log(
|
|
349
|
-
"⚠ No BOM is loaded. Use .import command to import an evinse BOM"
|
|
345
|
+
"⚠ No BOM is loaded. Use .import command to import an evinse BOM",
|
|
350
346
|
);
|
|
351
347
|
}
|
|
352
348
|
this.displayPrompt();
|
|
353
|
-
}
|
|
349
|
+
},
|
|
354
350
|
});
|
|
355
351
|
cdxgenRepl.defineCommand("discord", {
|
|
356
352
|
help: "display the discord invite link for support",
|
|
357
353
|
action() {
|
|
358
354
|
console.log("Head to https://discord.gg/pF4BYWEJcS for support");
|
|
359
355
|
this.displayPrompt();
|
|
360
|
-
}
|
|
356
|
+
},
|
|
361
357
|
});
|
|
362
358
|
cdxgenRepl.defineCommand("sponsor", {
|
|
363
359
|
help: "display the sponsorship link to fund this project",
|
|
364
360
|
action() {
|
|
365
361
|
console.log(
|
|
366
|
-
"Hey, thanks a lot for considering! https://github.com/sponsors/prabhu"
|
|
362
|
+
"Hey, thanks a lot for considering! https://github.com/sponsors/prabhu",
|
|
367
363
|
);
|
|
368
364
|
this.displayPrompt();
|
|
369
|
-
}
|
|
365
|
+
},
|
|
370
366
|
});
|
|
371
367
|
cdxgenRepl.defineCommand("callstack", {
|
|
372
368
|
help: "view components with evidence.callstack",
|
|
@@ -374,12 +370,12 @@ cdxgenRepl.defineCommand("callstack", {
|
|
|
374
370
|
if (sbom) {
|
|
375
371
|
try {
|
|
376
372
|
const expression = jsonata(
|
|
377
|
-
"components[$count(evidence.callstack.frames) > 0]"
|
|
373
|
+
"components[$count(evidence.callstack.frames) > 0]",
|
|
378
374
|
);
|
|
379
375
|
let components = await expression.evaluate(sbom);
|
|
380
376
|
if (!components) {
|
|
381
377
|
console.log(
|
|
382
|
-
"callstack evidence was not found. Use evinse command to generate an SBOM with evidence."
|
|
378
|
+
"callstack evidence was not found. Use evinse command to generate an SBOM with evidence.",
|
|
383
379
|
);
|
|
384
380
|
} else {
|
|
385
381
|
if (!Array.isArray(components)) {
|
|
@@ -392,11 +388,11 @@ cdxgenRepl.defineCommand("callstack", {
|
|
|
392
388
|
}
|
|
393
389
|
} else {
|
|
394
390
|
console.log(
|
|
395
|
-
"⚠ No SBOM is loaded. Use .import command to import an evinse SBOM"
|
|
391
|
+
"⚠ No SBOM is loaded. Use .import command to import an evinse SBOM",
|
|
396
392
|
);
|
|
397
393
|
}
|
|
398
394
|
this.displayPrompt();
|
|
399
|
-
}
|
|
395
|
+
},
|
|
400
396
|
});
|
|
401
397
|
cdxgenRepl.defineCommand("services", {
|
|
402
398
|
help: "view services",
|
|
@@ -407,7 +403,7 @@ cdxgenRepl.defineCommand("services", {
|
|
|
407
403
|
let services = await expression.evaluate(sbom);
|
|
408
404
|
if (!services) {
|
|
409
405
|
console.log(
|
|
410
|
-
"No services found. Use evinse command to generate an SBOM with evidence."
|
|
406
|
+
"No services found. Use evinse command to generate an SBOM with evidence.",
|
|
411
407
|
);
|
|
412
408
|
} else {
|
|
413
409
|
if (!Array.isArray(services)) {
|
|
@@ -420,11 +416,11 @@ cdxgenRepl.defineCommand("services", {
|
|
|
420
416
|
}
|
|
421
417
|
} else {
|
|
422
418
|
console.log(
|
|
423
|
-
"⚠ No SBOM is loaded. Use .import command to import an evinse SBOM"
|
|
419
|
+
"⚠ No SBOM is loaded. Use .import command to import an evinse SBOM",
|
|
424
420
|
);
|
|
425
421
|
}
|
|
426
422
|
this.displayPrompt();
|
|
427
|
-
}
|
|
423
|
+
},
|
|
428
424
|
});
|
|
429
425
|
cdxgenRepl.defineCommand("osinfocategories", {
|
|
430
426
|
help: "view the category names for the OS info from the obom",
|
|
@@ -432,12 +428,12 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
432
428
|
if (sbom) {
|
|
433
429
|
try {
|
|
434
430
|
const expression = jsonata(
|
|
435
|
-
'$distinct(components.properties[name="cdx:osquery:category"].value)'
|
|
431
|
+
'$distinct(components.properties[name="cdx:osquery:category"].value)',
|
|
436
432
|
);
|
|
437
433
|
const catgories = await expression.evaluate(sbom);
|
|
438
434
|
if (!catgories) {
|
|
439
435
|
console.log(
|
|
440
|
-
"Unable to retrieve the os info categories. Only OBOMs generated by cdxgen are supported by this tool."
|
|
436
|
+
"Unable to retrieve the os info categories. Only OBOMs generated by cdxgen are supported by this tool.",
|
|
441
437
|
);
|
|
442
438
|
} else {
|
|
443
439
|
console.log(catgories.join("\n"));
|
|
@@ -446,12 +442,10 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
446
442
|
console.log(e);
|
|
447
443
|
}
|
|
448
444
|
} else {
|
|
449
|
-
console.log(
|
|
450
|
-
"⚠ No OBOM is loaded. Use .import command to import an OBOM"
|
|
451
|
-
);
|
|
445
|
+
console.log("⚠ No OBOM is loaded. Use .import command to import an OBOM");
|
|
452
446
|
}
|
|
453
447
|
this.displayPrompt();
|
|
454
|
-
}
|
|
448
|
+
},
|
|
455
449
|
});
|
|
456
450
|
|
|
457
451
|
// Let's dynamically define more commands from the queries
|
|
@@ -522,7 +516,7 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
522
516
|
"wmi_cli_event_consumers",
|
|
523
517
|
"wmi_cli_event_consumers_snapshot",
|
|
524
518
|
"wmi_event_filters",
|
|
525
|
-
"wmi_filter_consumer_binding"
|
|
519
|
+
"wmi_filter_consumer_binding",
|
|
526
520
|
].forEach((c) => {
|
|
527
521
|
cdxgenRepl.defineCommand(c, {
|
|
528
522
|
help: `query the ${c} category from the OS info`,
|
|
@@ -530,7 +524,7 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
530
524
|
if (sbom) {
|
|
531
525
|
try {
|
|
532
526
|
const expression = jsonata(
|
|
533
|
-
`components[properties[name="cdx:osquery:category" and value="${c}"]]
|
|
527
|
+
`components[properties[name="cdx:osquery:category" and value="${c}"]]`,
|
|
534
528
|
);
|
|
535
529
|
let components = await expression.evaluate(sbom);
|
|
536
530
|
if (!components) {
|
|
@@ -546,10 +540,10 @@ cdxgenRepl.defineCommand("osinfocategories", {
|
|
|
546
540
|
}
|
|
547
541
|
} else {
|
|
548
542
|
console.log(
|
|
549
|
-
"⚠ No OBOM is loaded. Use .import command to import an OBOM"
|
|
543
|
+
"⚠ No OBOM is loaded. Use .import command to import an OBOM",
|
|
550
544
|
);
|
|
551
545
|
}
|
|
552
546
|
this.displayPrompt();
|
|
553
|
-
}
|
|
547
|
+
},
|
|
554
548
|
});
|
|
555
549
|
});
|
package/bin/verify.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import yargs from "yargs";
|
|
4
|
-
import { hideBin } from "yargs/helpers";
|
|
5
3
|
import fs from "node:fs";
|
|
6
|
-
import
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
7
5
|
import process from "node:process";
|
|
8
6
|
import { URL, fileURLToPath } from "node:url";
|
|
9
|
-
import
|
|
7
|
+
import jws from "jws";
|
|
8
|
+
import yargs from "yargs";
|
|
9
|
+
import { hideBin } from "yargs/helpers";
|
|
10
10
|
|
|
11
11
|
let url = import.meta.url;
|
|
12
12
|
if (!url.startsWith("file://")) {
|
|
@@ -18,11 +18,11 @@ const args = yargs(hideBin(process.argv))
|
|
|
18
18
|
.option("input", {
|
|
19
19
|
alias: "i",
|
|
20
20
|
default: "bom.json",
|
|
21
|
-
description: "Input json to validate. Default bom.json"
|
|
21
|
+
description: "Input json to validate. Default bom.json",
|
|
22
22
|
})
|
|
23
23
|
.option("public-key", {
|
|
24
24
|
default: "public.key",
|
|
25
|
-
description: "Public key in PEM format. Default public.key"
|
|
25
|
+
description: "Public key in PEM format. Default public.key",
|
|
26
26
|
})
|
|
27
27
|
.completion("completion", "Generate bash/zsh completion")
|
|
28
28
|
.epilogue("for documentation, visit https://cyclonedx.github.io/cdxgen")
|
|
@@ -33,7 +33,7 @@ const args = yargs(hideBin(process.argv))
|
|
|
33
33
|
if (args.version) {
|
|
34
34
|
const packageJsonAsString = fs.readFileSync(
|
|
35
35
|
join(dirName, "..", "package.json"),
|
|
36
|
-
"utf-8"
|
|
36
|
+
"utf-8",
|
|
37
37
|
);
|
|
38
38
|
const packageJson = JSON.parse(packageJsonAsString);
|
|
39
39
|
|
|
@@ -50,7 +50,7 @@ for (const comp of bomJson.components) {
|
|
|
50
50
|
const validationResult = jws.verify(
|
|
51
51
|
compSignature,
|
|
52
52
|
comp.signature.algorithm,
|
|
53
|
-
fs.readFileSync(args.publicKey, "utf8")
|
|
53
|
+
fs.readFileSync(args.publicKey, "utf8"),
|
|
54
54
|
);
|
|
55
55
|
if (!validationResult) {
|
|
56
56
|
console.log(`${comp["bom-ref"]} signature is invalid!`);
|
|
@@ -71,7 +71,7 @@ if (!bomSignature) {
|
|
|
71
71
|
const validationResult = jws.verify(
|
|
72
72
|
bomSignature,
|
|
73
73
|
bomJson.signature.algorithm,
|
|
74
|
-
fs.readFileSync(args.publicKey, "utf8")
|
|
74
|
+
fs.readFileSync(args.publicKey, "utf8"),
|
|
75
75
|
);
|
|
76
76
|
if (validationResult) {
|
|
77
77
|
console.log("Signature is valid!");
|