@cyclonedx/cdxgen 12.3.0 → 12.3.2
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 +15 -5
- package/bin/audit.js +7 -0
- package/bin/cdxgen.js +241 -81
- package/bin/repl.js +138 -0
- package/data/rules/ai-agent-governance.yaml +249 -0
- package/data/rules/dependency-sources.yaml +41 -0
- package/data/rules/mcp-servers.yaml +304 -0
- package/data/rules/package-integrity.yaml +123 -0
- package/lib/audit/index.js +353 -29
- package/lib/audit/index.poku.js +247 -7
- package/lib/audit/reporters.js +26 -0
- package/lib/audit/scoring.js +262 -13
- package/lib/audit/scoring.poku.js +179 -0
- package/lib/audit/targets.js +391 -2
- package/lib/audit/targets.poku.js +416 -3
- package/lib/cli/index.js +588 -45
- package/lib/cli/index.poku.js +735 -1
- package/lib/evinser/evinser.js +8 -5
- package/lib/helpers/agentFormulationParser.js +318 -0
- package/lib/helpers/aiInventory.js +262 -0
- package/lib/helpers/aiInventory.poku.js +111 -0
- package/lib/helpers/analyzer.js +1769 -0
- package/lib/helpers/analyzer.poku.js +284 -3
- package/lib/helpers/auditCategories.js +76 -0
- package/lib/helpers/ciParsers/githubActions.js +140 -16
- package/lib/helpers/ciParsers/githubActions.poku.js +110 -0
- package/lib/helpers/communityAiConfigParser.js +672 -0
- package/lib/helpers/communityAiConfigParser.poku.js +63 -0
- package/lib/helpers/depsUtils.js +108 -0
- package/lib/helpers/depsUtils.poku.js +72 -1
- package/lib/helpers/display.js +325 -3
- package/lib/helpers/display.poku.js +301 -0
- package/lib/helpers/formulationParsers.js +28 -0
- package/lib/helpers/formulationParsers.poku.js +504 -1
- package/lib/helpers/jsonLike.js +102 -0
- package/lib/helpers/jsonLike.poku.js +34 -0
- package/lib/helpers/mcp.js +248 -0
- package/lib/helpers/mcp.poku.js +101 -0
- package/lib/helpers/mcpConfigParser.js +656 -0
- package/lib/helpers/mcpConfigParser.poku.js +126 -0
- package/lib/helpers/mcpDiscovery.js +84 -0
- package/lib/helpers/mcpDiscovery.poku.js +21 -0
- package/lib/helpers/protobom.js +3 -3
- package/lib/helpers/provenanceUtils.js +29 -4
- package/lib/helpers/provenanceUtils.poku.js +29 -3
- package/lib/helpers/registryProvenance.js +210 -0
- package/lib/helpers/registryProvenance.poku.js +144 -0
- package/lib/helpers/rustFormulationParser.js +330 -0
- package/lib/helpers/source.js +21 -2
- package/lib/helpers/source.poku.js +38 -0
- package/lib/helpers/utils.js +1331 -83
- package/lib/helpers/utils.poku.js +599 -188
- package/lib/helpers/vsixutils.js +12 -4
- package/lib/helpers/vsixutils.poku.js +34 -0
- package/lib/managers/binary.js +36 -12
- package/lib/managers/binary.poku.js +68 -0
- package/lib/managers/docker.js +59 -9
- package/lib/managers/docker.poku.js +61 -0
- package/lib/managers/piptree.js +12 -7
- package/lib/managers/piptree.poku.js +44 -0
- package/lib/stages/postgen/annotator.js +2 -1
- package/lib/stages/postgen/annotator.poku.js +15 -0
- package/lib/stages/postgen/auditBom.js +20 -6
- package/lib/stages/postgen/auditBom.poku.js +694 -1
- package/lib/stages/postgen/postgen.js +262 -11
- package/lib/stages/postgen/postgen.poku.js +306 -2
- package/lib/stages/postgen/ruleEngine.js +49 -1
- package/lib/stages/postgen/spdxConverter.poku.js +70 -0
- package/lib/stages/pregen/pregen.js +6 -4
- package/package.json +1 -1
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/audit/reporters.d.ts.map +1 -1
- package/types/lib/audit/scoring.d.ts.map +1 -1
- package/types/lib/audit/targets.d.ts +12 -0
- package/types/lib/audit/targets.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts +2 -8
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/helpers/agentFormulationParser.d.ts +19 -0
- package/types/lib/helpers/agentFormulationParser.d.ts.map +1 -0
- package/types/lib/helpers/aiInventory.d.ts +23 -0
- package/types/lib/helpers/aiInventory.d.ts.map +1 -0
- package/types/lib/helpers/analyzer.d.ts +10 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/auditCategories.d.ts +12 -0
- package/types/lib/helpers/auditCategories.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
- package/types/lib/helpers/communityAiConfigParser.d.ts +29 -0
- package/types/lib/helpers/communityAiConfigParser.d.ts.map +1 -0
- package/types/lib/helpers/depsUtils.d.ts +8 -0
- package/types/lib/helpers/depsUtils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts +17 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
- package/types/lib/helpers/jsonLike.d.ts +4 -0
- package/types/lib/helpers/jsonLike.d.ts.map +1 -0
- package/types/lib/helpers/mcp.d.ts +29 -0
- package/types/lib/helpers/mcp.d.ts.map +1 -0
- package/types/lib/helpers/mcpConfigParser.d.ts +30 -0
- package/types/lib/helpers/mcpConfigParser.d.ts.map +1 -0
- package/types/lib/helpers/mcpDiscovery.d.ts +5 -0
- package/types/lib/helpers/mcpDiscovery.d.ts.map +1 -0
- package/types/lib/helpers/provenanceUtils.d.ts +5 -3
- package/types/lib/helpers/provenanceUtils.d.ts.map +1 -1
- package/types/lib/helpers/registryProvenance.d.ts +9 -0
- package/types/lib/helpers/registryProvenance.d.ts.map +1 -1
- package/types/lib/helpers/rustFormulationParser.d.ts +17 -0
- package/types/lib/helpers/rustFormulationParser.d.ts.map +1 -0
- package/types/lib/helpers/source.d.ts.map +1 -1
- package/types/lib/helpers/utils.d.ts +31 -1
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/piptree.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
package/lib/cli/index.js
CHANGED
|
@@ -3,13 +3,9 @@ import {
|
|
|
3
3
|
accessSync,
|
|
4
4
|
constants,
|
|
5
5
|
lstatSync,
|
|
6
|
-
mkdtempSync,
|
|
7
6
|
readdirSync,
|
|
8
7
|
readFileSync,
|
|
9
|
-
rmSync,
|
|
10
8
|
statSync,
|
|
11
|
-
unlinkSync,
|
|
12
|
-
writeFileSync,
|
|
13
9
|
} from "node:fs";
|
|
14
10
|
import { platform as _platform, arch, homedir } from "node:os";
|
|
15
11
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
@@ -22,7 +18,24 @@ import { parse } from "ssri";
|
|
|
22
18
|
import { v4 as uuidv4 } from "uuid";
|
|
23
19
|
import { parse as loadYaml } from "yaml";
|
|
24
20
|
|
|
25
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
AI_INSTRUCTION_FILE_KINDS,
|
|
23
|
+
AI_INVENTORY_PROJECT_TYPES,
|
|
24
|
+
AI_SKILL_FILE_KIND,
|
|
25
|
+
collectAiInventory,
|
|
26
|
+
filterInventoryDependencies,
|
|
27
|
+
filterInventorySubjectsByTypes,
|
|
28
|
+
inventoryPropertyValue,
|
|
29
|
+
MCP_CONFIG_FILE_KIND,
|
|
30
|
+
optionIncludesAiInventoryProjectType,
|
|
31
|
+
summarizeAiInventory,
|
|
32
|
+
} from "../helpers/aiInventory.js";
|
|
33
|
+
import {
|
|
34
|
+
detectMcpInventory,
|
|
35
|
+
detectPythonMcpInventory,
|
|
36
|
+
findJSImportsExports,
|
|
37
|
+
} from "../helpers/analyzer.js";
|
|
38
|
+
import { expandBomAuditCategories } from "../helpers/auditCategories.js";
|
|
26
39
|
import { parseCaxaMetadata } from "../helpers/caxa.js";
|
|
27
40
|
import {
|
|
28
41
|
CHROME_EXTENSION_PURL_TYPE,
|
|
@@ -30,9 +43,17 @@ import {
|
|
|
30
43
|
collectInstalledChromeExtensions,
|
|
31
44
|
discoverChromiumExtensionDirs,
|
|
32
45
|
} from "../helpers/chromextutils.js";
|
|
33
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
mergeDependencies,
|
|
48
|
+
mergeServices,
|
|
49
|
+
trimComponents,
|
|
50
|
+
} from "../helpers/depsUtils.js";
|
|
34
51
|
import { GIT_COMMAND } from "../helpers/envcontext.js";
|
|
35
52
|
import { thoughtLog } from "../helpers/logger.js";
|
|
53
|
+
import {
|
|
54
|
+
classifyMcpReference,
|
|
55
|
+
enrichComponentWithMcpMetadata,
|
|
56
|
+
} from "../helpers/mcp.js";
|
|
36
57
|
import { isPyLockFile } from "../helpers/pylockutils.js";
|
|
37
58
|
import {
|
|
38
59
|
buildDependencyTrackBomPayload,
|
|
@@ -71,6 +92,7 @@ import {
|
|
|
71
92
|
generatePixiLockFile,
|
|
72
93
|
getAllFiles,
|
|
73
94
|
getCppModules,
|
|
95
|
+
getCratesMetadata,
|
|
74
96
|
getGradleCommand,
|
|
75
97
|
getLicenses,
|
|
76
98
|
getMavenCommand,
|
|
@@ -87,6 +109,7 @@ import {
|
|
|
87
109
|
getTmpDir,
|
|
88
110
|
hasAnyProjectType,
|
|
89
111
|
includeMavenTestScope,
|
|
112
|
+
isDryRun,
|
|
90
113
|
isFeatureEnabled,
|
|
91
114
|
isMac,
|
|
92
115
|
isPackageManagerAllowed,
|
|
@@ -105,6 +128,7 @@ import {
|
|
|
105
128
|
parseCabalData,
|
|
106
129
|
parseCargoData,
|
|
107
130
|
parseCargoDependencyData,
|
|
131
|
+
parseCargoManifestDependencyData,
|
|
108
132
|
parseCargoTomlData,
|
|
109
133
|
parseCljDep,
|
|
110
134
|
parseCloudBuildData,
|
|
@@ -173,13 +197,23 @@ import {
|
|
|
173
197
|
parseYarnWorkspace,
|
|
174
198
|
readZipEntry,
|
|
175
199
|
recomputeScope,
|
|
200
|
+
recordActivity,
|
|
201
|
+
resetActivityContext,
|
|
176
202
|
SWIFT_CMD,
|
|
177
203
|
safeExistsSync,
|
|
178
204
|
safeMkdirSync,
|
|
205
|
+
safeMkdtempSync,
|
|
206
|
+
safeRmSync,
|
|
179
207
|
safeSpawnSync,
|
|
208
|
+
safeUnlinkSync,
|
|
209
|
+
safeWriteSync,
|
|
210
|
+
setActivityContext,
|
|
180
211
|
shouldFetchLicense,
|
|
181
212
|
splitOutputByGradleProjects,
|
|
182
213
|
} from "../helpers/utils.js";
|
|
214
|
+
|
|
215
|
+
export { summarizeAiInventory } from "../helpers/aiInventory.js";
|
|
216
|
+
|
|
183
217
|
import {
|
|
184
218
|
cleanupTempDir,
|
|
185
219
|
collectInstalledExtensions,
|
|
@@ -254,6 +288,16 @@ const GRADLE_INIT_SCRIPT = resolve(
|
|
|
254
288
|
const SBT_CACHE_DIR =
|
|
255
289
|
process.env.SBT_CACHE_DIR || join(homedir(), ".ivy2", "cache");
|
|
256
290
|
|
|
291
|
+
function getCargoCacheDir() {
|
|
292
|
+
return process.env.CARGO_CACHE_DIR
|
|
293
|
+
? resolve(process.env.CARGO_CACHE_DIR)
|
|
294
|
+
: resolve(
|
|
295
|
+
process.env.CARGO_HOME || join(homedir(), ".cargo"),
|
|
296
|
+
"registry",
|
|
297
|
+
"cache",
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
257
301
|
// CycloneDX Hash pattern
|
|
258
302
|
const HASH_PATTERN =
|
|
259
303
|
"^([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128})$";
|
|
@@ -1040,6 +1084,7 @@ function addComponent(
|
|
|
1040
1084
|
if (pkg.components) {
|
|
1041
1085
|
component.components = pkg.components;
|
|
1042
1086
|
}
|
|
1087
|
+
component = enrichComponentWithMcpMetadata(component);
|
|
1043
1088
|
const compMapKey = component.purl || component["bom-ref"];
|
|
1044
1089
|
// Issue: 1353. We need to keep merging the properties
|
|
1045
1090
|
if (compMap[compMapKey]) {
|
|
@@ -1241,6 +1286,23 @@ function addComponentHash(alg, digest, component) {
|
|
|
1241
1286
|
* @returns {Object} BOM with namespace mapping
|
|
1242
1287
|
*/
|
|
1243
1288
|
const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
1289
|
+
// Many create*Bom call sites provide only a source directory (`src`) when
|
|
1290
|
+
// there is no single manifest/lock file to report, so activity records must
|
|
1291
|
+
// fall back to that directory to keep the target populated.
|
|
1292
|
+
const sourcePath =
|
|
1293
|
+
context?.srcDir || context?.src || options.path || options.filePath;
|
|
1294
|
+
const activityProjectType =
|
|
1295
|
+
context?.projectType ||
|
|
1296
|
+
(Array.isArray(options.projectType)
|
|
1297
|
+
? options.projectType.length === 1
|
|
1298
|
+
? options.projectType[0]
|
|
1299
|
+
: undefined
|
|
1300
|
+
: options.projectType);
|
|
1301
|
+
setActivityContext({
|
|
1302
|
+
packageType: ptype,
|
|
1303
|
+
sourcePath,
|
|
1304
|
+
...(activityProjectType ? { projectType: activityProjectType } : {}),
|
|
1305
|
+
});
|
|
1244
1306
|
const bomNSData = {
|
|
1245
1307
|
bomJson: undefined,
|
|
1246
1308
|
bomJsonFiles: undefined,
|
|
@@ -1255,6 +1317,7 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
|
1255
1317
|
}
|
|
1256
1318
|
const nsMapping = context.nsMapping || {};
|
|
1257
1319
|
const dependencies = context.dependencies || [];
|
|
1320
|
+
const services = context.services || [];
|
|
1258
1321
|
const parentComponent =
|
|
1259
1322
|
determineParentComponent(options) || context.parentComponent;
|
|
1260
1323
|
const metadata = addMetadata(parentComponent, options, context);
|
|
@@ -1270,6 +1333,9 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
|
1270
1333
|
components,
|
|
1271
1334
|
dependencies,
|
|
1272
1335
|
};
|
|
1336
|
+
if (services.length) {
|
|
1337
|
+
jsonTpl.services = mergeServices([], services);
|
|
1338
|
+
}
|
|
1273
1339
|
bomNSData.bomJson = jsonTpl;
|
|
1274
1340
|
bomNSData.nsMapping = nsMapping;
|
|
1275
1341
|
bomNSData.dependencies = dependencies;
|
|
@@ -1280,6 +1346,13 @@ const buildBomNSData = (options, pkgInfo, ptype, context) => {
|
|
|
1280
1346
|
bomNSData.formulationList = context.formulationList;
|
|
1281
1347
|
}
|
|
1282
1348
|
}
|
|
1349
|
+
recordActivity({
|
|
1350
|
+
kind: "read",
|
|
1351
|
+
reason: `Collected ${ptype || "generic"} component metadata.`,
|
|
1352
|
+
status: components?.length || parentComponent ? "completed" : "failed",
|
|
1353
|
+
target: context?.filename || sourcePath,
|
|
1354
|
+
});
|
|
1355
|
+
resetActivityContext();
|
|
1283
1356
|
return bomNSData;
|
|
1284
1357
|
};
|
|
1285
1358
|
|
|
@@ -1342,7 +1415,7 @@ export async function createJarBom(path, options) {
|
|
|
1342
1415
|
jarFiles = jarFiles.concat(hpiFiles);
|
|
1343
1416
|
}
|
|
1344
1417
|
for (const jar of jarFiles) {
|
|
1345
|
-
const tempDir =
|
|
1418
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "jar-deps-"));
|
|
1346
1419
|
if (DEBUG_MODE) {
|
|
1347
1420
|
console.log(`Parsing ${jar}`);
|
|
1348
1421
|
}
|
|
@@ -1354,8 +1427,8 @@ export async function createJarBom(path, options) {
|
|
|
1354
1427
|
pkgList = await getMvnMetadata(pkgList);
|
|
1355
1428
|
}
|
|
1356
1429
|
// Clean up
|
|
1357
|
-
if (tempDir?.startsWith(getTmpDir())
|
|
1358
|
-
|
|
1430
|
+
if (tempDir?.startsWith(getTmpDir())) {
|
|
1431
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
1359
1432
|
}
|
|
1360
1433
|
}
|
|
1361
1434
|
pkgList = pkgList.concat(await convertJarNSToPackages(nsMapping));
|
|
@@ -1384,7 +1457,7 @@ export function createAndroidBom(path, options) {
|
|
|
1384
1457
|
* @returns {Object|undefined} BOM object
|
|
1385
1458
|
*/
|
|
1386
1459
|
export function createBinaryBom(path, options) {
|
|
1387
|
-
const tempDir =
|
|
1460
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "blint-tmp-"));
|
|
1388
1461
|
const binaryBomFile = join(tempDir, "bom.json");
|
|
1389
1462
|
getBinaryBom(path, binaryBomFile, options.deep);
|
|
1390
1463
|
if (safeExistsSync(binaryBomFile)) {
|
|
@@ -1425,16 +1498,16 @@ export async function createJavaBom(path, options) {
|
|
|
1425
1498
|
if (DEBUG_MODE) {
|
|
1426
1499
|
console.log(`Retrieving packages from ${path}`);
|
|
1427
1500
|
}
|
|
1428
|
-
const tempDir =
|
|
1501
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "war-deps-"));
|
|
1429
1502
|
jarNSMapping = await collectJarNS(tempDir);
|
|
1430
1503
|
pkgList = await extractJarArchive(path, tempDir, jarNSMapping);
|
|
1431
1504
|
if (pkgList.length) {
|
|
1432
1505
|
pkgList = await getMvnMetadata(pkgList);
|
|
1433
1506
|
}
|
|
1434
1507
|
// Clean up
|
|
1435
|
-
if (tempDir?.startsWith(getTmpDir())
|
|
1508
|
+
if (tempDir?.startsWith(getTmpDir())) {
|
|
1436
1509
|
console.log(`Cleaning up ${tempDir}`);
|
|
1437
|
-
|
|
1510
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
1438
1511
|
}
|
|
1439
1512
|
} else {
|
|
1440
1513
|
console.log(`${path} doesn't exist`);
|
|
@@ -1788,7 +1861,7 @@ export async function createJavaBom(path, options) {
|
|
|
1788
1861
|
}
|
|
1789
1862
|
}
|
|
1790
1863
|
if (!DEBUG_MODE) {
|
|
1791
|
-
|
|
1864
|
+
safeUnlinkSync(tempMvnTree);
|
|
1792
1865
|
}
|
|
1793
1866
|
}
|
|
1794
1867
|
}
|
|
@@ -2329,7 +2402,7 @@ export async function createJavaBom(path, options) {
|
|
|
2329
2402
|
`${options.multiProject ? "**/" : ""}build.sbt.lock`,
|
|
2330
2403
|
options,
|
|
2331
2404
|
);
|
|
2332
|
-
const tempCacheDir =
|
|
2405
|
+
const tempCacheDir = safeMkdtempSync(join(getTmpDir(), "sbt-cache-"));
|
|
2333
2406
|
safeMkdirSync(tempCacheDir, { recursive: true });
|
|
2334
2407
|
if (
|
|
2335
2408
|
sbtProjects?.length &&
|
|
@@ -2373,8 +2446,8 @@ export async function createJavaBom(path, options) {
|
|
|
2373
2446
|
const useSlashSyntax = !sbtVersion || gte(sbtVersion, "1.5.0");
|
|
2374
2447
|
const isDependencyTreeBuiltIn =
|
|
2375
2448
|
sbtVersion != null && gte(sbtVersion, "1.4.0");
|
|
2376
|
-
const tempDir =
|
|
2377
|
-
const tempSbtgDir =
|
|
2449
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "cdxsbt-"));
|
|
2450
|
+
const tempSbtgDir = safeMkdtempSync(join(getTmpDir(), "cdxsbtg-"));
|
|
2378
2451
|
safeMkdirSync(tempSbtgDir, { recursive: true });
|
|
2379
2452
|
// Create temporary plugins file
|
|
2380
2453
|
const tempSbtPlugins = join(tempSbtgDir, "dep-plugins.sbt");
|
|
@@ -2388,7 +2461,7 @@ export async function createJavaBom(path, options) {
|
|
|
2388
2461
|
console.log("Using addDependencyTreePlugin as the custom plugin");
|
|
2389
2462
|
}
|
|
2390
2463
|
}
|
|
2391
|
-
|
|
2464
|
+
safeWriteSync(tempSbtPlugins, sbtPluginDefinition);
|
|
2392
2465
|
let sbtExtraArgs = "";
|
|
2393
2466
|
const env = { ...process.env };
|
|
2394
2467
|
// We need to collect the jars from the cache
|
|
@@ -2477,7 +2550,7 @@ export async function createJavaBom(path, options) {
|
|
|
2477
2550
|
}
|
|
2478
2551
|
|
|
2479
2552
|
// Cleanup
|
|
2480
|
-
|
|
2553
|
+
safeUnlinkSync(tempSbtPlugins);
|
|
2481
2554
|
} // else
|
|
2482
2555
|
|
|
2483
2556
|
if (DEBUG_MODE) {
|
|
@@ -2510,7 +2583,7 @@ export async function createJavaBom(path, options) {
|
|
|
2510
2583
|
}
|
|
2511
2584
|
}
|
|
2512
2585
|
if (tempCacheDir?.startsWith(getTmpDir())) {
|
|
2513
|
-
|
|
2586
|
+
safeRmSync(tempCacheDir, {
|
|
2514
2587
|
recursive: true,
|
|
2515
2588
|
force: true,
|
|
2516
2589
|
});
|
|
@@ -2661,6 +2734,130 @@ export async function createJavaBom(path, options) {
|
|
|
2661
2734
|
* @param {Object} options Parse options from the cli
|
|
2662
2735
|
* @returns {Promise<Object>} Promise resolving to BOM object
|
|
2663
2736
|
*/
|
|
2737
|
+
function getRequestedAiInventoryTypes(options) {
|
|
2738
|
+
return AI_INVENTORY_PROJECT_TYPES.filter((type) =>
|
|
2739
|
+
optionIncludesAiInventoryProjectType(options?.projectType, type),
|
|
2740
|
+
);
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
function getExcludedAiInventoryTypes(options) {
|
|
2744
|
+
return AI_INVENTORY_PROJECT_TYPES.filter((type) =>
|
|
2745
|
+
optionIncludesAiInventoryProjectType(options?.excludeType, type),
|
|
2746
|
+
);
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
function getExactAiInventoryType(options) {
|
|
2750
|
+
const requestedAiInventoryTypes = getRequestedAiInventoryTypes(options);
|
|
2751
|
+
return requestedAiInventoryTypes.length === 1 &&
|
|
2752
|
+
Array.isArray(options?.projectType) &&
|
|
2753
|
+
options.projectType.length === 1
|
|
2754
|
+
? requestedAiInventoryTypes[0]
|
|
2755
|
+
: undefined;
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
function shouldDetectMcpInventory(options, allImports = {}) {
|
|
2759
|
+
if (hasAnyProjectType(["mcp"], options, false)) {
|
|
2760
|
+
return true;
|
|
2761
|
+
}
|
|
2762
|
+
const auditCategories = expandBomAuditCategories(options?.bomAuditCategories);
|
|
2763
|
+
if (
|
|
2764
|
+
auditCategories.some((category) =>
|
|
2765
|
+
["mcp-server", "ai-agent"].includes(category),
|
|
2766
|
+
)
|
|
2767
|
+
) {
|
|
2768
|
+
return true;
|
|
2769
|
+
}
|
|
2770
|
+
return Object.keys(allImports).some((importName) => {
|
|
2771
|
+
const classification = classifyMcpReference(importName);
|
|
2772
|
+
return classification.isMcp;
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2776
|
+
function summarizeAiInventoryNames(subjects, discoveryPath, kindSet) {
|
|
2777
|
+
return [
|
|
2778
|
+
...new Set(
|
|
2779
|
+
(subjects || [])
|
|
2780
|
+
.filter((subject) =>
|
|
2781
|
+
kindSet.has(inventoryPropertyValue(subject, "cdx:file:kind")),
|
|
2782
|
+
)
|
|
2783
|
+
.map((subject) => inventoryPropertyValue(subject, "SrcFile"))
|
|
2784
|
+
.filter(Boolean)
|
|
2785
|
+
.map(
|
|
2786
|
+
(filePath) => relative(discoveryPath, filePath) || basename(filePath),
|
|
2787
|
+
),
|
|
2788
|
+
),
|
|
2789
|
+
].sort();
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
function summarizeAiInventoryServiceNames(services) {
|
|
2793
|
+
return [
|
|
2794
|
+
...new Set(
|
|
2795
|
+
(services || []).map((service) => service?.name).filter(Boolean),
|
|
2796
|
+
),
|
|
2797
|
+
].sort();
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
function formatAiInventorySummaryLine(label, count, nameList) {
|
|
2801
|
+
return ` ${label.padEnd(20)} ${count}${nameList.length ? ` (${nameList.join(", ")})` : ""}`;
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
function emitAiInventorySummary(aiInventory, discoveryPath) {
|
|
2805
|
+
const summary = summarizeAiInventory(aiInventory);
|
|
2806
|
+
const totalInventory =
|
|
2807
|
+
summary.instructionCount +
|
|
2808
|
+
summary.skillCount +
|
|
2809
|
+
summary.mcpConfigCount +
|
|
2810
|
+
summary.mcpServiceCount;
|
|
2811
|
+
if (!totalInventory) {
|
|
2812
|
+
return;
|
|
2813
|
+
}
|
|
2814
|
+
const instructionNames = summarizeAiInventoryNames(
|
|
2815
|
+
aiInventory.components,
|
|
2816
|
+
discoveryPath,
|
|
2817
|
+
AI_INSTRUCTION_FILE_KINDS,
|
|
2818
|
+
);
|
|
2819
|
+
const skillNames = summarizeAiInventoryNames(
|
|
2820
|
+
aiInventory.components,
|
|
2821
|
+
discoveryPath,
|
|
2822
|
+
new Set([AI_SKILL_FILE_KIND]),
|
|
2823
|
+
);
|
|
2824
|
+
const mcpConfigNames = summarizeAiInventoryNames(
|
|
2825
|
+
aiInventory.components,
|
|
2826
|
+
discoveryPath,
|
|
2827
|
+
new Set([MCP_CONFIG_FILE_KIND]),
|
|
2828
|
+
);
|
|
2829
|
+
const mcpServiceNames = summarizeAiInventoryServiceNames(
|
|
2830
|
+
aiInventory.services,
|
|
2831
|
+
);
|
|
2832
|
+
console.warn(
|
|
2833
|
+
[
|
|
2834
|
+
"AI Inventory Summary:",
|
|
2835
|
+
formatAiInventorySummaryLine(
|
|
2836
|
+
"AI instruction files:",
|
|
2837
|
+
summary.instructionCount,
|
|
2838
|
+
instructionNames,
|
|
2839
|
+
),
|
|
2840
|
+
formatAiInventorySummaryLine(
|
|
2841
|
+
"Skill files:",
|
|
2842
|
+
summary.skillCount,
|
|
2843
|
+
skillNames,
|
|
2844
|
+
),
|
|
2845
|
+
formatAiInventorySummaryLine(
|
|
2846
|
+
"MCP configs:",
|
|
2847
|
+
summary.mcpConfigCount,
|
|
2848
|
+
mcpConfigNames,
|
|
2849
|
+
),
|
|
2850
|
+
formatAiInventorySummaryLine(
|
|
2851
|
+
"MCP services:",
|
|
2852
|
+
summary.mcpServiceCount,
|
|
2853
|
+
mcpServiceNames,
|
|
2854
|
+
),
|
|
2855
|
+
"",
|
|
2856
|
+
"Run --bom-audit --bom-audit-categories ai-inventory to audit these surfaces.",
|
|
2857
|
+
].join("\n"),
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2664
2861
|
export async function createNodejsBom(path, options) {
|
|
2665
2862
|
let pkgList = [];
|
|
2666
2863
|
let manifestFiles = [];
|
|
@@ -2668,6 +2865,15 @@ export async function createNodejsBom(path, options) {
|
|
|
2668
2865
|
let parentComponent = {};
|
|
2669
2866
|
const parentSubComponents = [];
|
|
2670
2867
|
let ppurl = "";
|
|
2868
|
+
const requestedAiInventoryTypes = getRequestedAiInventoryTypes(options);
|
|
2869
|
+
const excludedAiInventoryTypes = getExcludedAiInventoryTypes(options);
|
|
2870
|
+
const exactAiInventoryType = getExactAiInventoryType(options);
|
|
2871
|
+
const includedAiInventoryTypes = exactAiInventoryType
|
|
2872
|
+
? requestedAiInventoryTypes
|
|
2873
|
+
: AI_INVENTORY_PROJECT_TYPES.filter(
|
|
2874
|
+
(type) => !excludedAiInventoryTypes.includes(type),
|
|
2875
|
+
);
|
|
2876
|
+
let aiInventory = { components: [], dependencies: [], services: [] };
|
|
2671
2877
|
// Docker mode requires special handling
|
|
2672
2878
|
if (hasAnyProjectType(["docker", "oci", "container", "os"], options, false)) {
|
|
2673
2879
|
const pkgJsonFiles = getAllFiles(path, "**/package.json", options);
|
|
@@ -2679,16 +2885,33 @@ export async function createNodejsBom(path, options) {
|
|
|
2679
2885
|
pkgList = pkgList.concat(dlist);
|
|
2680
2886
|
}
|
|
2681
2887
|
}
|
|
2888
|
+
if (includedAiInventoryTypes.length) {
|
|
2889
|
+
aiInventory = collectAiInventory(
|
|
2890
|
+
path,
|
|
2891
|
+
options,
|
|
2892
|
+
includedAiInventoryTypes,
|
|
2893
|
+
);
|
|
2894
|
+
}
|
|
2895
|
+
if (aiInventory.components?.length) {
|
|
2896
|
+
pkgList = trimComponents(pkgList.concat(aiInventory.components));
|
|
2897
|
+
}
|
|
2682
2898
|
return buildBomNSData(options, pkgList, "npm", {
|
|
2683
2899
|
allImports: {},
|
|
2684
2900
|
src: path,
|
|
2685
2901
|
filename: "package.json",
|
|
2902
|
+
dependencies: mergeDependencies(
|
|
2903
|
+
[],
|
|
2904
|
+
aiInventory.dependencies,
|
|
2905
|
+
parentComponent,
|
|
2906
|
+
),
|
|
2686
2907
|
parentComponent,
|
|
2908
|
+
services: aiInventory.services,
|
|
2687
2909
|
});
|
|
2688
2910
|
}
|
|
2689
2911
|
}
|
|
2690
2912
|
let allImports = {};
|
|
2691
2913
|
let allExports = {};
|
|
2914
|
+
let mcpInventory = {};
|
|
2692
2915
|
if (
|
|
2693
2916
|
!hasAnyProjectType(["docker", "oci", "container", "os"], options, false) &&
|
|
2694
2917
|
!options.noBabel
|
|
@@ -2701,6 +2924,43 @@ export async function createNodejsBom(path, options) {
|
|
|
2701
2924
|
const retData = await findJSImportsExports(path, options.deep);
|
|
2702
2925
|
allImports = retData.allImports;
|
|
2703
2926
|
allExports = retData.allExports;
|
|
2927
|
+
if (shouldDetectMcpInventory(options, allImports)) {
|
|
2928
|
+
mcpInventory = detectMcpInventory(path, options.deep);
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
if (includedAiInventoryTypes.length) {
|
|
2932
|
+
aiInventory = collectAiInventory(path, options, includedAiInventoryTypes);
|
|
2933
|
+
}
|
|
2934
|
+
if (excludedAiInventoryTypes.includes("mcp")) {
|
|
2935
|
+
mcpInventory = { components: [], dependencies: [], services: [] };
|
|
2936
|
+
}
|
|
2937
|
+
const aiInventorySummary = summarizeAiInventory(aiInventory);
|
|
2938
|
+
if (!exactAiInventoryType) {
|
|
2939
|
+
if (aiInventorySummary.instructionCount || aiInventorySummary.skillCount) {
|
|
2940
|
+
thoughtLog(
|
|
2941
|
+
`I found ${aiInventorySummary.instructionCount + aiInventorySummary.skillCount} AI skill/instruction file component(s). Use '--exclude-type ai-skill' for a package-only BOM, or '--bom-audit --bom-audit-categories ai-inventory' for review-friendly reporting.`,
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
if (aiInventorySummary.mcpConfigCount) {
|
|
2945
|
+
thoughtLog(
|
|
2946
|
+
`I found ${aiInventorySummary.mcpConfigCount} MCP config component(s). Use '--exclude-type mcp' to drop them, or '--bom-audit --bom-audit-categories ai-inventory --tlp-classification AMBER' to keep and flag them.`,
|
|
2947
|
+
);
|
|
2948
|
+
}
|
|
2949
|
+
emitAiInventorySummary(aiInventory, path);
|
|
2950
|
+
}
|
|
2951
|
+
if (exactAiInventoryType === "ai-skill") {
|
|
2952
|
+
const exactComponents = trimComponents([...(aiInventory.components || [])]);
|
|
2953
|
+
const exactDependencies = mergeDependencies([], aiInventory.dependencies);
|
|
2954
|
+
const exactServices = mergeServices([], aiInventory.services);
|
|
2955
|
+
parentComponent = createDefaultParentComponent(path, "generic", options);
|
|
2956
|
+
return buildBomNSData(options, exactComponents, "generic", {
|
|
2957
|
+
dependencies: exactDependencies,
|
|
2958
|
+
filename: path,
|
|
2959
|
+
parentComponent,
|
|
2960
|
+
projectType: exactAiInventoryType,
|
|
2961
|
+
services: exactServices,
|
|
2962
|
+
src: path,
|
|
2963
|
+
});
|
|
2704
2964
|
}
|
|
2705
2965
|
let yarnLockFiles = getAllFiles(
|
|
2706
2966
|
path,
|
|
@@ -3582,11 +3842,47 @@ export async function createNodejsBom(path, options) {
|
|
|
3582
3842
|
options.deep,
|
|
3583
3843
|
);
|
|
3584
3844
|
}
|
|
3845
|
+
if (mcpInventory.components?.length) {
|
|
3846
|
+
pkgList = trimComponents(pkgList.concat(mcpInventory.components));
|
|
3847
|
+
}
|
|
3848
|
+
if (mcpInventory.dependencies?.length) {
|
|
3849
|
+
dependencies = mergeDependencies(
|
|
3850
|
+
dependencies,
|
|
3851
|
+
mcpInventory.dependencies,
|
|
3852
|
+
parentComponent,
|
|
3853
|
+
);
|
|
3854
|
+
}
|
|
3855
|
+
if (aiInventory.components?.length) {
|
|
3856
|
+
pkgList = trimComponents(pkgList.concat(aiInventory.components));
|
|
3857
|
+
}
|
|
3858
|
+
if (aiInventory.dependencies?.length) {
|
|
3859
|
+
dependencies = mergeDependencies(
|
|
3860
|
+
dependencies,
|
|
3861
|
+
aiInventory.dependencies,
|
|
3862
|
+
parentComponent,
|
|
3863
|
+
);
|
|
3864
|
+
}
|
|
3865
|
+
const inventoryServices = mergeServices(
|
|
3866
|
+
mergeServices([], mcpInventory.services || []),
|
|
3867
|
+
aiInventory.services || [],
|
|
3868
|
+
);
|
|
3869
|
+
if (exactAiInventoryType === "mcp") {
|
|
3870
|
+
pkgList = trimComponents(filterInventorySubjectsByTypes(pkgList, ["mcp"]));
|
|
3871
|
+
dependencies = filterInventoryDependencies(
|
|
3872
|
+
dependencies,
|
|
3873
|
+
pkgList,
|
|
3874
|
+
inventoryServices,
|
|
3875
|
+
);
|
|
3876
|
+
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
3877
|
+
parentComponent = createDefaultParentComponent(path, "generic", options);
|
|
3878
|
+
}
|
|
3879
|
+
}
|
|
3585
3880
|
return buildBomNSData(options, pkgList, "npm", {
|
|
3586
3881
|
src: path,
|
|
3587
3882
|
filename: manifestFiles.join(", "),
|
|
3588
3883
|
dependencies,
|
|
3589
3884
|
parentComponent,
|
|
3885
|
+
services: inventoryServices,
|
|
3590
3886
|
});
|
|
3591
3887
|
}
|
|
3592
3888
|
|
|
@@ -3765,7 +4061,17 @@ export async function createPythonBom(path, options) {
|
|
|
3765
4061
|
let dependencies = [];
|
|
3766
4062
|
let pkgList = [];
|
|
3767
4063
|
let formulationList = [];
|
|
3768
|
-
const
|
|
4064
|
+
const requestedAiInventoryTypes = getRequestedAiInventoryTypes(options);
|
|
4065
|
+
const excludedAiInventoryTypes = getExcludedAiInventoryTypes(options);
|
|
4066
|
+
const includedAiInventoryTypes = AI_INVENTORY_PROJECT_TYPES.filter(
|
|
4067
|
+
(type) =>
|
|
4068
|
+
(!requestedAiInventoryTypes.length ||
|
|
4069
|
+
requestedAiInventoryTypes.includes(type)) &&
|
|
4070
|
+
!excludedAiInventoryTypes.includes(type),
|
|
4071
|
+
);
|
|
4072
|
+
let aiInventory = { components: [], dependencies: [], services: [] };
|
|
4073
|
+
let mcpInventory = { components: [], dependencies: [], services: [] };
|
|
4074
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "cdxgen-venv-"));
|
|
3769
4075
|
let parentComponent = createDefaultParentComponent(path, "pypi", options);
|
|
3770
4076
|
// We are checking only the root here for pipenv
|
|
3771
4077
|
const pipenvMode = safeExistsSync(join(path, "Pipfile"));
|
|
@@ -3984,7 +4290,7 @@ export async function createPythonBom(path, options) {
|
|
|
3984
4290
|
tempDir,
|
|
3985
4291
|
`exported-${basename(basePath)}-reqs.txt`,
|
|
3986
4292
|
);
|
|
3987
|
-
|
|
4293
|
+
safeWriteSync(tmpReqFile, exportedReqs);
|
|
3988
4294
|
const dlist = await parseReqFile(tmpReqFile, false);
|
|
3989
4295
|
if (dlist?.length) {
|
|
3990
4296
|
pkgList = pkgList.concat(dlist);
|
|
@@ -4256,6 +4562,24 @@ export async function createPythonBom(path, options) {
|
|
|
4256
4562
|
pkgList = pkgList.concat(dlist);
|
|
4257
4563
|
}
|
|
4258
4564
|
}
|
|
4565
|
+
if (includedAiInventoryTypes.length) {
|
|
4566
|
+
aiInventory = collectAiInventory(path, options, includedAiInventoryTypes);
|
|
4567
|
+
if (includedAiInventoryTypes.includes("mcp")) {
|
|
4568
|
+
mcpInventory = detectPythonMcpInventory(path, options.deep);
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4571
|
+
const aiInventorySummary = summarizeAiInventory(aiInventory);
|
|
4572
|
+
if (aiInventorySummary.instructionCount || aiInventorySummary.skillCount) {
|
|
4573
|
+
thoughtLog(
|
|
4574
|
+
`I found ${aiInventorySummary.instructionCount + aiInventorySummary.skillCount} AI skill/instruction file component(s). Use '--exclude-type ai-skill' for a package-only BOM, or '--bom-audit --bom-audit-categories ai-inventory' for review-friendly reporting.`,
|
|
4575
|
+
);
|
|
4576
|
+
}
|
|
4577
|
+
if (aiInventorySummary.mcpConfigCount) {
|
|
4578
|
+
thoughtLog(
|
|
4579
|
+
`I found ${aiInventorySummary.mcpConfigCount} MCP config component(s). Use '--exclude-type mcp' to drop them, or '--bom-audit --bom-audit-categories ai-inventory --tlp-classification AMBER' to keep and flag them.`,
|
|
4580
|
+
);
|
|
4581
|
+
}
|
|
4582
|
+
emitAiInventorySummary(aiInventory, path);
|
|
4259
4583
|
// Check and complete the dependency tree
|
|
4260
4584
|
if (
|
|
4261
4585
|
isFeatureEnabled(options, "safe-pip-install") &&
|
|
@@ -4296,14 +4620,38 @@ export async function createPythonBom(path, options) {
|
|
|
4296
4620
|
}
|
|
4297
4621
|
}
|
|
4298
4622
|
// Clean up
|
|
4299
|
-
if (tempDir?.startsWith(getTmpDir())
|
|
4300
|
-
|
|
4623
|
+
if (tempDir?.startsWith(getTmpDir())) {
|
|
4624
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
4301
4625
|
}
|
|
4302
4626
|
// Re-compute the component scope
|
|
4303
4627
|
pkgList = recomputeScope(pkgList, dependencies);
|
|
4304
4628
|
if (shouldFetchLicense()) {
|
|
4305
4629
|
pkgList = await getPyMetadata(pkgList, false);
|
|
4306
4630
|
}
|
|
4631
|
+
if (mcpInventory.components?.length) {
|
|
4632
|
+
pkgList = trimComponents(pkgList.concat(mcpInventory.components));
|
|
4633
|
+
}
|
|
4634
|
+
if (mcpInventory.dependencies?.length) {
|
|
4635
|
+
dependencies = mergeDependencies(
|
|
4636
|
+
dependencies,
|
|
4637
|
+
mcpInventory.dependencies,
|
|
4638
|
+
parentComponent,
|
|
4639
|
+
);
|
|
4640
|
+
}
|
|
4641
|
+
if (aiInventory.components?.length) {
|
|
4642
|
+
pkgList = trimComponents(pkgList.concat(aiInventory.components));
|
|
4643
|
+
}
|
|
4644
|
+
if (aiInventory.dependencies?.length) {
|
|
4645
|
+
dependencies = mergeDependencies(
|
|
4646
|
+
dependencies,
|
|
4647
|
+
aiInventory.dependencies,
|
|
4648
|
+
parentComponent,
|
|
4649
|
+
);
|
|
4650
|
+
}
|
|
4651
|
+
const inventoryServices = mergeServices(
|
|
4652
|
+
mergeServices([], mcpInventory.services || []),
|
|
4653
|
+
aiInventory.services || [],
|
|
4654
|
+
);
|
|
4307
4655
|
return buildBomNSData(options, pkgList, "pypi", {
|
|
4308
4656
|
allImports,
|
|
4309
4657
|
src: path,
|
|
@@ -4311,6 +4659,7 @@ export async function createPythonBom(path, options) {
|
|
|
4311
4659
|
dependencies,
|
|
4312
4660
|
parentComponent,
|
|
4313
4661
|
formulationList,
|
|
4662
|
+
services: inventoryServices,
|
|
4314
4663
|
});
|
|
4315
4664
|
}
|
|
4316
4665
|
|
|
@@ -4828,7 +5177,9 @@ export async function createRustBom(path, options) {
|
|
|
4828
5177
|
if (DEBUG_MODE) {
|
|
4829
5178
|
console.log(`Parsing ${f}`);
|
|
4830
5179
|
}
|
|
4831
|
-
const dlist = await parseCargoTomlData(f, cargoLockMode, pkgFilesMap
|
|
5180
|
+
const dlist = await parseCargoTomlData(f, cargoLockMode, pkgFilesMap, {
|
|
5181
|
+
includeWorkspaceMembers: !options.multiProject,
|
|
5182
|
+
});
|
|
4832
5183
|
if (dlist?.length) {
|
|
4833
5184
|
if (!cargoLockMode) {
|
|
4834
5185
|
pkgList = pkgList.concat(dlist);
|
|
@@ -4873,6 +5224,18 @@ export async function createRustBom(path, options) {
|
|
|
4873
5224
|
}
|
|
4874
5225
|
}
|
|
4875
5226
|
}
|
|
5227
|
+
for (const f of cargoFiles) {
|
|
5228
|
+
const manifestDependencyList = parseCargoManifestDependencyData(f, {
|
|
5229
|
+
includeWorkspaceMembers: !options.multiProject,
|
|
5230
|
+
});
|
|
5231
|
+
if (manifestDependencyList?.length) {
|
|
5232
|
+
dependencyTree = mergeDependencies(
|
|
5233
|
+
dependencyTree,
|
|
5234
|
+
manifestDependencyList,
|
|
5235
|
+
parentComponent,
|
|
5236
|
+
);
|
|
5237
|
+
}
|
|
5238
|
+
}
|
|
4876
5239
|
return buildBomNSData(options, pkgList, "cargo", {
|
|
4877
5240
|
src: path,
|
|
4878
5241
|
filename: cargoLockFiles.join(", "),
|
|
@@ -4881,6 +5244,95 @@ export async function createRustBom(path, options) {
|
|
|
4881
5244
|
});
|
|
4882
5245
|
}
|
|
4883
5246
|
|
|
5247
|
+
function buildCargoCacheComponent(crateFile) {
|
|
5248
|
+
const crateFileName = basename(crateFile, ".crate");
|
|
5249
|
+
const nameVersionMatch = crateFileName.match(/^(.+)-([0-9][A-Za-z0-9.+-]*)$/);
|
|
5250
|
+
if (!nameVersionMatch) {
|
|
5251
|
+
return undefined;
|
|
5252
|
+
}
|
|
5253
|
+
const [, name, version] = nameVersionMatch;
|
|
5254
|
+
const purl = new PackageURL(
|
|
5255
|
+
"cargo",
|
|
5256
|
+
"",
|
|
5257
|
+
name,
|
|
5258
|
+
version,
|
|
5259
|
+
null,
|
|
5260
|
+
null,
|
|
5261
|
+
).toString();
|
|
5262
|
+
return {
|
|
5263
|
+
"bom-ref": decodeURIComponent(purl),
|
|
5264
|
+
group: "",
|
|
5265
|
+
name,
|
|
5266
|
+
properties: [
|
|
5267
|
+
{
|
|
5268
|
+
name: "SrcFile",
|
|
5269
|
+
value: crateFile,
|
|
5270
|
+
},
|
|
5271
|
+
{
|
|
5272
|
+
name: "cdx:cargo:cacheSource",
|
|
5273
|
+
value: "registry-cache",
|
|
5274
|
+
},
|
|
5275
|
+
],
|
|
5276
|
+
purl,
|
|
5277
|
+
type: "library",
|
|
5278
|
+
version,
|
|
5279
|
+
};
|
|
5280
|
+
}
|
|
5281
|
+
|
|
5282
|
+
async function enrichCargoCacheComponent(crateFile, component) {
|
|
5283
|
+
if (!component) {
|
|
5284
|
+
return undefined;
|
|
5285
|
+
}
|
|
5286
|
+
try {
|
|
5287
|
+
component.hashes = [
|
|
5288
|
+
{
|
|
5289
|
+
alg: "SHA-256",
|
|
5290
|
+
content: await checksumFile("sha256", crateFile),
|
|
5291
|
+
},
|
|
5292
|
+
];
|
|
5293
|
+
} catch {
|
|
5294
|
+
// continue without hashes
|
|
5295
|
+
}
|
|
5296
|
+
component.evidence = {
|
|
5297
|
+
identity: {
|
|
5298
|
+
field: "purl",
|
|
5299
|
+
confidence: 0.5,
|
|
5300
|
+
methods: [
|
|
5301
|
+
{
|
|
5302
|
+
technique: "filename",
|
|
5303
|
+
confidence: 0.5,
|
|
5304
|
+
value: crateFile,
|
|
5305
|
+
},
|
|
5306
|
+
],
|
|
5307
|
+
},
|
|
5308
|
+
};
|
|
5309
|
+
return component;
|
|
5310
|
+
}
|
|
5311
|
+
|
|
5312
|
+
async function createCargoCacheBom(path, options) {
|
|
5313
|
+
const parentComponent = createDefaultParentComponent(path, "cargo", options);
|
|
5314
|
+
const crateFiles = path.endsWith(".crate")
|
|
5315
|
+
? [resolve(path)]
|
|
5316
|
+
: getAllFiles(path, "**/*.crate", options);
|
|
5317
|
+
let pkgList = [];
|
|
5318
|
+
for (const crateFile of crateFiles) {
|
|
5319
|
+
const component = await enrichCargoCacheComponent(
|
|
5320
|
+
crateFile,
|
|
5321
|
+
buildCargoCacheComponent(crateFile),
|
|
5322
|
+
);
|
|
5323
|
+
if (component) {
|
|
5324
|
+
pkgList.push(component);
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
if (pkgList.length && shouldFetchLicense()) {
|
|
5328
|
+
pkgList = await getCratesMetadata(pkgList);
|
|
5329
|
+
}
|
|
5330
|
+
return buildBomNSData(options, pkgList, "cargo", {
|
|
5331
|
+
src: path,
|
|
5332
|
+
parentComponent,
|
|
5333
|
+
});
|
|
5334
|
+
}
|
|
5335
|
+
|
|
4884
5336
|
/**
|
|
4885
5337
|
* Function to create bom string for Dart projects
|
|
4886
5338
|
*
|
|
@@ -5483,7 +5935,7 @@ export async function createJenkinsBom(path, options) {
|
|
|
5483
5935
|
`${options.multiProject ? "**/" : ""}*.hpi`,
|
|
5484
5936
|
options,
|
|
5485
5937
|
);
|
|
5486
|
-
const tempDir =
|
|
5938
|
+
const tempDir = safeMkdtempSync(join(getTmpDir(), "hpi-deps-"));
|
|
5487
5939
|
if (hpiFiles.length) {
|
|
5488
5940
|
for (const f of hpiFiles) {
|
|
5489
5941
|
if (DEBUG_MODE) {
|
|
@@ -5508,9 +5960,9 @@ export async function createJenkinsBom(path, options) {
|
|
|
5508
5960
|
}
|
|
5509
5961
|
}
|
|
5510
5962
|
// Clean up
|
|
5511
|
-
if (tempDir?.startsWith(getTmpDir())
|
|
5963
|
+
if (tempDir?.startsWith(getTmpDir())) {
|
|
5512
5964
|
console.log(`Cleaning up ${tempDir}`);
|
|
5513
|
-
|
|
5965
|
+
safeRmSync(tempDir, { recursive: true, force: true });
|
|
5514
5966
|
}
|
|
5515
5967
|
return buildBomNSData(options, pkgList, "maven", {
|
|
5516
5968
|
src: path,
|
|
@@ -6281,7 +6733,7 @@ export async function createContainerSpecLikeBom(path, options) {
|
|
|
6281
6733
|
},
|
|
6282
6734
|
];
|
|
6283
6735
|
}
|
|
6284
|
-
services = services
|
|
6736
|
+
services = mergeServices(services, servlist);
|
|
6285
6737
|
}
|
|
6286
6738
|
}
|
|
6287
6739
|
}
|
|
@@ -6303,7 +6755,7 @@ export async function createContainerSpecLikeBom(path, options) {
|
|
|
6303
6755
|
console.log(`Parsing ${f}`);
|
|
6304
6756
|
}
|
|
6305
6757
|
const servlist = parsePrivadoFile(f);
|
|
6306
|
-
services = services
|
|
6758
|
+
services = mergeServices(services, servlist);
|
|
6307
6759
|
if (servlist.length) {
|
|
6308
6760
|
const aservice = servlist[0];
|
|
6309
6761
|
if (aservice.data) {
|
|
@@ -6353,7 +6805,7 @@ export async function createContainerSpecLikeBom(path, options) {
|
|
|
6353
6805
|
);
|
|
6354
6806
|
}
|
|
6355
6807
|
if (mbomData.bomJson.services) {
|
|
6356
|
-
services = services
|
|
6808
|
+
services = mergeServices(services, mbomData.bomJson.services);
|
|
6357
6809
|
}
|
|
6358
6810
|
}
|
|
6359
6811
|
if (DEBUG_MODE) {
|
|
@@ -6363,7 +6815,7 @@ export async function createContainerSpecLikeBom(path, options) {
|
|
|
6363
6815
|
}
|
|
6364
6816
|
}
|
|
6365
6817
|
}
|
|
6366
|
-
options.services = services;
|
|
6818
|
+
options.services = mergeServices([], services);
|
|
6367
6819
|
options.ociSpecs = ociSpecs;
|
|
6368
6820
|
return dedupeBom(options, components, parentComponent, dependencies);
|
|
6369
6821
|
}
|
|
@@ -6763,7 +7215,10 @@ export async function createRubyBom(path, options) {
|
|
|
6763
7215
|
}
|
|
6764
7216
|
// Clean up
|
|
6765
7217
|
if (process.env?.CDXGEN_GEM_HOME?.startsWith(getTmpDir())) {
|
|
6766
|
-
|
|
7218
|
+
safeRmSync(process.env.CDXGEN_GEM_HOME, {
|
|
7219
|
+
recursive: true,
|
|
7220
|
+
force: true,
|
|
7221
|
+
});
|
|
6767
7222
|
}
|
|
6768
7223
|
} else {
|
|
6769
7224
|
if (process.env.CDXGEN_GEM_HOME) {
|
|
@@ -7578,6 +8033,12 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7578
8033
|
let formulationList = [];
|
|
7579
8034
|
let parentComponent = determineParentComponent(options) || {};
|
|
7580
8035
|
let parentSubComponents = [];
|
|
8036
|
+
const setProjectTypeActivityContext = (projectType, sourcePath) => {
|
|
8037
|
+
setActivityContext({
|
|
8038
|
+
projectType,
|
|
8039
|
+
sourcePath,
|
|
8040
|
+
});
|
|
8041
|
+
};
|
|
7581
8042
|
options.createMultiXBom = true;
|
|
7582
8043
|
// Convert single path to an array
|
|
7583
8044
|
if (!Array.isArray(pathList)) {
|
|
@@ -7657,27 +8118,58 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7657
8118
|
}
|
|
7658
8119
|
}
|
|
7659
8120
|
for (const path of pathList) {
|
|
8121
|
+
setActivityContext({
|
|
8122
|
+
projectType: Array.isArray(options.projectType)
|
|
8123
|
+
? options.projectType.join(",")
|
|
8124
|
+
: options.projectType,
|
|
8125
|
+
sourcePath: path,
|
|
8126
|
+
});
|
|
8127
|
+
recordActivity({
|
|
8128
|
+
kind: "read",
|
|
8129
|
+
reason:
|
|
8130
|
+
"Scanning project path for supported languages and package managers.",
|
|
8131
|
+
status: "completed",
|
|
8132
|
+
target: path,
|
|
8133
|
+
});
|
|
7660
8134
|
if (DEBUG_MODE) {
|
|
7661
8135
|
console.log("Scanning", path);
|
|
7662
8136
|
}
|
|
7663
8137
|
if (pathList.length > 2) {
|
|
7664
8138
|
thoughtLog(`Let's thoroughly check the path ${path}.`);
|
|
7665
8139
|
}
|
|
7666
|
-
// Node.js
|
|
7667
|
-
if (hasAnyProjectType(["oci", "js"], options)) {
|
|
8140
|
+
// Node.js and AI inventory
|
|
8141
|
+
if (hasAnyProjectType(["oci", "js", "mcp", "ai-skill"], options)) {
|
|
8142
|
+
const exactAiInventoryType = getExactAiInventoryType(options);
|
|
7668
8143
|
if (!hasAnyProjectType(["oci"], options, false)) {
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
8144
|
+
if (exactAiInventoryType === "mcp") {
|
|
8145
|
+
thoughtLog(
|
|
8146
|
+
"**MCP**: Looking for MCP services, MCP configs, and related AI control-plane artifacts.",
|
|
8147
|
+
);
|
|
8148
|
+
} else if (exactAiInventoryType === "ai-skill") {
|
|
8149
|
+
thoughtLog(
|
|
8150
|
+
"**AI-SKILL**: Looking for AI instruction, skill, and agent-definition files that can influence build or release flows.",
|
|
8151
|
+
);
|
|
8152
|
+
} else {
|
|
8153
|
+
thoughtLog(
|
|
8154
|
+
"**JS**: Now looking for JavaScript projects (npm, yarn, pnpm) and files.",
|
|
8155
|
+
);
|
|
8156
|
+
}
|
|
7672
8157
|
}
|
|
8158
|
+
setProjectTypeActivityContext(exactAiInventoryType || "js", path);
|
|
7673
8159
|
bomData = await createNodejsBom(path, options);
|
|
7674
8160
|
if (bomData?.bomJson?.components?.length) {
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
8161
|
+
if (exactAiInventoryType) {
|
|
8162
|
+
thoughtLog(
|
|
8163
|
+
`I found ${bomData.bomJson.components.length} ${exactAiInventoryType} component(s). Let's keep looking.`,
|
|
8164
|
+
);
|
|
8165
|
+
} else {
|
|
8166
|
+
thoughtLog(
|
|
8167
|
+
`I found ${bomData.bomJson.components.length} npm packages. Let's keep looking.`,
|
|
8168
|
+
);
|
|
8169
|
+
}
|
|
7678
8170
|
if (DEBUG_MODE) {
|
|
7679
8171
|
console.log(
|
|
7680
|
-
`Found ${bomData.bomJson.components.length} npm
|
|
8172
|
+
`Found ${bomData.bomJson.components.length} ${exactAiInventoryType || "npm"} components at ${path}`,
|
|
7681
8173
|
);
|
|
7682
8174
|
}
|
|
7683
8175
|
components = components.concat(bomData.bomJson.components);
|
|
@@ -7685,6 +8177,12 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7685
8177
|
dependencies,
|
|
7686
8178
|
bomData.bomJson.dependencies,
|
|
7687
8179
|
);
|
|
8180
|
+
if (bomData?.bomJson?.services?.length) {
|
|
8181
|
+
options.services = mergeServices(
|
|
8182
|
+
options.services || [],
|
|
8183
|
+
bomData.bomJson.services,
|
|
8184
|
+
);
|
|
8185
|
+
}
|
|
7688
8186
|
if (
|
|
7689
8187
|
bomData.parentComponent &&
|
|
7690
8188
|
Object.keys(bomData.parentComponent).length
|
|
@@ -7707,6 +8205,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7707
8205
|
"**JAVA**: Looking for Java projects (e.g., Maven, Gradle, SBT). I hope all configurations—from Java version to individual build settings—are correctly aligned.",
|
|
7708
8206
|
);
|
|
7709
8207
|
}
|
|
8208
|
+
setProjectTypeActivityContext("java", path);
|
|
7710
8209
|
bomData = await createJavaBom(path, options);
|
|
7711
8210
|
if (bomData?.bomJson?.components?.length) {
|
|
7712
8211
|
thoughtLog(
|
|
@@ -7764,6 +8263,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7764
8263
|
"I'm running in a non-container environment. Let's hope the correct build tools are available ✌️.",
|
|
7765
8264
|
);
|
|
7766
8265
|
}
|
|
8266
|
+
setProjectTypeActivityContext("py", path);
|
|
7767
8267
|
bomData = await createPythonBom(path, options);
|
|
7768
8268
|
if (bomData?.bomJson?.components?.length) {
|
|
7769
8269
|
thoughtLog(
|
|
@@ -7796,6 +8296,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7796
8296
|
"**GO**: Looking for go projects. I need to be cautious about purl namespaces and potential failures with the 'go list' command.",
|
|
7797
8297
|
);
|
|
7798
8298
|
}
|
|
8299
|
+
setProjectTypeActivityContext("go", path);
|
|
7799
8300
|
bomData = await createGoBom(path, options);
|
|
7800
8301
|
if (bomData?.bomJson?.components?.length) {
|
|
7801
8302
|
thoughtLog(`I found ${bomData.bomJson.components.length} go packages.`);
|
|
@@ -7823,6 +8324,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7823
8324
|
"**RUST**: Let's search for Cargo/Rust projects. Should I warn the user that we don't support Cargo 'features' and native dependencies, which may lead to both false positives and false negatives? 🤔?",
|
|
7824
8325
|
);
|
|
7825
8326
|
}
|
|
8327
|
+
setProjectTypeActivityContext("rust", path);
|
|
7826
8328
|
bomData = await createRustBom(path, options);
|
|
7827
8329
|
if (bomData?.bomJson?.components?.length) {
|
|
7828
8330
|
thoughtLog(
|
|
@@ -7859,6 +8361,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7859
8361
|
"**PHP**: About to search for Composer-based projects. I hope lock files are available; otherwise, the 'composer install' command might fail for various reasons.",
|
|
7860
8362
|
);
|
|
7861
8363
|
}
|
|
8364
|
+
setProjectTypeActivityContext("php", path);
|
|
7862
8365
|
bomData = createPHPBom(path, options);
|
|
7863
8366
|
if (bomData?.bomJson?.components?.length) {
|
|
7864
8367
|
thoughtLog(
|
|
@@ -7895,6 +8398,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7895
8398
|
"**RUBY**: Are there any Ruby projects in this path? There's only one way to know.",
|
|
7896
8399
|
);
|
|
7897
8400
|
}
|
|
8401
|
+
setProjectTypeActivityContext("ruby", path);
|
|
7898
8402
|
bomData = await createRubyBom(path, options);
|
|
7899
8403
|
if (bomData?.bomJson?.components?.length) {
|
|
7900
8404
|
thoughtLog(
|
|
@@ -7930,6 +8434,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7930
8434
|
if (!hasAnyProjectType(["oci"], options, false)) {
|
|
7931
8435
|
thoughtLog("**CSHARP**: What about csharp and fsharp projects?");
|
|
7932
8436
|
}
|
|
8437
|
+
setProjectTypeActivityContext("csharp", path);
|
|
7933
8438
|
bomData = await createCsharpBom(path, options);
|
|
7934
8439
|
if (bomData?.bomJson?.components?.length) {
|
|
7935
8440
|
thoughtLog(
|
|
@@ -7966,6 +8471,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7966
8471
|
"**DART**: Looking for Dart projects. These are rare ones. Should I inform the user that they can pass the types argument via the command-line to speed things up?",
|
|
7967
8472
|
);
|
|
7968
8473
|
}
|
|
8474
|
+
setProjectTypeActivityContext("dart", path);
|
|
7969
8475
|
bomData = await createDartBom(path, options);
|
|
7970
8476
|
if (bomData?.bomJson?.components?.length) {
|
|
7971
8477
|
thoughtLog(
|
|
@@ -7995,6 +8501,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
7995
8501
|
"**HASKELL**: Looking for Haskell projects. They're rarely encountered.",
|
|
7996
8502
|
);
|
|
7997
8503
|
}
|
|
8504
|
+
setProjectTypeActivityContext("haskell", path);
|
|
7998
8505
|
bomData = createHaskellBom(path, options);
|
|
7999
8506
|
if (bomData?.bomJson?.components?.length) {
|
|
8000
8507
|
thoughtLog(
|
|
@@ -8024,6 +8531,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8024
8531
|
"**ELIXIR**: Looking for Elixir projects—they're quite rare as well.",
|
|
8025
8532
|
);
|
|
8026
8533
|
}
|
|
8534
|
+
setProjectTypeActivityContext("elixir", path);
|
|
8027
8535
|
bomData = createElixirBom(path, options);
|
|
8028
8536
|
if (bomData?.bomJson?.components?.length) {
|
|
8029
8537
|
thoughtLog(
|
|
@@ -8053,6 +8561,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8053
8561
|
"**C/C++**: Looking for C/C++ projects. Should I warn the user that the generated SBOM might have low accuracy and contain errors?",
|
|
8054
8562
|
);
|
|
8055
8563
|
}
|
|
8564
|
+
setProjectTypeActivityContext("c", path);
|
|
8056
8565
|
bomData = createCppBom(path, options);
|
|
8057
8566
|
if (bomData?.bomJson?.components?.length) {
|
|
8058
8567
|
thoughtLog(
|
|
@@ -8082,6 +8591,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8082
8591
|
"**CLOJURE**: Looking for Clojure projects. Should I warn the user that the purl namespace 'clojars' isn't widely supported by tools like Dependency-Track?",
|
|
8083
8592
|
);
|
|
8084
8593
|
}
|
|
8594
|
+
setProjectTypeActivityContext("clojure", path);
|
|
8085
8595
|
bomData = createClojureBom(path, options);
|
|
8086
8596
|
if (bomData?.bomJson?.components?.length) {
|
|
8087
8597
|
thoughtLog(
|
|
@@ -8111,6 +8621,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8111
8621
|
"**GITHUB**: Looking for any github packages and workflows.",
|
|
8112
8622
|
);
|
|
8113
8623
|
}
|
|
8624
|
+
setProjectTypeActivityContext("github", path);
|
|
8114
8625
|
bomData = createGitHubBom(path, options);
|
|
8115
8626
|
if (bomData?.bomJson?.components?.length) {
|
|
8116
8627
|
thoughtLog(
|
|
@@ -8140,6 +8651,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8140
8651
|
"**CLOUDBUILD**: Let's check for CloudBuild configuration files that include package dependencies.",
|
|
8141
8652
|
);
|
|
8142
8653
|
}
|
|
8654
|
+
setProjectTypeActivityContext("cloudbuild", path);
|
|
8143
8655
|
bomData = createCloudBuildBom(path, options);
|
|
8144
8656
|
if (bomData?.bomJson?.components?.length) {
|
|
8145
8657
|
thoughtLog(
|
|
@@ -8169,6 +8681,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8169
8681
|
"**SWIFT**: Now checking for Swift projects. We don't support CocoaPods, Objective-C, or pure Xcode projects, so the SBOM will be incomplete.",
|
|
8170
8682
|
);
|
|
8171
8683
|
}
|
|
8684
|
+
setProjectTypeActivityContext("swift", path);
|
|
8172
8685
|
bomData = await createSwiftBom(path, options);
|
|
8173
8686
|
if (bomData?.bomJson?.components?.length) {
|
|
8174
8687
|
thoughtLog(
|
|
@@ -8198,6 +8711,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8198
8711
|
"**JAR**: Let's check for any bundled jar/war/ear files to improve the SBOM accuracy.",
|
|
8199
8712
|
);
|
|
8200
8713
|
}
|
|
8714
|
+
setProjectTypeActivityContext("jar", path);
|
|
8201
8715
|
bomData = await createJarBom(path, options);
|
|
8202
8716
|
if (bomData?.bomJson?.components?.length) {
|
|
8203
8717
|
thoughtLog(
|
|
@@ -8222,6 +8736,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8222
8736
|
}
|
|
8223
8737
|
}
|
|
8224
8738
|
if (hasAnyProjectType(["oci", "cocoa"], options)) {
|
|
8739
|
+
setProjectTypeActivityContext("cocoa", path);
|
|
8225
8740
|
bomData = await createCocoaBom(path, options);
|
|
8226
8741
|
if (bomData?.bomJson?.components?.length) {
|
|
8227
8742
|
if (DEBUG_MODE) {
|
|
@@ -8240,6 +8755,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8240
8755
|
}
|
|
8241
8756
|
}
|
|
8242
8757
|
if (hasAnyProjectType(["oci", "nix"], options)) {
|
|
8758
|
+
setProjectTypeActivityContext("nix", path);
|
|
8243
8759
|
bomData = await createNixBom(path, options);
|
|
8244
8760
|
if (bomData?.bomJson?.components?.length) {
|
|
8245
8761
|
if (DEBUG_MODE) {
|
|
@@ -8261,6 +8777,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8261
8777
|
}
|
|
8262
8778
|
}
|
|
8263
8779
|
if (hasAnyProjectType(["caxa"], options)) {
|
|
8780
|
+
setProjectTypeActivityContext("caxa", path);
|
|
8264
8781
|
bomData = await createCaxaBom(path, options);
|
|
8265
8782
|
if (bomData?.bomJson?.components?.length) {
|
|
8266
8783
|
if (DEBUG_MODE) {
|
|
@@ -8282,6 +8799,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8282
8799
|
}
|
|
8283
8800
|
}
|
|
8284
8801
|
if (hasAnyProjectType(["vscode-extension"], options)) {
|
|
8802
|
+
setProjectTypeActivityContext("vscode-extension", path);
|
|
8285
8803
|
bomData = await createVscodeExtensionBom(path, options);
|
|
8286
8804
|
if (bomData?.bomJson?.components?.length) {
|
|
8287
8805
|
if (DEBUG_MODE) {
|
|
@@ -8321,6 +8839,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8321
8839
|
if (!isExplicitChromeExtensionPath) {
|
|
8322
8840
|
options.__didScanChromeExtensions = true;
|
|
8323
8841
|
}
|
|
8842
|
+
setProjectTypeActivityContext("chrome-extension", path);
|
|
8324
8843
|
bomData = await createChromeExtensionBom(path, options);
|
|
8325
8844
|
if (bomData?.bomJson?.components?.length) {
|
|
8326
8845
|
if (DEBUG_MODE) {
|
|
@@ -8349,6 +8868,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8349
8868
|
"**CBOM**: Wait, the user wants me to look for cryptographic assets. Let's check thoroughly.",
|
|
8350
8869
|
);
|
|
8351
8870
|
}
|
|
8871
|
+
setProjectTypeActivityContext("cbom", path);
|
|
8352
8872
|
bomData = await createCryptoCertsBom(path, options);
|
|
8353
8873
|
if (bomData?.bomJson?.components?.length) {
|
|
8354
8874
|
thoughtLog(
|
|
@@ -8370,6 +8890,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8370
8890
|
!options.lastWorkingDir.includes("/opt/") &&
|
|
8371
8891
|
!options.lastWorkingDir.includes("/home/")
|
|
8372
8892
|
) {
|
|
8893
|
+
setProjectTypeActivityContext("jar", options.lastWorkingDir);
|
|
8373
8894
|
bomData = createJarBom(options.lastWorkingDir, options);
|
|
8374
8895
|
if (bomData?.bomJson?.components?.length) {
|
|
8375
8896
|
if (DEBUG_MODE) {
|
|
@@ -8435,9 +8956,7 @@ export async function createMultiXBom(pathList, options) {
|
|
|
8435
8956
|
// some cleanup, but not complete
|
|
8436
8957
|
for (const path of pathList) {
|
|
8437
8958
|
if (path.startsWith(join(getTmpDir(), "docker-images-"))) {
|
|
8438
|
-
|
|
8439
|
-
rmSync(path, { recursive: true, force: true });
|
|
8440
|
-
}
|
|
8959
|
+
safeRmSync(path, { recursive: true, force: true });
|
|
8441
8960
|
}
|
|
8442
8961
|
}
|
|
8443
8962
|
const multiResult = dedupeBom(
|
|
@@ -8956,6 +9475,10 @@ export async function createBom(path, options) {
|
|
|
8956
9475
|
projectType = ["java"];
|
|
8957
9476
|
}
|
|
8958
9477
|
if (projectType.length > 1) {
|
|
9478
|
+
setActivityContext({
|
|
9479
|
+
projectType: projectType.join(","),
|
|
9480
|
+
sourcePath: path,
|
|
9481
|
+
});
|
|
8959
9482
|
thoughtLog(
|
|
8960
9483
|
`The user has specified multiple project types: ${projectType.join(", ")}. Let's focus on the types one at a time.`,
|
|
8961
9484
|
);
|
|
@@ -8963,6 +9486,7 @@ export async function createBom(path, options) {
|
|
|
8963
9486
|
return await createMultiXBom(path, options);
|
|
8964
9487
|
}
|
|
8965
9488
|
if (projectType.length === 1) {
|
|
9489
|
+
setActivityContext({ projectType: projectType[0], sourcePath: path });
|
|
8966
9490
|
if (hasAnyProjectType(["oci"], options, false)) {
|
|
8967
9491
|
thoughtLog(
|
|
8968
9492
|
"Okay, we're generating an SBOM for the OCI type. We'll need a compatible tool like Docker, Podman, or Nerdctl, along with the binary plugins.",
|
|
@@ -8986,6 +9510,12 @@ export async function createBom(path, options) {
|
|
|
8986
9510
|
) {
|
|
8987
9511
|
return await createNodejsBom(path, options);
|
|
8988
9512
|
}
|
|
9513
|
+
if (PROJECT_TYPE_ALIASES["mcp"].includes(projectType[0])) {
|
|
9514
|
+
return await createNodejsBom(path, options);
|
|
9515
|
+
}
|
|
9516
|
+
if (PROJECT_TYPE_ALIASES["ai-skill"].includes(projectType[0])) {
|
|
9517
|
+
return await createNodejsBom(path, options);
|
|
9518
|
+
}
|
|
8989
9519
|
if (
|
|
8990
9520
|
PROJECT_TYPE_ALIASES["py"].includes(projectType[0]) ||
|
|
8991
9521
|
projectType?.[0]?.startsWith("python")
|
|
@@ -8998,6 +9528,9 @@ export async function createBom(path, options) {
|
|
|
8998
9528
|
if (PROJECT_TYPE_ALIASES["rust"].includes(projectType[0])) {
|
|
8999
9529
|
return await createRustBom(path, options);
|
|
9000
9530
|
}
|
|
9531
|
+
if (PROJECT_TYPE_ALIASES["cargo-cache"].includes(projectType[0])) {
|
|
9532
|
+
return await createCargoCacheBom(getCargoCacheDir(), options);
|
|
9533
|
+
}
|
|
9001
9534
|
if (PROJECT_TYPE_ALIASES["php"].includes(projectType[0])) {
|
|
9002
9535
|
return createPHPBom(path, options);
|
|
9003
9536
|
}
|
|
@@ -9108,6 +9641,16 @@ export async function createBom(path, options) {
|
|
|
9108
9641
|
* @throws {Error} if the request fails
|
|
9109
9642
|
*/
|
|
9110
9643
|
export async function submitBom(args, bomContents) {
|
|
9644
|
+
if (isDryRun) {
|
|
9645
|
+
recordActivity({
|
|
9646
|
+
kind: "network",
|
|
9647
|
+
reason:
|
|
9648
|
+
"Dry run mode blocks Dependency-Track submission and reports the request instead.",
|
|
9649
|
+
status: "blocked",
|
|
9650
|
+
target: getDependencyTrackBomUrl(args.serverUrl),
|
|
9651
|
+
});
|
|
9652
|
+
return undefined;
|
|
9653
|
+
}
|
|
9111
9654
|
const serverUrl = getDependencyTrackBomUrl(args.serverUrl);
|
|
9112
9655
|
const bomPayload = buildDependencyTrackBomPayload(args, bomContents);
|
|
9113
9656
|
if (!bomPayload) {
|