@cyclonedx/cdxgen 12.3.2 → 12.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.
Files changed (182) hide show
  1. package/README.md +70 -22
  2. package/bin/audit.js +21 -7
  3. package/bin/cdxgen.js +238 -116
  4. package/bin/convert.js +28 -13
  5. package/bin/hbom.js +490 -0
  6. package/bin/repl.js +580 -29
  7. package/bin/validate.js +34 -4
  8. package/bin/verify.js +40 -5
  9. package/data/README.md +298 -25
  10. package/data/component-tags.json +6 -0
  11. package/data/crypto-oid.json +16 -0
  12. package/data/predictive-audit-allowlist.json +11 -0
  13. package/data/queries-darwin.json +12 -1
  14. package/data/queries-win.json +7 -1
  15. package/data/queries.json +39 -2
  16. package/data/rules/ai-agent-governance.yaml +16 -0
  17. package/data/rules/asar-archives.yaml +150 -0
  18. package/data/rules/chrome-extensions.yaml +8 -0
  19. package/data/rules/ci-permissions.yaml +171 -15
  20. package/data/rules/container-risk.yaml +14 -7
  21. package/data/rules/dependency-sources.yaml +76 -5
  22. package/data/rules/hbom-compliance.yaml +325 -0
  23. package/data/rules/hbom-performance.yaml +307 -0
  24. package/data/rules/hbom-security.yaml +248 -0
  25. package/data/rules/host-topology.yaml +165 -0
  26. package/data/rules/mcp-servers.yaml +18 -3
  27. package/data/rules/obom-runtime.yaml +907 -22
  28. package/data/rules/package-integrity.yaml +36 -0
  29. package/data/rules/rootfs-hardening.yaml +179 -0
  30. package/data/rules/vscode-extensions.yaml +9 -0
  31. package/lib/audit/index.js +209 -8
  32. package/lib/audit/index.poku.js +332 -0
  33. package/lib/audit/reporters.js +222 -0
  34. package/lib/audit/targets.js +146 -1
  35. package/lib/audit/targets.poku.js +186 -0
  36. package/lib/cli/asar.poku.js +328 -0
  37. package/lib/cli/index.js +647 -127
  38. package/lib/cli/index.poku.js +1905 -187
  39. package/lib/evinser/evinser.js +14 -9
  40. package/lib/helpers/agentFormulationParser.js +6 -2
  41. package/lib/helpers/agentFormulationParser.poku.js +42 -0
  42. package/lib/helpers/analyzer.js +1444 -38
  43. package/lib/helpers/analyzer.poku.js +409 -0
  44. package/lib/helpers/analyzerScope.js +712 -0
  45. package/lib/helpers/asarutils.js +1556 -0
  46. package/lib/helpers/asarutils.poku.js +443 -0
  47. package/lib/helpers/auditCategories.js +12 -0
  48. package/lib/helpers/auditCategories.poku.js +32 -0
  49. package/lib/helpers/cbomutils.js +271 -1
  50. package/lib/helpers/cbomutils.poku.js +248 -5
  51. package/lib/helpers/chromextutils.js +25 -3
  52. package/lib/helpers/chromextutils.poku.js +68 -0
  53. package/lib/helpers/ciParsers/githubActions.js +79 -0
  54. package/lib/helpers/ciParsers/githubActions.poku.js +103 -0
  55. package/lib/helpers/communityAiConfigParser.js +15 -5
  56. package/lib/helpers/communityAiConfigParser.poku.js +71 -0
  57. package/lib/helpers/depsUtils.js +5 -0
  58. package/lib/helpers/depsUtils.poku.js +55 -0
  59. package/lib/helpers/display.js +336 -23
  60. package/lib/helpers/display.poku.js +179 -43
  61. package/lib/helpers/evidenceUtils.js +58 -0
  62. package/lib/helpers/evidenceUtils.poku.js +54 -0
  63. package/lib/helpers/exportUtils.js +9 -0
  64. package/lib/helpers/gtfobins.js +142 -8
  65. package/lib/helpers/gtfobins.poku.js +24 -1
  66. package/lib/helpers/hbom.js +710 -0
  67. package/lib/helpers/hbom.poku.js +496 -0
  68. package/lib/helpers/hbomAnalysis.js +268 -0
  69. package/lib/helpers/hbomAnalysis.poku.js +249 -0
  70. package/lib/helpers/hbomLoader.js +35 -0
  71. package/lib/helpers/hostTopology.js +803 -0
  72. package/lib/helpers/hostTopology.poku.js +363 -0
  73. package/lib/helpers/inventoryStats.js +69 -0
  74. package/lib/helpers/inventoryStats.poku.js +86 -0
  75. package/lib/helpers/lolbas.js +19 -1
  76. package/lib/helpers/lolbas.poku.js +23 -0
  77. package/lib/helpers/mcpConfigParser.js +21 -5
  78. package/lib/helpers/mcpConfigParser.poku.js +39 -2
  79. package/lib/helpers/osqueryTransform.js +47 -0
  80. package/lib/helpers/osqueryTransform.poku.js +47 -0
  81. package/lib/helpers/plugins.js +349 -0
  82. package/lib/helpers/plugins.poku.js +57 -0
  83. package/lib/helpers/propertySanitizer.js +121 -0
  84. package/lib/helpers/protobom.js +156 -45
  85. package/lib/helpers/protobom.poku.js +140 -5
  86. package/lib/helpers/remote/dependency-track.js +36 -3
  87. package/lib/helpers/remote/dependency-track.poku.js +44 -0
  88. package/lib/helpers/source.js +24 -0
  89. package/lib/helpers/source.poku.js +32 -0
  90. package/lib/helpers/utils.js +2454 -198
  91. package/lib/helpers/utils.poku.js +1798 -74
  92. package/lib/managers/binary.e2e.poku.js +367 -0
  93. package/lib/managers/binary.js +2306 -350
  94. package/lib/managers/binary.poku.js +1700 -1
  95. package/lib/managers/docker.js +441 -95
  96. package/lib/managers/docker.poku.js +1479 -14
  97. package/lib/server/server.js +2 -24
  98. package/lib/server/server.poku.js +36 -1
  99. package/lib/stages/postgen/annotator.js +38 -0
  100. package/lib/stages/postgen/annotator.poku.js +107 -1
  101. package/lib/stages/postgen/auditBom.js +121 -18
  102. package/lib/stages/postgen/auditBom.poku.js +2967 -990
  103. package/lib/stages/postgen/hostTopologyAudit.poku.js +186 -0
  104. package/lib/stages/postgen/postgen.js +192 -1
  105. package/lib/stages/postgen/postgen.poku.js +321 -0
  106. package/lib/stages/postgen/ruleEngine.js +116 -0
  107. package/lib/stages/pregen/envAudit.js +14 -3
  108. package/package.json +24 -21
  109. package/types/bin/hbom.d.ts +3 -0
  110. package/types/bin/hbom.d.ts.map +1 -0
  111. package/types/bin/repl.d.ts.map +1 -1
  112. package/types/lib/audit/index.d.ts +44 -0
  113. package/types/lib/audit/index.d.ts.map +1 -1
  114. package/types/lib/audit/reporters.d.ts +16 -0
  115. package/types/lib/audit/reporters.d.ts.map +1 -1
  116. package/types/lib/audit/targets.d.ts.map +1 -1
  117. package/types/lib/cli/index.d.ts +16 -0
  118. package/types/lib/cli/index.d.ts.map +1 -1
  119. package/types/lib/evinser/evinser.d.ts +4 -0
  120. package/types/lib/evinser/evinser.d.ts.map +1 -1
  121. package/types/lib/helpers/agentFormulationParser.d.ts.map +1 -1
  122. package/types/lib/helpers/analyzer.d.ts +33 -0
  123. package/types/lib/helpers/analyzer.d.ts.map +1 -1
  124. package/types/lib/helpers/analyzerScope.d.ts +11 -0
  125. package/types/lib/helpers/analyzerScope.d.ts.map +1 -0
  126. package/types/lib/helpers/asarutils.d.ts +34 -0
  127. package/types/lib/helpers/asarutils.d.ts.map +1 -0
  128. package/types/lib/helpers/auditCategories.d.ts +5 -0
  129. package/types/lib/helpers/auditCategories.d.ts.map +1 -1
  130. package/types/lib/helpers/cbomutils.d.ts +3 -2
  131. package/types/lib/helpers/cbomutils.d.ts.map +1 -1
  132. package/types/lib/helpers/chromextutils.d.ts.map +1 -1
  133. package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
  134. package/types/lib/helpers/communityAiConfigParser.d.ts.map +1 -1
  135. package/types/lib/helpers/depsUtils.d.ts.map +1 -1
  136. package/types/lib/helpers/display.d.ts +1 -0
  137. package/types/lib/helpers/display.d.ts.map +1 -1
  138. package/types/lib/helpers/evidenceUtils.d.ts +8 -0
  139. package/types/lib/helpers/evidenceUtils.d.ts.map +1 -0
  140. package/types/lib/helpers/exportUtils.d.ts.map +1 -1
  141. package/types/lib/helpers/gtfobins.d.ts +8 -0
  142. package/types/lib/helpers/gtfobins.d.ts.map +1 -1
  143. package/types/lib/helpers/hbom.d.ts +49 -0
  144. package/types/lib/helpers/hbom.d.ts.map +1 -0
  145. package/types/lib/helpers/hbomAnalysis.d.ts +62 -0
  146. package/types/lib/helpers/hbomAnalysis.d.ts.map +1 -0
  147. package/types/lib/helpers/hbomLoader.d.ts +7 -0
  148. package/types/lib/helpers/hbomLoader.d.ts.map +1 -0
  149. package/types/lib/helpers/hostTopology.d.ts +12 -0
  150. package/types/lib/helpers/hostTopology.d.ts.map +1 -0
  151. package/types/lib/helpers/inventoryStats.d.ts +11 -0
  152. package/types/lib/helpers/inventoryStats.d.ts.map +1 -0
  153. package/types/lib/helpers/lolbas.d.ts.map +1 -1
  154. package/types/lib/helpers/mcpConfigParser.d.ts +1 -1
  155. package/types/lib/helpers/mcpConfigParser.d.ts.map +1 -1
  156. package/types/lib/helpers/osqueryTransform.d.ts +3 -0
  157. package/types/lib/helpers/osqueryTransform.d.ts.map +1 -1
  158. package/types/lib/helpers/plugins.d.ts +58 -0
  159. package/types/lib/helpers/plugins.d.ts.map +1 -0
  160. package/types/lib/helpers/propertySanitizer.d.ts +3 -0
  161. package/types/lib/helpers/propertySanitizer.d.ts.map +1 -0
  162. package/types/lib/helpers/protobom.d.ts +3 -4
  163. package/types/lib/helpers/protobom.d.ts.map +1 -1
  164. package/types/lib/helpers/remote/dependency-track.d.ts +10 -3
  165. package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -1
  166. package/types/lib/helpers/source.d.ts.map +1 -1
  167. package/types/lib/helpers/utils.d.ts +74 -8
  168. package/types/lib/helpers/utils.d.ts.map +1 -1
  169. package/types/lib/managers/binary.d.ts +5 -0
  170. package/types/lib/managers/binary.d.ts.map +1 -1
  171. package/types/lib/managers/docker.d.ts +3 -0
  172. package/types/lib/managers/docker.d.ts.map +1 -1
  173. package/types/lib/server/server.d.ts +2 -0
  174. package/types/lib/server/server.d.ts.map +1 -1
  175. package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
  176. package/types/lib/stages/postgen/auditBom.d.ts +26 -1
  177. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
  178. package/types/lib/stages/postgen/postgen.d.ts +2 -1
  179. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  180. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
  181. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -1
  182. package/data/spdx-model-v3.0.1.jsonld +0 -15999
