@cdxgen/cdxgen 13.6.0 → 13.7.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 +15 -8
- package/bin/audit.js +7 -4
- package/bin/cdxgen.js +256 -37
- package/bin/convert.js +146 -22
- package/bin/evinse.js +25 -3
- package/bin/repl.js +47 -3
- package/bin/sign.js +211 -34
- package/bin/tracebom.js +18 -6
- package/bin/validate.js +18 -3
- package/bin/verify.js +113 -5
- package/data/behavior-taxonomy.schema.json +1491 -0
- package/data/cyclonedx-2.0-bundled.schema.json +18606 -5528
- package/data/cyclonedx-2.0-cryptography-defs.schema.json +857 -0
- package/data/pqc-migration.json +239 -0
- package/data/remediations.json +52 -0
- package/data/rules/cbom-security.yaml +4 -3
- package/data/rules/package-integrity.yaml +28 -0
- package/lib/audit/index.js +25 -3
- package/lib/cli/bomAssembly.js +80 -1
- package/lib/cli/cliOptions.js +121 -17
- package/lib/cli/index.js +609 -898
- package/lib/cli/jsBom.js +3 -0
- package/lib/cli/jvmBom.js +365 -40
- package/lib/cli/managedBom.js +19 -3
- package/lib/cli/nativeBom.js +10 -0
- package/lib/core/env.js +26 -0
- package/lib/core/fs.js +126 -3
- package/lib/core/globPatterns.js +218 -0
- package/lib/core/processTree.js +99 -12
- package/lib/core/projectConfig.js +332 -25
- package/lib/core/toolRegistry.js +15 -1
- package/lib/ecosystems/denoutils.js +2 -2
- package/lib/ecosystems/golem.js +3 -8
- package/lib/ecosystems/gradleutils.js +1082 -6
- package/lib/ecosystems/jsEvidence.js +90 -38
- package/lib/ecosystems/kosi.js +3 -5
- package/lib/ecosystems/npmVersionResolution.js +376 -0
- package/lib/ecosystems/parsers-python.js +89 -28
- package/lib/ecosystems/parsers-rust.js +117 -15
- package/lib/ecosystems/remote/huggingface.js +22 -0
- package/lib/ecosystems/rusi.js +2 -4
- package/lib/ecosystems/scalasem.js +2 -1
- package/lib/evinser/evinser.js +196 -34
- package/lib/evinser/scalasem.js +5 -1
- package/lib/helpers/agenticToolutils.js +112 -1
- package/lib/helpers/bomSigner.js +43 -9
- package/lib/helpers/jssSigner.js +1276 -0
- package/lib/inventory/agentBlueprint.js +193 -0
- package/lib/inventory/agentToolNames.js +145 -0
- package/lib/inventory/aiCollector.js +153 -7
- package/lib/inventory/aiInventory.js +44 -8
- package/lib/inventory/aiProviders.js +324 -0
- package/lib/inventory/bomUtils.js +8 -1
- package/lib/inventory/ciParsers/githubActionsLock.js +821 -0
- package/lib/inventory/citations.js +31 -2
- package/lib/inventory/communityAiConfigParser.js +978 -80
- package/lib/inventory/cyclonedx20.js +152 -0
- package/lib/inventory/cyclonedx20Common.js +286 -0
- package/lib/inventory/cyclonedx20Derived.js +159 -0
- package/lib/inventory/cyclonedx20Parties.js +552 -0
- package/lib/inventory/cyclonedx20Read.js +768 -0
- package/lib/inventory/cyclonedx20ReadCommon.js +374 -0
- package/lib/inventory/cyclonedx20ReadComponents.js +692 -0
- package/lib/inventory/cyclonedx20ReadContext.js +380 -0
- package/lib/inventory/cyclonedx20ReadEvidence.js +466 -0
- package/lib/inventory/cyclonedx20ReadSections.js +599 -0
- package/lib/inventory/cyclonedx20Render.js +766 -0
- package/lib/inventory/cyclonedx20RenderComponents.js +716 -0
- package/lib/inventory/cyclonedx20RenderDefinitions.js +405 -0
- package/lib/inventory/cyclonedx20RenderEvidence.js +726 -0
- package/lib/inventory/cyclonedx20RenderHardware.js +203 -0
- package/lib/inventory/cyclonedx20RenderPatents.js +174 -0
- package/lib/inventory/cyclonedx20RenderRefIds.js +314 -0
- package/lib/inventory/cyclonedx20RenderSections.js +499 -0
- package/lib/inventory/cyclonedx20Tables.js +594 -0
- package/lib/inventory/deps.js +106 -13
- package/lib/inventory/dosai.js +236 -1
- package/lib/inventory/dosaiParsers.js +3 -6
- package/lib/inventory/dotnetRuntime.js +164 -14
- package/lib/inventory/ecosystemFormulationParsers.js +979 -0
- package/lib/inventory/envcontext.js +132 -38
- package/lib/inventory/evidenceUtils.js +2 -1
- package/lib/inventory/formulationParsers.js +95 -13
- package/lib/inventory/hbom.js +45 -6
- package/lib/inventory/hbomLoader.js +166 -0
- package/lib/inventory/mcpConfigParser.js +5 -0
- package/lib/inventory/occurrenceKey.js +90 -0
- package/lib/inventory/pqcMigration.js +426 -0
- package/lib/inventory/rustFormulationParser.js +21 -10
- package/lib/inventory/source.js +65 -6
- package/lib/parsers/huggingfaceManifest.js +9 -1
- package/lib/parsers/huggingfaceUtils.js +18 -0
- package/lib/parsers/kiroPermissions.js +166 -0
- package/lib/server/server.js +36 -34
- package/lib/stages/postgen/postgen.js +41 -1
- package/lib/stages/postgen/specVersionCompat.js +76 -0
- package/lib/validator/bomValidator.js +8 -1
- package/lib/validator/complianceEngine.js +30 -3
- package/lib/validator/complianceRules.js +1416 -4
- package/lib/validator/generated/validate-2.0.mjs +57554 -13851
- package/lib/validator/index.js +48 -7
- package/lib/validator/reporters/json.js +6 -0
- package/package.json +9 -9
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +6 -2
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +16 -0
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +6 -0
- package/types/lib/cli/cliOptions.d.ts.map +1 -1
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/cli/jsBom.d.ts +2 -1
- package/types/lib/cli/jsBom.d.ts.map +1 -1
- package/types/lib/cli/jvmBom.d.ts +15 -0
- package/types/lib/cli/jvmBom.d.ts.map +1 -1
- package/types/lib/cli/managedBom.d.ts.map +1 -1
- package/types/lib/cli/nativeBom.d.ts.map +1 -1
- package/types/lib/core/boundedFile.d.ts +30 -0
- package/types/lib/core/boundedFile.d.ts.map +1 -1
- package/types/lib/core/env.d.ts +10 -0
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts +4 -0
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/globPatterns.d.ts +70 -0
- package/types/lib/core/globPatterns.d.ts.map +1 -0
- package/types/lib/core/paths.d.ts +9 -0
- package/types/lib/core/paths.d.ts.map +1 -1
- package/types/lib/core/processTree.d.ts +16 -5
- package/types/lib/core/processTree.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts +47 -8
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/toolRegistry.d.ts.map +1 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +248 -8
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/jsEvidence.d.ts +14 -1
- package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
- package/types/lib/ecosystems/kosi.d.ts.map +1 -1
- package/types/lib/ecosystems/npmVersionResolution.d.ts +119 -0
- package/types/lib/ecosystems/npmVersionResolution.d.ts.map +1 -0
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +1 -1
- package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts +58 -16
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +61 -9
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/scalasem.d.ts.map +1 -1
- package/types/lib/helpers/agenticToolutils.d.ts +53 -19
- package/types/lib/helpers/agenticToolutils.d.ts.map +1 -1
- package/types/lib/helpers/bomSigner.d.ts +20 -3
- package/types/lib/helpers/bomSigner.d.ts.map +1 -1
- package/types/lib/helpers/jssSigner.d.ts +288 -0
- package/types/lib/helpers/jssSigner.d.ts.map +1 -0
- package/types/lib/helpers/vsixutils.d.ts +303 -19
- package/types/lib/helpers/vsixutils.d.ts.map +1 -1
- package/types/lib/inventory/agentBlueprint.d.ts +70 -0
- package/types/lib/inventory/agentBlueprint.d.ts.map +1 -0
- package/types/lib/inventory/agentToolNames.d.ts +51 -0
- package/types/lib/inventory/agentToolNames.d.ts.map +1 -0
- package/types/lib/inventory/aiCollector.d.ts.map +1 -1
- package/types/lib/inventory/aiInventory.d.ts.map +1 -1
- package/types/lib/inventory/aiProviders.d.ts +85 -0
- package/types/lib/inventory/aiProviders.d.ts.map +1 -0
- package/types/lib/inventory/bomUtils.d.ts.map +1 -1
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts +101 -0
- package/types/lib/inventory/ciParsers/githubActionsLock.d.ts.map +1 -0
- package/types/lib/inventory/citations.d.ts +5 -0
- package/types/lib/inventory/citations.d.ts.map +1 -1
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/cyclonedx20.d.ts +99 -0
- package/types/lib/inventory/cyclonedx20.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts +102 -0
- package/types/lib/inventory/cyclonedx20Common.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts +74 -0
- package/types/lib/inventory/cyclonedx20Derived.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts +91 -0
- package/types/lib/inventory/cyclonedx20Parties.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts +51 -0
- package/types/lib/inventory/cyclonedx20Read.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts +69 -0
- package/types/lib/inventory/cyclonedx20ReadCommon.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts +77 -0
- package/types/lib/inventory/cyclonedx20ReadComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts +118 -0
- package/types/lib/inventory/cyclonedx20ReadContext.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts +40 -0
- package/types/lib/inventory/cyclonedx20ReadEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20ReadSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts +53 -0
- package/types/lib/inventory/cyclonedx20Render.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts +73 -0
- package/types/lib/inventory/cyclonedx20RenderComponents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts +29 -0
- package/types/lib/inventory/cyclonedx20RenderDefinitions.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts +110 -0
- package/types/lib/inventory/cyclonedx20RenderEvidence.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts +42 -0
- package/types/lib/inventory/cyclonedx20RenderHardware.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts +26 -0
- package/types/lib/inventory/cyclonedx20RenderPatents.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts +55 -0
- package/types/lib/inventory/cyclonedx20RenderRefIds.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts +45 -0
- package/types/lib/inventory/cyclonedx20RenderSections.d.ts.map +1 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts +134 -0
- package/types/lib/inventory/cyclonedx20Tables.d.ts.map +1 -0
- package/types/lib/inventory/deps.d.ts +35 -2
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +19 -0
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
- package/types/lib/inventory/dotnetRuntime.d.ts +51 -4
- package/types/lib/inventory/dotnetRuntime.d.ts.map +1 -1
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts +73 -0
- package/types/lib/inventory/ecosystemFormulationParsers.d.ts.map +1 -0
- package/types/lib/inventory/envcontext.d.ts +22 -6
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/hbom.d.ts +11 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomLoader.d.ts +54 -0
- package/types/lib/inventory/hbomLoader.d.ts.map +1 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts +5 -1
- package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -1
- package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/occurrenceKey.d.ts +52 -0
- package/types/lib/inventory/occurrenceKey.d.ts.map +1 -0
- package/types/lib/inventory/pqcMigration.d.ts +84 -0
- package/types/lib/inventory/pqcMigration.d.ts.map +1 -0
- package/types/lib/inventory/rustFormulationParser.d.ts +7 -2
- package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
- package/types/lib/inventory/scalaCoords.d.ts.map +1 -1
- package/types/lib/inventory/scalaDedupe.d.ts +43 -0
- package/types/lib/inventory/scalaDedupe.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +15 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts +10 -1
- package/types/lib/parsers/huggingfaceManifest.d.ts.map +1 -1
- package/types/lib/parsers/huggingfaceUtils.d.ts +12 -0
- package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
- package/types/lib/parsers/kiroPermissions.d.ts +62 -0
- package/types/lib/parsers/kiroPermissions.d.ts.map +1 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts +48 -0
- package/types/lib/parsers/vscodeExtensionId.d.ts.map +1 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts +7 -0
- 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/postgen/specVersionCompat.d.ts +25 -0
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts +5 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceEngine.d.ts +4 -4
- package/types/lib/validator/complianceEngine.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts +14 -2
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/index.d.ts +10 -0
- package/types/lib/validator/index.d.ts.map +1 -1
- package/types/lib/validator/reporters/json.d.ts.map +1 -1
package/lib/cli/jsBom.js
CHANGED
|
@@ -1073,6 +1073,7 @@ export async function createNodejsBom(path, options) {
|
|
|
1073
1073
|
allImports,
|
|
1074
1074
|
allExports,
|
|
1075
1075
|
options.deep,
|
|
1076
|
+
{ srcDir: path },
|
|
1076
1077
|
);
|
|
1077
1078
|
return buildBomNSData(options, pkgList, "npm", {
|
|
1078
1079
|
allImports,
|
|
@@ -1106,6 +1107,7 @@ export async function createNodejsBom(path, options) {
|
|
|
1106
1107
|
allImports,
|
|
1107
1108
|
allExports,
|
|
1108
1109
|
options.deep,
|
|
1110
|
+
{ srcDir: path, dependencies },
|
|
1109
1111
|
);
|
|
1110
1112
|
pkgList = propagateRequiredScopeFromDependencies(pkgList, dependencies);
|
|
1111
1113
|
pkgList = markNpmTypesPackagesAsExcluded(pkgList);
|
|
@@ -1551,6 +1553,7 @@ export async function createNodejsBom(path, options) {
|
|
|
1551
1553
|
allImports,
|
|
1552
1554
|
allExports,
|
|
1553
1555
|
options.deep,
|
|
1556
|
+
{ srcDir: path, dependencies, parentComponent },
|
|
1554
1557
|
);
|
|
1555
1558
|
if (mcpInventory.components?.length) {
|
|
1556
1559
|
pkgList = trimComponents(pkgList.concat(mcpInventory.components));
|
package/lib/cli/jvmBom.js
CHANGED
|
@@ -41,11 +41,14 @@ import {
|
|
|
41
41
|
} from "../core/projectTooling.js";
|
|
42
42
|
import { extractJarArchive, getMvnMetadata } from "../ecosystems/ecosystems.js";
|
|
43
43
|
import {
|
|
44
|
+
applyGradleVerificationMetadata,
|
|
44
45
|
buildGradleCommandArguments,
|
|
45
46
|
buildObjectForGradleModule,
|
|
46
47
|
collectGradleDependencies,
|
|
47
48
|
excludeGradleBuildTooling,
|
|
48
49
|
executeParallelGradleProperties,
|
|
50
|
+
findGradleLockfiles,
|
|
51
|
+
findGradleVerificationMetadata,
|
|
49
52
|
findMillDaemons,
|
|
50
53
|
getGradleCommand,
|
|
51
54
|
getMavenCommand,
|
|
@@ -53,14 +56,18 @@ import {
|
|
|
53
56
|
getMillVersion,
|
|
54
57
|
gradleArgsFromEnv,
|
|
55
58
|
gradleDependencyTasks,
|
|
59
|
+
gradleVerificationMainArtifact,
|
|
56
60
|
hasGradleInvocationFailure,
|
|
57
61
|
isProjectToolingAllowed,
|
|
58
62
|
loadGradleModulesForReports,
|
|
59
63
|
parseGradleDep,
|
|
60
64
|
parseGradleInfoLogsForUrls,
|
|
65
|
+
parseGradleLockfiles,
|
|
61
66
|
parseGradleProperties,
|
|
62
67
|
parseGradleResolvedDistributions,
|
|
68
|
+
parseGradleVerificationMetadata,
|
|
63
69
|
parseGradleVersionCatalog,
|
|
70
|
+
readGradleRootProjectName,
|
|
64
71
|
reconcileGradleComponents,
|
|
65
72
|
recordGradleInvocationFailure,
|
|
66
73
|
splitOutputByGradleProjects,
|
|
@@ -645,6 +652,33 @@ export async function createJavaBom(path, options) {
|
|
|
645
652
|
let jarNSMapping = {};
|
|
646
653
|
let pkgList = [];
|
|
647
654
|
let dependencies = [];
|
|
655
|
+
// The committed gradle/verification-metadata.xml of this build, if any,
|
|
656
|
+
// and the metadata parsed from it exactly once. These live at function
|
|
657
|
+
// scope because the fallback runs inside the Gradle block below while the
|
|
658
|
+
// enrichment runs after getMvnMetadata, outside the try that guards the
|
|
659
|
+
// per-tool sections, so a deferred failure keeps the enrichment too.
|
|
660
|
+
let gradleVerificationFile;
|
|
661
|
+
let gradleVerificationRootDir;
|
|
662
|
+
let gradleVerificationData;
|
|
663
|
+
let gradleVerificationParsed = false;
|
|
664
|
+
const gradleVerification = () => {
|
|
665
|
+
if (!gradleVerificationParsed) {
|
|
666
|
+
gradleVerificationParsed = true;
|
|
667
|
+
if (gradleVerificationFile) {
|
|
668
|
+
gradleVerificationData = parseGradleVerificationMetadata(
|
|
669
|
+
gradleVerificationFile,
|
|
670
|
+
{ rootDir: gradleVerificationRootDir },
|
|
671
|
+
);
|
|
672
|
+
if (gradleVerificationData) {
|
|
673
|
+
const { configuration } = gradleVerificationData;
|
|
674
|
+
thoughtLog(
|
|
675
|
+
`${gradleVerificationFile} records ${configuration.trustedKeyCount} trusted key(s), ${configuration.trustedArtifactRuleCount} trust rule(s), ${configuration.ignoredKeyCount} ignored key(s) and ${configuration.keyServerCount} key server(s).`,
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return gradleVerificationData;
|
|
681
|
+
};
|
|
648
682
|
// cyclone-dx-maven plugin creates a component for the app under metadata
|
|
649
683
|
// This is subsequently referred to in the dependencies list
|
|
650
684
|
let parentComponent = {};
|
|
@@ -1436,15 +1470,51 @@ export async function createJavaBom(path, options) {
|
|
|
1436
1470
|
"Hmm, there is a gradle.properties file. Do we need any private modules or custom JVM arguments for this project 🤔?",
|
|
1437
1471
|
);
|
|
1438
1472
|
}
|
|
1439
|
-
//
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1473
|
+
// The package-manager gate the Gradle invocations below share: a scan
|
|
1474
|
+
// that prefers another JVM build tool over Gradle reads no Gradle
|
|
1475
|
+
// lockfiles either.
|
|
1476
|
+
const gradleManagerAllowed = isPackageManagerAllowed(
|
|
1477
|
+
"gradle",
|
|
1478
|
+
["maven", "bazel", "sbt", "mill"],
|
|
1479
|
+
options,
|
|
1480
|
+
);
|
|
1481
|
+
// The committed Gradle dependency lockfiles record the resolved versions
|
|
1482
|
+
// of every locked configuration, so they are an inventory source that
|
|
1483
|
+
// needs no Gradle run. They are looked for only in a Gradle build: a
|
|
1484
|
+
// Maven-rooted scan does not pick up a nested sample's lockfile.
|
|
1485
|
+
const gradleLockFiles =
|
|
1486
|
+
gradleFiles?.length && gradleManagerAllowed
|
|
1487
|
+
? findGradleLockfiles(gradleRootPath, options)
|
|
1488
|
+
: [];
|
|
1489
|
+
// The committed gradle/verification-metadata.xml records the checksums
|
|
1490
|
+
// and PGP key ids Gradle verified when `gradle
|
|
1491
|
+
// --write-verification-metadata` last ran. Like the lockfiles, it is an
|
|
1492
|
+
// inventory source that needs no Gradle run, and it is looked for only in
|
|
1493
|
+
// a Gradle build.
|
|
1494
|
+
gradleVerificationFile =
|
|
1495
|
+
gradleFiles?.length && gradleManagerAllowed
|
|
1496
|
+
? findGradleVerificationMetadata(gradleRootPath)
|
|
1497
|
+
: undefined;
|
|
1498
|
+
gradleVerificationRootDir = gradleRootPath;
|
|
1499
|
+
// `gradle properties` evaluates the project's build scripts and `gradle
|
|
1500
|
+
// dependencies` resolves the graph, so both belong to the
|
|
1501
|
+
// dependency-tooling surface. The properties task runs whenever
|
|
1502
|
+
// `isProjectToolingAllowed` lets it, as it names the root project and
|
|
1503
|
+
// the subprojects; only the gradle-prefer-lockfile preference holds it
|
|
1504
|
+
// back. The dependencies task also needs `options.installDeps`. When
|
|
1505
|
+
// either check would stop the dependencies task, or when the preference
|
|
1506
|
+
// asks for it, the lockfiles supply the components instead.
|
|
1507
|
+
const gradleToolingAllowed = isProjectToolingAllowed(options);
|
|
1508
|
+
const gradlePreferLockfile = isFeatureEnabled(
|
|
1509
|
+
options,
|
|
1510
|
+
"gradle-prefer-lockfile",
|
|
1511
|
+
);
|
|
1512
|
+
const gradleSkipProperties =
|
|
1513
|
+
gradlePreferLockfile && gradleLockFiles.length > 0;
|
|
1514
|
+
const gradleUseLockfiles =
|
|
1515
|
+
gradleLockFiles.length > 0 &&
|
|
1516
|
+
(gradlePreferLockfile || !gradleToolingAllowed || !options.installDeps);
|
|
1517
|
+
if (gradleFiles?.length && gradleManagerAllowed) {
|
|
1448
1518
|
const wrapperInfo = readGradleWrapperVersion(gradleRootPath);
|
|
1449
1519
|
if (wrapperInfo) {
|
|
1450
1520
|
try {
|
|
@@ -1506,6 +1576,177 @@ export async function createJavaBom(path, options) {
|
|
|
1506
1576
|
// ignore
|
|
1507
1577
|
}
|
|
1508
1578
|
}
|
|
1579
|
+
}
|
|
1580
|
+
// A module of this build that another one consumes by its coordinates is
|
|
1581
|
+
// a project, not a dependency, so the fallback sources below drop it.
|
|
1582
|
+
const dropGradleModuleComponents = (pkgs) => {
|
|
1583
|
+
const moduleRefs = new Set(
|
|
1584
|
+
[parentComponent, ...(parentComponent?.components || [])]
|
|
1585
|
+
.map((c) => c?.["bom-ref"])
|
|
1586
|
+
.filter(Boolean),
|
|
1587
|
+
);
|
|
1588
|
+
return pkgs.filter((pkg) => !moduleRefs.has(pkg["bom-ref"]));
|
|
1589
|
+
};
|
|
1590
|
+
// Without `gradle properties` nothing named the root project. The
|
|
1591
|
+
// settings script names it, and the directory name stands in when it
|
|
1592
|
+
// does not, so the BOM still has a primary component.
|
|
1593
|
+
const ensureGradleParentComponent = () => {
|
|
1594
|
+
if (!parentComponent || !Object.keys(parentComponent).length) {
|
|
1595
|
+
const rootProjectName = readGradleRootProjectName(gradleRootPath);
|
|
1596
|
+
parentComponent = createDefaultParentComponent(
|
|
1597
|
+
gradleRootPath,
|
|
1598
|
+
"maven",
|
|
1599
|
+
rootProjectName && !("project-name" in options)
|
|
1600
|
+
? {
|
|
1601
|
+
...options,
|
|
1602
|
+
"project-name": rootProjectName,
|
|
1603
|
+
projectName: rootProjectName,
|
|
1604
|
+
}
|
|
1605
|
+
: options,
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1609
|
+
// The lockfiles stand in for the Gradle dependency resolution this scan
|
|
1610
|
+
// is not making, prefers not to make, or that produced nothing. They
|
|
1611
|
+
// record resolved versions but no graph, so the components carry no
|
|
1612
|
+
// dependency edges and the scan records what that costs. Returns the
|
|
1613
|
+
// number of components added.
|
|
1614
|
+
const addGradleLockfileComponents = () => {
|
|
1615
|
+
const lockfilePkgs = dropGradleModuleComponents(
|
|
1616
|
+
parseGradleLockfiles(gradleLockFiles, {
|
|
1617
|
+
rootDir: gradleRootPath,
|
|
1618
|
+
}),
|
|
1619
|
+
);
|
|
1620
|
+
if (!lockfilePkgs.length) {
|
|
1621
|
+
return 0;
|
|
1622
|
+
}
|
|
1623
|
+
pkgList = pkgList.concat(lockfilePkgs);
|
|
1624
|
+
recordDegradation("jvm.gradle.lockfile-only", {
|
|
1625
|
+
ecosystem: "java",
|
|
1626
|
+
tool: "gradle",
|
|
1627
|
+
impact: "transitive-deps",
|
|
1628
|
+
detail:
|
|
1629
|
+
"The components came from Gradle dependency lockfiles, which record no dependency graph between them.",
|
|
1630
|
+
});
|
|
1631
|
+
ensureGradleParentComponent();
|
|
1632
|
+
return lockfilePkgs.length;
|
|
1633
|
+
};
|
|
1634
|
+
// The version catalog and, on request, the verification file declare
|
|
1635
|
+
// coordinates without resolving them, so both are used only when Gradle
|
|
1636
|
+
// and the lockfiles produced no dependency information at all. The call
|
|
1637
|
+
// inside the Gradle run block happens before its failure paths, so a
|
|
1638
|
+
// build whose static sources resolved it is not degraded twice and not
|
|
1639
|
+
// failed with --fail-on-error over a BOM that has components. The
|
|
1640
|
+
// verification fallback stays off unless the
|
|
1641
|
+
// gradle-verification-fallback feature flag asks for it: the file
|
|
1642
|
+
// records what the build resolved when --write-verification-metadata
|
|
1643
|
+
// ran, which may be stale, and its components can only be optional.
|
|
1644
|
+
// Both belong to a Gradle build, so a scan without Gradle build files,
|
|
1645
|
+
// or one that prefers another JVM build tool, reads neither.
|
|
1646
|
+
const addGradleStaticFallbackComponents = () => {
|
|
1647
|
+
if (!gradleFiles?.length || !gradleManagerAllowed || pkgList.length) {
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
const catalogFiles = getAllFiles(
|
|
1651
|
+
path,
|
|
1652
|
+
`${options.multiProject ? "**/" : ""}gradle/libs.versions.toml`,
|
|
1653
|
+
options,
|
|
1654
|
+
);
|
|
1655
|
+
for (const catalogFile of catalogFiles) {
|
|
1656
|
+
if (DEBUG_MODE) {
|
|
1657
|
+
console.log(`Parsing ${catalogFile}`);
|
|
1658
|
+
}
|
|
1659
|
+
const dlist = parseGradleVersionCatalog(catalogFile);
|
|
1660
|
+
if (dlist?.length) {
|
|
1661
|
+
pkgList = pkgList.concat(dlist);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
if (
|
|
1665
|
+
pkgList.length ||
|
|
1666
|
+
!gradleVerificationFile ||
|
|
1667
|
+
!isFeatureEnabled(options, "gradle-verification-fallback")
|
|
1668
|
+
) {
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
const verificationMetadata = gradleVerification();
|
|
1672
|
+
if (!verificationMetadata) {
|
|
1673
|
+
return;
|
|
1674
|
+
}
|
|
1675
|
+
const verificationPkgs = [];
|
|
1676
|
+
for (const component of verificationMetadata.components.values()) {
|
|
1677
|
+
// A Gradle plugin marker coordinate publishes only a POM that
|
|
1678
|
+
// points at the real plugin, so it is not a dependency of the
|
|
1679
|
+
// build, and a coordinate without a main artifact is a parent or a
|
|
1680
|
+
// BOM rather than a component of this BOM.
|
|
1681
|
+
if (component.name.endsWith(".gradle.plugin")) {
|
|
1682
|
+
continue;
|
|
1683
|
+
}
|
|
1684
|
+
if (!gradleVerificationMainArtifact(component, false)) {
|
|
1685
|
+
continue;
|
|
1686
|
+
}
|
|
1687
|
+
const purl = mavenPurl(
|
|
1688
|
+
component.group,
|
|
1689
|
+
component.name,
|
|
1690
|
+
component.version,
|
|
1691
|
+
{
|
|
1692
|
+
type: "jar",
|
|
1693
|
+
},
|
|
1694
|
+
);
|
|
1695
|
+
if (!purl) {
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1698
|
+
verificationPkgs.push({
|
|
1699
|
+
group: component.group,
|
|
1700
|
+
name: component.name,
|
|
1701
|
+
version: component.version,
|
|
1702
|
+
qualifiers: { type: "jar" },
|
|
1703
|
+
type: "library",
|
|
1704
|
+
// A component with no scope counts as required, and the file
|
|
1705
|
+
// cannot tell a runtime dependency from build tooling, so the
|
|
1706
|
+
// components are optional.
|
|
1707
|
+
scope: "optional",
|
|
1708
|
+
purl,
|
|
1709
|
+
"bom-ref": decodeURIComponent(purl),
|
|
1710
|
+
// The digests are merged in at the end of the scan, from the file
|
|
1711
|
+
// or from the artifact itself when the local cache holds it.
|
|
1712
|
+
properties: [
|
|
1713
|
+
{ name: "internal:SrcFile", value: gradleVerificationFile },
|
|
1714
|
+
{ name: "cdx:gradle:verificationMetadata", value: "true" },
|
|
1715
|
+
],
|
|
1716
|
+
evidence: {
|
|
1717
|
+
identity: {
|
|
1718
|
+
field: "purl",
|
|
1719
|
+
confidence: 1,
|
|
1720
|
+
concludedValue: purl,
|
|
1721
|
+
methods: [
|
|
1722
|
+
{
|
|
1723
|
+
technique: "manifest-analysis",
|
|
1724
|
+
confidence: 1,
|
|
1725
|
+
value: gradleVerificationFile,
|
|
1726
|
+
},
|
|
1727
|
+
],
|
|
1728
|
+
},
|
|
1729
|
+
},
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
const addedPkgs = dropGradleModuleComponents(verificationPkgs);
|
|
1733
|
+
if (addedPkgs.length) {
|
|
1734
|
+
pkgList = pkgList.concat(addedPkgs);
|
|
1735
|
+
recordDegradation("jvm.gradle.verification-metadata-only", {
|
|
1736
|
+
ecosystem: "java",
|
|
1737
|
+
tool: "gradle",
|
|
1738
|
+
impact: "transitive-deps",
|
|
1739
|
+
detail:
|
|
1740
|
+
"The components came from gradle/verification-metadata.xml, which records no dependency graph between them.",
|
|
1741
|
+
});
|
|
1742
|
+
ensureGradleParentComponent();
|
|
1743
|
+
thoughtLog(
|
|
1744
|
+
`Obtained ${addedPkgs.length} components from ${gradleVerificationFile}. It says nothing about which module depends on which, and nothing about scopes.`,
|
|
1745
|
+
);
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
// Execute gradle properties
|
|
1749
|
+
if (gradleFiles?.length && gradleManagerAllowed && !gradleSkipProperties) {
|
|
1509
1750
|
let includedBuilds = [];
|
|
1510
1751
|
let allProjectsStr = [];
|
|
1511
1752
|
if (readEnvironmentVariable("GRADLE_INCLUDED_BUILDS")) {
|
|
@@ -1529,10 +1770,6 @@ export async function createJavaBom(path, options) {
|
|
|
1529
1770
|
if (resolveGradleDistribution && gradleInitArgs.length) {
|
|
1530
1771
|
gradleInitArgs.push("-PcdxgenResolveDistribution=true");
|
|
1531
1772
|
}
|
|
1532
|
-
// `gradle properties` evaluates the project's build scripts, so it is
|
|
1533
|
-
// part of the dependency-tooling surface gated by --no-install-deps
|
|
1534
|
-
// (and the pre-build lifecycle).
|
|
1535
|
-
const gradleToolingAllowed = isProjectToolingAllowed(options);
|
|
1536
1773
|
if (gradleToolingAllowed) {
|
|
1537
1774
|
parallelPropTaskOut = executeParallelGradleProperties(
|
|
1538
1775
|
gradleRootPath,
|
|
@@ -1712,14 +1949,39 @@ export async function createJavaBom(path, options) {
|
|
|
1712
1949
|
});
|
|
1713
1950
|
}
|
|
1714
1951
|
}
|
|
1952
|
+
if (gradleUseLockfiles) {
|
|
1953
|
+
const lockfileCount = addGradleLockfileComponents();
|
|
1954
|
+
if (lockfileCount) {
|
|
1955
|
+
console.log(
|
|
1956
|
+
`Using the dependencies locked by ${gradleLockFiles.length} Gradle lockfile(s) instead of executing 'gradle dependencies'.`,
|
|
1957
|
+
);
|
|
1958
|
+
thoughtLog(
|
|
1959
|
+
`Obtained ${lockfileCount} components from ${gradleLockFiles.length} Gradle lockfile(s). A lockfile is flat, so it says nothing about which module depends on which.`,
|
|
1960
|
+
);
|
|
1961
|
+
// --deep reads the jar namespaces of the versions the local Gradle
|
|
1962
|
+
// cache holds, as it does after a Gradle run; a cold cache yields
|
|
1963
|
+
// nothing.
|
|
1964
|
+
if (options.resolveClass || options.deep) {
|
|
1965
|
+
const tmpjarNSMapping = await collectJarNS(GRADLE_CACHE_DIR);
|
|
1966
|
+
if (tmpjarNSMapping && Object.keys(tmpjarNSMapping).length) {
|
|
1967
|
+
jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
} else {
|
|
1971
|
+
thoughtLog(
|
|
1972
|
+
"The Gradle lockfiles yielded no components, so the remaining static sources are tried.",
|
|
1973
|
+
);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
// Components that came from somewhere other than this Gradle run, such
|
|
1977
|
+
// as a Maven build in the same root, so the decisions below look only at
|
|
1978
|
+
// what Gradle itself produced.
|
|
1979
|
+
const pkgCountBeforeGradleRun = pkgList.length;
|
|
1715
1980
|
if (
|
|
1716
1981
|
gradleFiles?.length &&
|
|
1717
1982
|
options.installDeps &&
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
["maven", "bazel", "sbt", "mill"],
|
|
1721
|
-
options,
|
|
1722
|
-
)
|
|
1983
|
+
gradleManagerAllowed &&
|
|
1984
|
+
!gradleUseLockfiles
|
|
1723
1985
|
) {
|
|
1724
1986
|
allProjects.push(parentComponent);
|
|
1725
1987
|
const gradleCmd = getGradleCommand(gradleRootPath, null, options);
|
|
@@ -1848,6 +2110,23 @@ export async function createJavaBom(path, options) {
|
|
|
1848
2110
|
}
|
|
1849
2111
|
reconcileGradleComponents(pkgList);
|
|
1850
2112
|
}
|
|
2113
|
+
const gradleRunPkgCount = pkgList.length - pkgCountBeforeGradleRun;
|
|
2114
|
+
if (!gradleRunPkgCount && gradleLockFiles.length) {
|
|
2115
|
+
// Gradle produced no components of its own. The lockfiles are the
|
|
2116
|
+
// next source before the failure paths below: Gradle may have run
|
|
2117
|
+
// fine over configurations the project never locked, or failed
|
|
2118
|
+
// outright while the committed lockfiles still describe the build.
|
|
2119
|
+
const lockfileCount = addGradleLockfileComponents();
|
|
2120
|
+
if (lockfileCount) {
|
|
2121
|
+
thoughtLog(
|
|
2122
|
+
`Gradle produced no components, so the ${lockfileCount} components of ${gradleLockFiles.length} Gradle lockfile(s) were used instead.`,
|
|
2123
|
+
);
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
// A catalog or verification fallback can supply these components when
|
|
2127
|
+
// Gradle produced none, so they pass through the same distribution and
|
|
2128
|
+
// subproject handling below.
|
|
2129
|
+
addGradleStaticFallbackComponents();
|
|
1851
2130
|
if (pkgList.length) {
|
|
1852
2131
|
const fileToUrlMap = parseGradleInfoLogsForUrls(sstdout);
|
|
1853
2132
|
// When the `resolve-gradle-distribution` feature flag is enabled, the init script
|
|
@@ -1894,11 +2173,21 @@ export async function createJavaBom(path, options) {
|
|
|
1894
2173
|
}
|
|
1895
2174
|
}
|
|
1896
2175
|
thoughtLog(
|
|
1897
|
-
|
|
2176
|
+
gradleRunPkgCount
|
|
2177
|
+
? `Obtained ${pkgList.length} components by executing the '${basename(gradleCmd)}' command.`
|
|
2178
|
+
: `Obtained ${pkgList.length} components from the static Gradle sources after '${basename(gradleCmd)}' produced none.`,
|
|
1898
2179
|
);
|
|
1899
2180
|
if (DEBUG_MODE) {
|
|
1900
2181
|
console.log("Obtained", pkgList.length, "from this gradle project.");
|
|
1901
2182
|
}
|
|
2183
|
+
if (gradleRunPkgCount && gradleLockFiles.length) {
|
|
2184
|
+
// Gradle resolved against the lockfiles itself, so the versions it
|
|
2185
|
+
// reports already are the locked ones and parsing the files again
|
|
2186
|
+
// would add nothing.
|
|
2187
|
+
thoughtLog(
|
|
2188
|
+
`Gradle enforced the ${gradleLockFiles.length} Gradle lockfile(s) of this build, so they are not parsed separately.`,
|
|
2189
|
+
);
|
|
2190
|
+
}
|
|
1902
2191
|
} else if (hasGradleInvocationFailure()) {
|
|
1903
2192
|
// The invocation failure is already ranked, and an empty
|
|
1904
2193
|
// configuration is what that failure looks like from here: reporting
|
|
@@ -1964,29 +2253,14 @@ export async function createJavaBom(path, options) {
|
|
|
1964
2253
|
jarNSMapping = { ...jarNSMapping, ...tmpjarNSMapping };
|
|
1965
2254
|
}
|
|
1966
2255
|
}
|
|
1967
|
-
|
|
1968
|
-
// A version catalog declares coordinates without resolving them, so it
|
|
1969
|
-
// is used only when Gradle produced no dependency information at all.
|
|
1970
|
-
// The emitted components carry cdx:gradle:catalog=true to mark them as
|
|
1971
|
-
// declared rather than resolved.
|
|
1972
|
-
if (!pkgList.length) {
|
|
1973
|
-
const catalogFiles = getAllFiles(
|
|
1974
|
-
path,
|
|
1975
|
-
`${options.multiProject ? "**/" : ""}gradle/libs.versions.toml`,
|
|
1976
|
-
options,
|
|
1977
|
-
);
|
|
1978
|
-
for (const catalogFile of catalogFiles) {
|
|
1979
|
-
if (DEBUG_MODE) {
|
|
1980
|
-
console.log(`Parsing ${catalogFile}`);
|
|
1981
|
-
}
|
|
1982
|
-
const dlist = parseGradleVersionCatalog(catalogFile);
|
|
1983
|
-
if (dlist?.length) {
|
|
1984
|
-
pkgList = pkgList.concat(dlist);
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
}
|
|
1988
2256
|
}
|
|
1989
2257
|
|
|
2258
|
+
// Outside the installDeps block on purpose: a scan with dependency
|
|
2259
|
+
// installation disabled reaches the static sources through the lockfile
|
|
2260
|
+
// path instead of the Gradle run, and a scan whose Gradle run was
|
|
2261
|
+
// skipped entirely needs them here.
|
|
2262
|
+
addGradleStaticFallbackComponents();
|
|
2263
|
+
|
|
1990
2264
|
// Bazel
|
|
1991
2265
|
// Look for the BUILD file only in the root directory
|
|
1992
2266
|
// NOTE: This can match BUILD files used by perl, so could lead to errors in some projects
|
|
@@ -2907,6 +3181,57 @@ export async function createJavaBom(path, options) {
|
|
|
2907
3181
|
pkgList = await getMvnMetadata(pkgList, jarNSMapping, false, {
|
|
2908
3182
|
skipPurls: ownComponentRefs(parentComponent),
|
|
2909
3183
|
});
|
|
3184
|
+
// The verification file is the last enrichment, after getMvnMetadata has
|
|
3185
|
+
// hashed the jars of the local cache: a digest of the artifact itself is
|
|
3186
|
+
// the stronger claim, so the recorded digests only fill the algorithms a
|
|
3187
|
+
// component still lacks, and a differing digest of the same algorithm is
|
|
3188
|
+
// flagged, never applied. Whatever source found the component keeps the
|
|
3189
|
+
// identity evidence of that source.
|
|
3190
|
+
if (gradleVerificationFile) {
|
|
3191
|
+
const verificationMetadata = gradleVerification();
|
|
3192
|
+
if (verificationMetadata) {
|
|
3193
|
+
const enrichedCount = applyGradleVerificationMetadata(
|
|
3194
|
+
pkgList,
|
|
3195
|
+
verificationMetadata,
|
|
3196
|
+
gradleVerificationFile,
|
|
3197
|
+
);
|
|
3198
|
+
if (enrichedCount) {
|
|
3199
|
+
thoughtLog(
|
|
3200
|
+
`Enriched ${enrichedCount} component(s) with the checksums that ${gradleVerificationFile} records.`,
|
|
3201
|
+
);
|
|
3202
|
+
}
|
|
3203
|
+
// Whether Gradle verified metadata and signatures is a fact about the
|
|
3204
|
+
// whole build, so it lands on the primary component. Only the flags
|
|
3205
|
+
// the file actually writes are emitted.
|
|
3206
|
+
const { configuration } = verificationMetadata;
|
|
3207
|
+
if (parentComponent && Object.keys(parentComponent).length) {
|
|
3208
|
+
const parentProperties = parentComponent.properties || [];
|
|
3209
|
+
if (
|
|
3210
|
+
configuration.verifyMetadata !== undefined &&
|
|
3211
|
+
!parentProperties.some((p) => p.name === "cdx:gradle:verifyMetadata")
|
|
3212
|
+
) {
|
|
3213
|
+
parentProperties.push({
|
|
3214
|
+
name: "cdx:gradle:verifyMetadata",
|
|
3215
|
+
value: String(configuration.verifyMetadata),
|
|
3216
|
+
});
|
|
3217
|
+
}
|
|
3218
|
+
if (
|
|
3219
|
+
configuration.verifySignatures !== undefined &&
|
|
3220
|
+
!parentProperties.some(
|
|
3221
|
+
(p) => p.name === "cdx:gradle:verifySignatures",
|
|
3222
|
+
)
|
|
3223
|
+
) {
|
|
3224
|
+
parentProperties.push({
|
|
3225
|
+
name: "cdx:gradle:verifySignatures",
|
|
3226
|
+
value: String(configuration.verifySignatures),
|
|
3227
|
+
});
|
|
3228
|
+
}
|
|
3229
|
+
if (parentProperties.length) {
|
|
3230
|
+
parentComponent.properties = parentProperties;
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
2910
3235
|
return buildBomNSData(options, pkgList, "maven", {
|
|
2911
3236
|
src: path,
|
|
2912
3237
|
nsMapping: jarNSMapping,
|
package/lib/cli/managedBom.js
CHANGED
|
@@ -147,6 +147,7 @@ import {
|
|
|
147
147
|
dosaiFailureReported,
|
|
148
148
|
dosaiMethodsSectionsArgument,
|
|
149
149
|
dosaiReportFileOmittedSections,
|
|
150
|
+
dosaiSlicesFileIsFresh,
|
|
150
151
|
dosaiToolComponents,
|
|
151
152
|
isDosaiDotnetLanguage,
|
|
152
153
|
normalizeDosaiServiceMap,
|
|
@@ -2505,9 +2506,13 @@ export async function createCsharpBom(path, options) {
|
|
|
2505
2506
|
// Anything else needs only the sections cdxgen reads, so dosai
|
|
2506
2507
|
// leaves the rest out (Metadata.OmittedSections names it).
|
|
2507
2508
|
const willRunEvinse = runsEvidenceAnalysis(options);
|
|
2508
|
-
// Reuse an existing slice as-is, with
|
|
2509
|
+
// Reuse an existing slice as-is, with two exceptions. A trimmed file
|
|
2509
2510
|
// (an earlier --deep run left it behind) is regenerated full before
|
|
2510
|
-
// an evidence run uses it, so dosai still runs once per scan.
|
|
2511
|
+
// an evidence run uses it, so dosai still runs once per scan. A slice
|
|
2512
|
+
// older than the sources it describes is regenerated for every run:
|
|
2513
|
+
// it holds the occurrences of the sources as they were when it was
|
|
2514
|
+
// written, so reusing one keeps occurrences of call sites that no
|
|
2515
|
+
// longer exist (issue 4675).
|
|
2511
2516
|
let reuseExisting = safeExistsSync(slicesFile);
|
|
2512
2517
|
if (reuseExisting && willRunEvinse) {
|
|
2513
2518
|
const omitted = dosaiReportFileOmittedSections(slicesFile);
|
|
@@ -2520,6 +2525,17 @@ export async function createCsharpBom(path, options) {
|
|
|
2520
2525
|
reuseExisting = false;
|
|
2521
2526
|
}
|
|
2522
2527
|
}
|
|
2528
|
+
if (
|
|
2529
|
+
reuseExisting &&
|
|
2530
|
+
!dosaiSlicesFileIsFresh(slicesFile, path, options)
|
|
2531
|
+
) {
|
|
2532
|
+
if (DEBUG_MODE) {
|
|
2533
|
+
console.log(
|
|
2534
|
+
`The existing dosai methods slice "${slicesFile}" is older than the sources it describes; regenerating it.`,
|
|
2535
|
+
);
|
|
2536
|
+
}
|
|
2537
|
+
reuseExisting = false;
|
|
2538
|
+
}
|
|
2523
2539
|
// Create the slices file if it doesn't exist
|
|
2524
2540
|
if (!reuseExisting) {
|
|
2525
2541
|
thoughtLog(
|
|
@@ -2551,7 +2567,7 @@ export async function createCsharpBom(path, options) {
|
|
|
2551
2567
|
}
|
|
2552
2568
|
} else if (DEBUG_MODE) {
|
|
2553
2569
|
console.log(
|
|
2554
|
-
`Reusing the existing dosai methods slice "${slicesFile}"
|
|
2570
|
+
`Reusing the existing dosai methods slice "${slicesFile}", which is newer than the sources it describes. The slice is still not checked against the current --exclude patterns; delete the file to force a fresh run.`,
|
|
2555
2571
|
);
|
|
2556
2572
|
}
|
|
2557
2573
|
pkgList = addEvidenceForDotnet(pkgList, slicesFile, {
|
package/lib/cli/nativeBom.js
CHANGED
|
@@ -1429,6 +1429,16 @@ export async function createDartBom(path, options) {
|
|
|
1429
1429
|
pkgList = pkgList.concat(retMap.pkgList);
|
|
1430
1430
|
}
|
|
1431
1431
|
if (retMap?.rootList?.length) {
|
|
1432
|
+
// A pubspec.lock read without its pubspec.yaml still names the
|
|
1433
|
+
// project's direct dependencies; the project is then named after the
|
|
1434
|
+
// directory that holds the lock file.
|
|
1435
|
+
if (!parentComponent) {
|
|
1436
|
+
parentComponent = createDefaultParentComponent(
|
|
1437
|
+
dirname(f),
|
|
1438
|
+
"generic",
|
|
1439
|
+
options,
|
|
1440
|
+
);
|
|
1441
|
+
}
|
|
1432
1442
|
const thisParentDependsOn = [
|
|
1433
1443
|
{
|
|
1434
1444
|
ref: parentComponent["bom-ref"],
|
package/lib/core/env.js
CHANGED
|
@@ -541,6 +541,32 @@ export const PROJECT_TYPE_ALIASES = {
|
|
|
541
541
|
"ai-provenance": ["ai-provenance", "ai-authorship", "aicode", "ai-codegen"],
|
|
542
542
|
};
|
|
543
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Project types, with their aliases, that inventory the host cdxgen runs on
|
|
546
|
+
* rather than the scan path: installed packages, users, shell history, IDE
|
|
547
|
+
* and browser extensions, or the Maven, Gradle, sbt, Cargo and Helm caches in
|
|
548
|
+
* the user's home directory. Only the operator may select them; neither a
|
|
549
|
+
* server request nor a config file in the scanned directory can.
|
|
550
|
+
*
|
|
551
|
+
* @type {Set<string>}
|
|
552
|
+
*/
|
|
553
|
+
export const HOST_SCOPE_PROJECT_TYPES = new Set(
|
|
554
|
+
[
|
|
555
|
+
"os",
|
|
556
|
+
"hbom",
|
|
557
|
+
"cargo-cache",
|
|
558
|
+
"helm-index",
|
|
559
|
+
"gradle-index",
|
|
560
|
+
"sbt-index",
|
|
561
|
+
"maven-index",
|
|
562
|
+
"vscode-extension",
|
|
563
|
+
"chrome-extension",
|
|
564
|
+
"agentic",
|
|
565
|
+
]
|
|
566
|
+
.flatMap((key) => PROJECT_TYPE_ALIASES[key] || [key])
|
|
567
|
+
.concat(["maven-repo"]),
|
|
568
|
+
);
|
|
569
|
+
|
|
544
570
|
/** Map of base package manager to the array of accepted alias strings. */
|
|
545
571
|
export const PACKAGE_MANAGER_ALIASES = {
|
|
546
572
|
scala: ["sbt"],
|