@@ -0,0 +1,367 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import process from "node:process";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+
8
+ import { assert, it } from "poku";
9
+
10
+ const managersDir = path.dirname(fileURLToPath(import.meta.url));
11
+ const cdxgenRoot = path.resolve(managersDir, "../..");
12
+ const pluginsRepoRoot = [
13
+ path.resolve(cdxgenRoot, ".."),
14
+ path.resolve(cdxgenRoot, "../cdxgen-plugins-bin"),
15
+ path.resolve(process.cwd(), ".."),
16
+ path.resolve(process.cwd(), "../cdxgen-plugins-bin"),
17
+ ].find((candidate) =>
18
+ existsSync(path.join(candidate, "thirdparty", "trivy", "main.go")),
19
+ );
20
+ const trivySourceDir = pluginsRepoRoot
21
+ ? path.join(pluginsRepoRoot, "thirdparty", "trivy")
22
+ : undefined;
23
+ const trustInspectorSourceDir = pluginsRepoRoot
24
+ ? path.join(pluginsRepoRoot, "thirdparty", "trustinspector")
25
+ : undefined;
26
+ const nerdctlPath =
27
+ process.env.CDXGEN_NERDCTL_PATH || "/Users/prabhu/.rd/bin/nerdctl";
28
+
29
+ function quoteForShell(value) {
30
+ return `'${String(value).replace(/'/g, `'"'"'`)}'`;
31
+ }
32
+
33
+ function runCommand(command, args, options = {}) {
34
+ const result = spawnSync(command, args, {
35
+ encoding: "utf-8",
36
+ maxBuffer: 20 * 1024 * 1024,
37
+ ...options,
38
+ });
39
+ if (result.status !== 0) {
40
+ throw new Error(
41
+ `${command} ${args.join(" ")} failed with status ${result.status}: ${result.stderr || result.stdout}`,
42
+ );
43
+ }
44
+ return result;
45
+ }
46
+
47
+ function buildTrivyBinary() {
48
+ const outputDir = mkdtempSync(path.join(tmpdir(), "trivy-cdxgen-bin-"));
49
+ const outputPath = path.join(outputDir, "trivy-cdxgen-test");
50
+ runCommand(
51
+ "bash",
52
+ ["-lc", `GOEXPERIMENT=jsonv2 go build -o ${quoteForShell(outputPath)}`],
53
+ {
54
+ cwd: trivySourceDir,
55
+ env: process.env,
56
+ },
57
+ );
58
+ return outputPath;
59
+ }
60
+
61
+ function buildTrustInspectorBinary() {
62
+ const outputDir = mkdtempSync(
63
+ path.join(tmpdir(), "trustinspector-cdxgen-bin-"),
64
+ );
65
+ const outputPath = path.join(outputDir, "trustinspector-cdxgen-test");
66
+ runCommand("go", ["build", "-o", outputPath], {
67
+ cwd: trustInspectorSourceDir,
68
+ env: process.env,
69
+ });
70
+ return outputPath;
71
+ }
72
+
73
+ function exportRootfsWithNerdctl(image, options = {}) {
74
+ const rootfsDir = mkdtempSync(path.join(tmpdir(), "cdxgen-rootfs-e2e-"));
75
+ const shellScript = [
76
+ "set -euo pipefail",
77
+ ...(options.skipPull
78
+ ? []
79
+ : [
80
+ `${quoteForShell(nerdctlPath)} pull ${quoteForShell(image)} >/dev/null`,
81
+ ]),
82
+ `cid=$(${quoteForShell(nerdctlPath)} create ${quoteForShell(image)})`,
83
+ `trap '${quoteForShell(nerdctlPath)} rm -f "$cid" >/dev/null 2>&1 || true' EXIT`,
84
+ `${quoteForShell(nerdctlPath)} export "$cid" | tar -xf - -C ${quoteForShell(rootfsDir)}`,
85
+ `${quoteForShell(nerdctlPath)} rm -f "$cid" >/dev/null 2>&1 || true`,
86
+ ].join("\n");
87
+ runCommand("bash", ["-lc", shellScript]);
88
+ return rootfsDir;
89
+ }
90
+
91
+ function buildImageWithNerdctl(tag, dockerfileContents) {
92
+ const buildContextDir = mkdtempSync(path.join(tmpdir(), "cdxgen-image-e2e-"));
93
+ writeFileSync(path.join(buildContextDir, "Dockerfile"), dockerfileContents);
94
+ runCommand(nerdctlPath, ["build", "-t", tag, buildContextDir]);
95
+ return buildContextDir;
96
+ }
97
+
98
+ function createTrustInspectorPluginsDir() {
99
+ const pluginsDir = mkdtempSync(path.join(tmpdir(), "cdxgen-empty-plugins-"));
100
+ writeFileSync(
101
+ path.join(pluginsDir, "plugins-manifest.json"),
102
+ JSON.stringify(
103
+ {
104
+ plugins: [
105
+ {
106
+ name: "trustinspector",
107
+ component: {
108
+ type: "application",
109
+ name: "trustinspector",
110
+ version: "2.1.0",
111
+ purl: "pkg:generic/github.com/cdxgen/cdxgen-plugins-bin/trustinspector-cdxgen@2.1.0",
112
+ "bom-ref":
113
+ "pkg:generic/github.com/cdxgen/cdxgen-plugins-bin/trustinspector-cdxgen@2.1.0",
114
+ },
115
+ },
116
+ ],
117
+ },
118
+ null,
119
+ 2,
120
+ ),
121
+ );
122
+ return pluginsDir;
123
+ }
124
+
125
+ async function importBinaryModule() {
126
+ return import(
127
+ `${pathToFileURL(path.join(managersDir, "binary.js")).href}?e2e=${Date.now()}`
128
+ );
129
+ }
130
+
131
+ function setTemporaryEnv(overrides) {
132
+ const previousEnv = {};
133
+ for (const [name, value] of Object.entries(overrides)) {
134
+ previousEnv[name] = process.env[name];
135
+ if (value === undefined) {
136
+ delete process.env[name];
137
+ continue;
138
+ }
139
+ process.env[name] = value;
140
+ }
141
+ return () => {
142
+ for (const [name, value] of Object.entries(previousEnv)) {
143
+ if (value === undefined) {
144
+ delete process.env[name];
145
+ continue;
146
+ }
147
+ process.env[name] = value;
148
+ }
149
+ };
150
+ }
151
+
152
+ function extractSrcFiles(components) {
153
+ return new Set(
154
+ (components || [])
155
+ .flatMap((component) => component.properties || [])
156
+ .filter((property) => property.name === "SrcFile")
157
+ .map((property) => property.value),
158
+ );
159
+ }
160
+
161
+ const canRunE2E = Boolean(pluginsRepoRoot) && existsSync(nerdctlPath);
162
+
163
+ await it("getOSPackages() end-to-end on alpine rootfs creates owned file components without duplicate unpackaged binaries", async () => {
164
+ if (!canRunE2E) {
165
+ return;
166
+ }
167
+ const trivyBinary = buildTrivyBinary();
168
+ const rootfsDir = exportRootfsWithNerdctl("docker.io/library/alpine:3.20");
169
+ const emptyPluginsDir = mkdtempSync(
170
+ path.join(tmpdir(), "cdxgen-empty-plugins-"),
171
+ );
172
+ const restoreEnv = setTemporaryEnv({
173
+ CDXGEN_PLUGINS_DIR: emptyPluginsDir,
174
+ TRIVY_CMD: trivyBinary,
175
+ });
176
+ try {
177
+ const { getOSPackages } = await importBinaryModule();
178
+ const result = await getOSPackages(rootfsDir, {
179
+ Env: [
180
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
181
+ ],
182
+ });
183
+
184
+ assert.ok(result.osPackages.length > 0);
185
+ assert.ok(result.osPackageFiles.length > 0);
186
+ assert.ok(
187
+ result.dependenciesList.some(
188
+ (dependency) =>
189
+ dependency.ref &&
190
+ Array.isArray(dependency.provides) &&
191
+ dependency.provides.length > 0,
192
+ ),
193
+ );
194
+ assert.ok(
195
+ result.osPackages.some((component) =>
196
+ (component.properties || []).some((property) =>
197
+ property.name.endsWith("Capability"),
198
+ ),
199
+ ),
200
+ );
201
+
202
+ const packagedFilePaths = extractSrcFiles(result.osPackageFiles);
203
+ for (const component of result.executables.concat(result.sharedLibs)) {
204
+ const srcFile = (component.properties || []).find(
205
+ (property) => property.name === "SrcFile",
206
+ )?.value;
207
+ assert.strictEqual(packagedFilePaths.has(srcFile), false);
208
+ }
209
+ } finally {
210
+ restoreEnv();
211
+ rmSync(emptyPluginsDir, { recursive: true, force: true });
212
+ rmSync(path.dirname(trivyBinary), { recursive: true, force: true });
213
+ rmSync(rootfsDir, { recursive: true, force: true });
214
+ }
215
+ });
216
+
217
+ await it("getOSPackages() end-to-end on debian rootfs surfaces dpkg capabilities", async () => {
218
+ if (!canRunE2E) {
219
+ return;
220
+ }
221
+ const trivyBinary = buildTrivyBinary();
222
+ const trustInspectorBinary = buildTrustInspectorBinary();
223
+ const rootfsDir = exportRootfsWithNerdctl("docker.io/library/debian:12-slim");
224
+ const emptyPluginsDir = createTrustInspectorPluginsDir();
225
+ const restoreEnv = setTemporaryEnv({
226
+ CDXGEN_PLUGINS_DIR: emptyPluginsDir,
227
+ TRIVY_CMD: trivyBinary,
228
+ TRUSTINSPECTOR_CMD: trustInspectorBinary,
229
+ });
230
+ try {
231
+ const { getOSPackages } = await importBinaryModule();
232
+ const result = await getOSPackages(rootfsDir, {
233
+ Env: [
234
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
235
+ ],
236
+ });
237
+
238
+ assert.ok(result.osPackages.length > 0);
239
+ assert.ok(
240
+ result.osPackages.some((component) =>
241
+ (component.properties || []).some((property) =>
242
+ property.name.endsWith("Capability"),
243
+ ),
244
+ ),
245
+ );
246
+ assert.ok(
247
+ result.osPackages.some(
248
+ (component) =>
249
+ component.supplier?.name ||
250
+ component.manufacturer?.name ||
251
+ (component.authors || []).length,
252
+ ),
253
+ );
254
+ assert.ok(
255
+ result.osPackages.some(
256
+ (component) =>
257
+ component.type === "data" &&
258
+ (component.properties || []).some(
259
+ (property) =>
260
+ property.name === "cdx:os:repo:type" &&
261
+ (property.value === "apt-source" ||
262
+ property.value === "ppa-source"),
263
+ ),
264
+ ),
265
+ );
266
+ assert.ok(
267
+ result.osPackages.some(
268
+ (component) =>
269
+ component.type === "cryptographic-asset" &&
270
+ component.cryptoProperties?.assetType === "related-crypto-material" &&
271
+ component.cryptoProperties?.relatedCryptoMaterialProperties?.type ===
272
+ "public-key",
273
+ ),
274
+ );
275
+ assert.ok(result.tools.some((tool) => tool.name === "trustinspector"));
276
+ assert.ok(
277
+ result.osPackages.some(
278
+ (component) =>
279
+ component.type === "cryptographic-asset" &&
280
+ (component.properties || []).some(
281
+ (property) =>
282
+ property.name === "cdx:crypto:sourceType" &&
283
+ property.value === "repository-keyring",
284
+ ),
285
+ ),
286
+ );
287
+ } finally {
288
+ restoreEnv();
289
+ rmSync(emptyPluginsDir, { recursive: true, force: true });
290
+ rmSync(path.dirname(trivyBinary), { recursive: true, force: true });
291
+ rmSync(path.dirname(trustInspectorBinary), {
292
+ recursive: true,
293
+ force: true,
294
+ });
295
+ rmSync(rootfsDir, { recursive: true, force: true });
296
+ }
297
+ });
298
+
299
+ await it("getOSPackages() end-to-end on ubuntu rootfs with ca-certificates emits certificate crypto assets", async () => {
300
+ if (!canRunE2E) {
301
+ return;
302
+ }
303
+ const trivyBinary = buildTrivyBinary();
304
+ const trustInspectorBinary = buildTrustInspectorBinary();
305
+ const emptyPluginsDir = createTrustInspectorPluginsDir();
306
+ const imageTag = `cdxgen-e2e-cert-${Date.now()}`;
307
+ const buildContextDir = buildImageWithNerdctl(
308
+ imageTag,
309
+ [
310
+ "FROM docker.io/library/ubuntu:24.04",
311
+ "RUN apt-get update && \\",
312
+ " DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ca-certificates && \\",
313
+ " rm -rf /var/lib/apt/lists/*",
314
+ ].join("\n"),
315
+ );
316
+ const rootfsDir = exportRootfsWithNerdctl(imageTag, { skipPull: true });
317
+ const restoreEnv = setTemporaryEnv({
318
+ CDXGEN_PLUGINS_DIR: emptyPluginsDir,
319
+ TRIVY_CMD: trivyBinary,
320
+ TRUSTINSPECTOR_CMD: trustInspectorBinary,
321
+ });
322
+ try {
323
+ const { getOSPackages } = await importBinaryModule();
324
+ const result = await getOSPackages(rootfsDir, {
325
+ Env: [
326
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
327
+ ],
328
+ });
329
+
330
+ const certificateAssets = result.osPackages.filter(
331
+ (component) =>
332
+ component.type === "cryptographic-asset" &&
333
+ component.cryptoProperties?.assetType === "certificate",
334
+ );
335
+ assert.ok(certificateAssets.length > 0);
336
+ assert.ok(result.tools.some((tool) => tool.name === "trustinspector"));
337
+ assert.ok(
338
+ certificateAssets.some(
339
+ (component) =>
340
+ (component.properties || []).some(
341
+ (property) => property.name === "SrcFile",
342
+ ) && component.cryptoProperties?.certificateProperties?.subjectName,
343
+ ),
344
+ );
345
+ assert.ok(
346
+ certificateAssets.some(
347
+ (component) =>
348
+ component.cryptoProperties?.certificateProperties
349
+ ?.certificateFormat === "X.509",
350
+ ),
351
+ );
352
+ } finally {
353
+ restoreEnv();
354
+ spawnSync(nerdctlPath, ["rmi", "-f", imageTag], {
355
+ encoding: "utf-8",
356
+ maxBuffer: 20 * 1024 * 1024,
357
+ });
358
+ rmSync(buildContextDir, { recursive: true, force: true });
359
+ rmSync(emptyPluginsDir, { recursive: true, force: true });
360
+ rmSync(path.dirname(trivyBinary), { recursive: true, force: true });
361
+ rmSync(path.dirname(trustInspectorBinary), {
362
+ recursive: true,
363
+ force: true,
364
+ });
365
+ rmSync(rootfsDir, { recursive: true, force: true });
366
+ }
367
+ });