@cdxgen/cdxgen 13.4.0 → 13.5.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 +7 -7
- package/bin/cdxgen-secure.js +15 -0
- package/bin/cdxgen.js +25 -5
- package/bin/evinse.js +5 -0
- package/bin/hbom.js +15 -7
- package/bin/repl.js +29 -0
- package/data/cbomosdb-queries.json +13 -1
- package/data/component-tags.json +8 -0
- package/data/queries-darwin.json +25 -1
- package/data/queries-win.json +19 -1
- package/data/queries.json +41 -0
- package/data/remediations.json +283 -1
- package/data/rules/cbom-security.yaml +235 -4
- package/data/rules/go-binaries.yaml +46 -0
- package/data/rules/golem-go.yaml +80 -0
- package/data/rules/hbom-compliance.yaml +40 -22
- package/data/rules/hbom-performance.yaml +7 -1
- package/data/rules/host-topology.yaml +1 -1
- package/data/rules/obom-runtime.yaml +31 -2
- package/data/rules/php-runtime.yaml +143 -0
- package/lib/audit/index.js +14 -0
- package/lib/cli/bomAssembly.js +28 -3
- package/lib/cli/cliOptions.js +110 -3
- package/lib/cli/index.js +73 -4
- package/lib/cli/jvmBom.js +126 -20
- package/lib/cli/managedBom.js +711 -71
- package/lib/cli/nativeBom.js +225 -28
- package/lib/core/env.js +30 -8
- package/lib/core/fs.js +28 -19
- package/lib/core/httpClient.js +74 -45
- package/lib/core/projectConfig.js +1 -0
- package/lib/core/projectTooling.js +97 -0
- package/lib/core/propertySanitizer.js +72 -0
- package/lib/ecosystems/golem.js +550 -6
- package/lib/ecosystems/gradleutils.js +30 -20
- package/lib/ecosystems/parsers-dotnet.js +117 -18
- package/lib/ecosystems/parsers-go.js +1090 -367
- package/lib/ecosystems/parsers-jvm.js +259 -17
- package/lib/ecosystems/parsers-misc.js +229 -44
- package/lib/ecosystems/parsers-python.js +11 -10
- package/lib/ecosystems/rubyutils.js +6 -3
- package/lib/ecosystems/rusi.js +10 -0
- package/lib/ecosystems/scalacliutils.js +2 -1
- package/lib/ecosystems/scalasem.js +3 -1
- package/lib/evinser/evinser.js +126 -18
- package/lib/evinser/swiftsem.js +68 -5
- package/lib/inventory/agentSkillSpec.js +17 -0
- package/lib/inventory/apkInstalledDb.js +243 -0
- package/lib/inventory/atomUtils.js +33 -0
- package/lib/inventory/auditCategories.js +3 -3
- package/lib/inventory/cacheDir.js +52 -9
- package/lib/inventory/certificates.js +2371 -0
- package/lib/inventory/communityAiConfigParser.js +4 -9
- package/lib/inventory/deps.js +6 -4
- package/lib/inventory/display.js +200 -3
- package/lib/inventory/dosai.js +500 -58
- package/lib/inventory/dynamic.js +45 -3
- package/lib/inventory/envcontext.js +168 -5
- package/lib/inventory/evidenceUtils.js +436 -23
- package/lib/inventory/formulationParsers.js +3 -2
- package/lib/inventory/goBuildInfo.js +140 -0
- package/lib/inventory/hbom.js +67 -7
- package/lib/inventory/hbomAnalysis.js +16 -0
- package/lib/inventory/hostTopology.js +21 -0
- package/lib/inventory/osPackagePurl.js +244 -0
- package/lib/inventory/osPackageResolver.js +89 -87
- package/lib/inventory/osinfo.js +79 -31
- package/lib/inventory/osqueryTransform.js +114 -5
- package/lib/inventory/phpBuildInfo.js +487 -0
- package/lib/inventory/phpHostProbe.js +641 -0
- package/lib/inventory/rootfsCerts.js +426 -0
- package/lib/inventory/source.js +207 -3
- package/lib/inventory/spdx.js +144 -0
- package/lib/inventory/traceRunner.js +5 -1
- package/lib/inventory/tracedCrypto.js +129 -0
- package/lib/managers/binary.js +529 -183
- package/lib/managers/docker.js +166 -12
- package/lib/parsers/email.js +277 -0
- package/lib/parsers/largeJson.js +34 -2
- package/lib/server/server.js +186 -1
- package/lib/stages/postgen/annotator.js +17 -1
- package/lib/stages/postgen/introspection/reflect.js +4 -1
- package/lib/stages/postgen/postgen.js +5 -5
- package/lib/stages/postgen/ruleEngine.js +58 -1
- package/lib/stages/postgen/specVersionCompat.js +30 -0
- package/lib/stages/pregen/pregen.js +117 -5
- package/lib/validator/bomValidator.js +26 -5
- package/lib/validator/generated/runtime.mjs +13 -0
- package/lib/validator/generated/validate-1.6.mjs +26 -7
- package/lib/validator/generated/validate-1.7.mjs +31 -12
- package/lib/validator/generated/validate-2.0.mjs +30 -11
- package/package.json +17 -17
- package/types/bin/cdxgen-secure.d.ts +3 -0
- package/types/bin/cdxgen-secure.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts.map +1 -1
- package/types/lib/cli/bomAssembly.d.ts +9 -2
- package/types/lib/cli/bomAssembly.d.ts.map +1 -1
- package/types/lib/cli/cliOptions.d.ts +43 -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/jvmBom.d.ts +20 -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/env.d.ts +18 -2
- package/types/lib/core/env.d.ts.map +1 -1
- package/types/lib/core/fs.d.ts.map +1 -1
- package/types/lib/core/httpClient.d.ts.map +1 -1
- package/types/lib/core/projectConfig.d.ts.map +1 -1
- package/types/lib/core/projectTooling.d.ts +41 -0
- package/types/lib/core/projectTooling.d.ts.map +1 -0
- package/types/lib/core/propertySanitizer.d.ts +26 -0
- package/types/lib/core/propertySanitizer.d.ts.map +1 -1
- package/types/lib/ecosystems/cppEvidence.d.ts +1 -1
- package/types/lib/ecosystems/golem.d.ts +81 -1
- package/types/lib/ecosystems/golem.d.ts.map +1 -1
- package/types/lib/ecosystems/gradleutils.d.ts +10 -8
- package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-dotnet.d.ts +40 -4
- package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-go.d.ts +85 -13
- package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-jvm.d.ts +28 -2
- package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-misc.d.ts +18 -58
- package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
- package/types/lib/ecosystems/parsers-python.d.ts +4 -3
- package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
- package/types/lib/ecosystems/pythonutils.d.ts +1 -1
- package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
- package/types/lib/ecosystems/rusi.d.ts.map +1 -1
- package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -1
- package/types/lib/ecosystems/scalasem.d.ts.map +1 -1
- package/types/lib/evinser/evinser.d.ts +25 -0
- package/types/lib/evinser/evinser.d.ts.map +1 -1
- package/types/lib/evinser/swiftsem.d.ts +10 -0
- package/types/lib/evinser/swiftsem.d.ts.map +1 -1
- package/types/lib/inventory/agentSkillSpec.d.ts +13 -0
- package/types/lib/inventory/agentSkillSpec.d.ts.map +1 -0
- package/types/lib/inventory/apkInstalledDb.d.ts +42 -0
- package/types/lib/inventory/apkInstalledDb.d.ts.map +1 -0
- package/types/lib/inventory/atomUtils.d.ts +14 -0
- package/types/lib/inventory/atomUtils.d.ts.map +1 -1
- package/types/lib/inventory/cacheDir.d.ts +12 -4
- package/types/lib/inventory/cacheDir.d.ts.map +1 -1
- package/types/lib/inventory/certificates.d.ts +205 -0
- package/types/lib/inventory/certificates.d.ts.map +1 -0
- package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
- package/types/lib/inventory/deps.d.ts +2 -1
- package/types/lib/inventory/deps.d.ts.map +1 -1
- package/types/lib/inventory/display.d.ts +18 -0
- package/types/lib/inventory/display.d.ts.map +1 -1
- package/types/lib/inventory/dosai.d.ts +145 -6
- package/types/lib/inventory/dosai.d.ts.map +1 -1
- package/types/lib/inventory/dynamic.d.ts +6 -1
- package/types/lib/inventory/dynamic.d.ts.map +1 -1
- package/types/lib/inventory/envcontext.d.ts +40 -2
- package/types/lib/inventory/envcontext.d.ts.map +1 -1
- package/types/lib/inventory/evidenceUtils.d.ts +29 -10
- package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
- package/types/lib/inventory/formulationParsers.d.ts.map +1 -1
- package/types/lib/inventory/goBuildInfo.d.ts +10 -0
- package/types/lib/inventory/goBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/hbom.d.ts.map +1 -1
- package/types/lib/inventory/hbomAnalysis.d.ts +10 -0
- package/types/lib/inventory/hbomAnalysis.d.ts.map +1 -1
- package/types/lib/inventory/hostTopology.d.ts.map +1 -1
- package/types/lib/inventory/osPackagePurl.d.ts +99 -0
- package/types/lib/inventory/osPackagePurl.d.ts.map +1 -0
- package/types/lib/inventory/osPackageResolver.d.ts +6 -2
- package/types/lib/inventory/osPackageResolver.d.ts.map +1 -1
- package/types/lib/inventory/osinfo.d.ts +31 -6
- package/types/lib/inventory/osinfo.d.ts.map +1 -1
- package/types/lib/inventory/osqueryTransform.d.ts +51 -0
- package/types/lib/inventory/osqueryTransform.d.ts.map +1 -1
- package/types/lib/inventory/phpBuildInfo.d.ts +142 -0
- package/types/lib/inventory/phpBuildInfo.d.ts.map +1 -0
- package/types/lib/inventory/phpHostProbe.d.ts +35 -0
- package/types/lib/inventory/phpHostProbe.d.ts.map +1 -0
- package/types/lib/inventory/rootfsCerts.d.ts +27 -0
- package/types/lib/inventory/rootfsCerts.d.ts.map +1 -0
- package/types/lib/inventory/source.d.ts +28 -0
- package/types/lib/inventory/source.d.ts.map +1 -1
- package/types/lib/inventory/spdx.d.ts +15 -0
- package/types/lib/inventory/spdx.d.ts.map +1 -1
- package/types/lib/inventory/traceRunner.d.ts +4 -1
- package/types/lib/inventory/traceRunner.d.ts.map +1 -1
- package/types/lib/inventory/tracedCrypto.d.ts +22 -0
- package/types/lib/inventory/tracedCrypto.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts +10 -0
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts +12 -0
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/parsers/email.d.ts +19 -0
- package/types/lib/parsers/email.d.ts.map +1 -0
- package/types/lib/parsers/largeJson.d.ts +13 -0
- package/types/lib/parsers/largeJson.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +8 -0
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/introspection/reflect.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts +7 -4
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
- package/types/lib/stages/pregen/pregen.d.ts +14 -1
- package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
import { getAllFiles, safeExistsSync, safeSpawnSync } from "../core/fs.js";
|
|
24
24
|
import { thoughtLog } from "../core/logger.js";
|
|
25
25
|
import { isWin } from "../core/paths.js";
|
|
26
|
+
import { isProjectToolingAllowed } from "../core/projectTooling.js";
|
|
26
27
|
import { parseToml } from "../core/toml.js";
|
|
27
28
|
import {
|
|
28
29
|
isBuildToolRateLimited,
|
|
@@ -44,13 +45,16 @@ function isJvmToolPinned() {
|
|
|
44
45
|
);
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
// The gate lives in lib/core so that every layer can reach it; it stays
|
|
49
|
+
// exported here for existing callers.
|
|
50
|
+
export { isProjectToolingAllowed };
|
|
51
|
+
|
|
47
52
|
/**
|
|
48
53
|
* Method to return the gradle command to use.
|
|
49
54
|
*
|
|
50
55
|
* Project-local wrapper scripts (`gradlew`) are attacker-controlled files in
|
|
51
|
-
* the scanned project, so they are only used when
|
|
52
|
-
*
|
|
53
|
-
* used.
|
|
56
|
+
* the scanned project, so they are only used when the project's own tooling
|
|
57
|
+
* may run (see isProjectToolingAllowed); otherwise the system Gradle is used.
|
|
54
58
|
*
|
|
55
59
|
* @param {string} srcPath Path to look for gradlew wrapper
|
|
56
60
|
* @param {string|null} rootPath Root directory to look for gradlew wrapper
|
|
@@ -59,10 +63,7 @@ function isJvmToolPinned() {
|
|
|
59
63
|
export function getGradleCommand(srcPath, rootPath, options = {}) {
|
|
60
64
|
let gradleCmd = "gradle";
|
|
61
65
|
const pinnedToolSelected = isJvmToolPinned();
|
|
62
|
-
|
|
63
|
-
// keeps using wrappers even when dependency installation is disabled.
|
|
64
|
-
const allowProjectWrappers =
|
|
65
|
-
options.installDeps !== false || options.introspect === true;
|
|
66
|
+
const allowProjectWrappers = isProjectToolingAllowed(options);
|
|
66
67
|
|
|
67
68
|
let findGradleFile = "gradlew";
|
|
68
69
|
if (platform() === "win32") {
|
|
@@ -1349,15 +1350,18 @@ export async function collectGradleDependencies(
|
|
|
1349
1350
|
* Method to return the mill command to use.
|
|
1350
1351
|
*
|
|
1351
1352
|
* The project-local `mill` script is an attacker-controlled file in the
|
|
1352
|
-
* scanned project, so it is only used when
|
|
1353
|
-
* (
|
|
1353
|
+
* scanned project, so it is only used when the project's own tooling may run
|
|
1354
|
+
* (see isProjectToolingAllowed).
|
|
1354
1355
|
*
|
|
1355
1356
|
* @param {string} srcPath Path to look for mill wrapper
|
|
1356
1357
|
* @param {Object} [options] CLI options (`installDeps` gates wrapper use)
|
|
1357
1358
|
*/
|
|
1358
1359
|
export function getMillCommand(srcPath, options = {}) {
|
|
1359
1360
|
let millCmd = `mill${platform() === "win32" ? ".bat" : ""}`;
|
|
1360
|
-
if (
|
|
1361
|
+
if (
|
|
1362
|
+
isProjectToolingAllowed(options) &&
|
|
1363
|
+
safeExistsSync(join(srcPath, millCmd))
|
|
1364
|
+
) {
|
|
1361
1365
|
// Use local mill wrapper if available
|
|
1362
1366
|
// Enable execute permission
|
|
1363
1367
|
try {
|
|
@@ -1510,16 +1514,25 @@ function isProcessAlive(pid) {
|
|
|
1510
1514
|
* @param {string} rootPath Scanned tree
|
|
1511
1515
|
* @param {Map<string, Set<number>>} [runningBefore] Result of
|
|
1512
1516
|
* {@link findMillDaemons} taken before the scan
|
|
1517
|
+
* @param {Object} [options] CLI options
|
|
1513
1518
|
*/
|
|
1514
|
-
export function stopMillDaemons(
|
|
1519
|
+
export function stopMillDaemons(
|
|
1520
|
+
rootPath,
|
|
1521
|
+
runningBefore = new Map(),
|
|
1522
|
+
options = {},
|
|
1523
|
+
) {
|
|
1524
|
+
// The daemon PID files live in the scanned tree. When the scan was not
|
|
1525
|
+
// allowed to run Mill it started no daemon, and running the build's own
|
|
1526
|
+
// launcher here would execute a script from the scanned project.
|
|
1527
|
+
if (!isProjectToolingAllowed(options)) {
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1515
1530
|
for (const [buildRoot, pids] of findMillDaemons(rootPath)) {
|
|
1516
1531
|
const before = runningBefore.get(buildRoot) || new Set();
|
|
1517
1532
|
if ([...pids].every((pid) => before.has(pid))) {
|
|
1518
1533
|
continue;
|
|
1519
1534
|
}
|
|
1520
|
-
const launcher =
|
|
1521
|
-
? join(buildRoot, "mill")
|
|
1522
|
-
: "mill";
|
|
1535
|
+
const launcher = getMillCommand(buildRoot, options);
|
|
1523
1536
|
console.log("Stopping the Mill daemon the scan started in", buildRoot);
|
|
1524
1537
|
safeSpawnSync(launcher, ["shutdown"], {
|
|
1525
1538
|
cwd: buildRoot,
|
|
@@ -1532,8 +1545,8 @@ export function stopMillDaemons(rootPath, runningBefore = new Map()) {
|
|
|
1532
1545
|
* Method to return the maven command to use.
|
|
1533
1546
|
*
|
|
1534
1547
|
* Project-local wrapper scripts (`mvnw`) are attacker-controlled files in the
|
|
1535
|
-
* scanned project, so they are only used when
|
|
1536
|
-
* (
|
|
1548
|
+
* scanned project, so they are only used when the project's own tooling may
|
|
1549
|
+
* run (see isProjectToolingAllowed); otherwise the installed Maven is used.
|
|
1537
1550
|
*
|
|
1538
1551
|
* @param {string} srcPath Path to look for maven wrapper
|
|
1539
1552
|
* @param {string} rootPath Root directory to look for maven wrapper
|
|
@@ -1545,10 +1558,7 @@ export function getMavenCommand(srcPath, rootPath, options = {}) {
|
|
|
1545
1558
|
let isWrapperReady = false;
|
|
1546
1559
|
let isWrapperFound = false;
|
|
1547
1560
|
const pinnedToolSelected = isJvmToolPinned();
|
|
1548
|
-
|
|
1549
|
-
// keeps using wrappers even when dependency installation is disabled.
|
|
1550
|
-
const allowProjectWrappers =
|
|
1551
|
-
options.installDeps !== false || options.introspect === true;
|
|
1561
|
+
const allowProjectWrappers = isProjectToolingAllowed(options);
|
|
1552
1562
|
let findMavenFile = "mvnw";
|
|
1553
1563
|
let mavenWrapperCmd = null;
|
|
1554
1564
|
if (platform() === "win32") {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
basename,
|
|
4
|
+
dirname,
|
|
5
|
+
isAbsolute,
|
|
6
|
+
join,
|
|
7
|
+
posix,
|
|
8
|
+
resolve,
|
|
9
|
+
win32,
|
|
10
|
+
} from "node:path";
|
|
3
11
|
|
|
4
12
|
import { build } from "@cdxgen/cdx-purl";
|
|
5
13
|
|
|
@@ -182,7 +190,10 @@ export function resolveInstalledNugetVersion(range, installedVersions = []) {
|
|
|
182
190
|
* @returns {string} Project directory
|
|
183
191
|
*/
|
|
184
192
|
export function dotnetManifestProjectDir(manifestFile, projectPath) {
|
|
185
|
-
|
|
193
|
+
// A path recorded on another operating system, such as `D:\src\App.csproj`
|
|
194
|
+
// read on Linux, is not absolute here and would resolve against the working
|
|
195
|
+
// directory.
|
|
196
|
+
if (projectPath && isAbsolute(projectPath)) {
|
|
186
197
|
const projectDir = dirname(resolve(projectPath));
|
|
187
198
|
if (safeExistsSync(projectDir)) {
|
|
188
199
|
return projectDir;
|
|
@@ -192,6 +203,55 @@ export function dotnetManifestProjectDir(manifestFile, projectPath) {
|
|
|
192
203
|
return basename(dir) === "obj" ? dirname(dir) : dir;
|
|
193
204
|
}
|
|
194
205
|
|
|
206
|
+
/**
|
|
207
|
+
* The path, on this machine, of the project file a project.assets.json belongs to.
|
|
208
|
+
*
|
|
209
|
+
* Restore records the project file and the directory it wrote the assets file
|
|
210
|
+
* to (`outputPath`) as absolute paths on the machine that ran it, which can be
|
|
211
|
+
* a CI agent, a container, another operating system, or this tree reached
|
|
212
|
+
* through another path. Where the project file sits relative to that
|
|
213
|
+
* directory does not change when the tree moves, so the project file is that
|
|
214
|
+
* offset applied to the directory the assets file is in. An assets file that
|
|
215
|
+
* records no output path is taken to be in its project's `obj/`. The recorded
|
|
216
|
+
* path itself is used only when no offset can be worked out, as when restore
|
|
217
|
+
* wrote to another drive than the project's.
|
|
218
|
+
*
|
|
219
|
+
* Nothing is read from disk: the name is spelled as restore recorded it, which
|
|
220
|
+
* can differ in case from the file a case-insensitive file system holds.
|
|
221
|
+
*
|
|
222
|
+
* @param {string} assetsFile project.assets.json path
|
|
223
|
+
* @param {string} [projectPath] Project file restore recorded
|
|
224
|
+
* @param {string} [outputPath] Directory restore recorded writing the assets file to
|
|
225
|
+
* @returns {string|undefined} Project file path, or undefined when none can be named
|
|
226
|
+
*/
|
|
227
|
+
export function dotnetRestoredProjectFile(assetsFile, projectPath, outputPath) {
|
|
228
|
+
if (!assetsFile || typeof projectPath !== "string" || !projectPath.trim()) {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
// Read the recorded paths the way the machine that wrote them would
|
|
232
|
+
const recorded =
|
|
233
|
+
win32.isAbsolute(projectPath) && !posix.isAbsolute(projectPath)
|
|
234
|
+
? win32
|
|
235
|
+
: posix;
|
|
236
|
+
const assetsDir = dirname(resolve(assetsFile));
|
|
237
|
+
let offset;
|
|
238
|
+
if (typeof outputPath === "string" && outputPath.trim()) {
|
|
239
|
+
const relativePath = recorded.relative(outputPath, projectPath);
|
|
240
|
+
// Across two drives there is no relative path, only the recorded one
|
|
241
|
+
if (!recorded.isAbsolute(relativePath)) {
|
|
242
|
+
offset = relativePath.split(recorded.sep);
|
|
243
|
+
}
|
|
244
|
+
} else if (basename(assetsDir) === "obj") {
|
|
245
|
+
offset = ["..", recorded.basename(projectPath)];
|
|
246
|
+
}
|
|
247
|
+
// The offset must end at a file, not at the output directory or a parent
|
|
248
|
+
const fileName = offset?.at(-1);
|
|
249
|
+
if (fileName && fileName !== "." && fileName !== "..") {
|
|
250
|
+
return resolve(assetsDir, ...offset);
|
|
251
|
+
}
|
|
252
|
+
return isAbsolute(projectPath) ? resolve(projectPath) : undefined;
|
|
253
|
+
}
|
|
254
|
+
|
|
195
255
|
/**
|
|
196
256
|
* Index the MSBuild properties that props files define, by the directory each
|
|
197
257
|
* file sits in and across the whole scan, so the candidates for every project
|
|
@@ -853,8 +913,12 @@ function evaluateMsbuildProperties(projFile, names) {
|
|
|
853
913
|
* @param {Object} restoredNames Package ids as this project's restore output spells them,
|
|
854
914
|
* keyed by lowercased id. NuGet ids are case-insensitive, so a reference spelled
|
|
855
915
|
* differently names the same package and takes the restored spelling.
|
|
916
|
+
* @param {{name: string, version: (string|undefined)}} [projectIdentity] Package id and
|
|
917
|
+
* version this project's project.assets.json records for the project. They name the
|
|
918
|
+
* project in place of what the project file states.
|
|
856
919
|
*
|
|
857
|
-
* @returns {Object} Containing parent component, package, and
|
|
920
|
+
* @returns {Object} Containing parent component, package, dependencies, and the
|
|
921
|
+
* `$(Name)` version labels left unresolved without msbuild
|
|
858
922
|
*/
|
|
859
923
|
export function parseCsProjData(
|
|
860
924
|
csProjData,
|
|
@@ -865,6 +929,7 @@ export function parseCsProjData(
|
|
|
865
929
|
centralVersions = {},
|
|
866
930
|
fallbackVersions = {},
|
|
867
931
|
restoredNames = {},
|
|
932
|
+
projectIdentity = undefined,
|
|
868
933
|
) {
|
|
869
934
|
const pkgList = [];
|
|
870
935
|
const parentComponent = { type: "application", properties: [] };
|
|
@@ -909,21 +974,21 @@ export function parseCsProjData(
|
|
|
909
974
|
? pkgVersionLabelCandidates[label][0]
|
|
910
975
|
: undefined);
|
|
911
976
|
let msbuildValues = {};
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
for (const
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
reference
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
unresolved.add(label);
|
|
924
|
-
}
|
|
977
|
+
const unresolved = new Set();
|
|
978
|
+
for (const item of project.ItemGroup || []) {
|
|
979
|
+
for (const reference of item.PackageReference || []) {
|
|
980
|
+
const label = labelOf(
|
|
981
|
+
reference.$?.VersionOverride ||
|
|
982
|
+
reference.VersionOverride?.[0]._?.[0] ||
|
|
983
|
+
reference.$?.Version ||
|
|
984
|
+
reference.Version?.[0]._?.[0],
|
|
985
|
+
);
|
|
986
|
+
if (label && staticLabelValue(label) === undefined) {
|
|
987
|
+
unresolved.add(label);
|
|
925
988
|
}
|
|
926
989
|
}
|
|
990
|
+
}
|
|
991
|
+
if (msbuildInstalled) {
|
|
927
992
|
msbuildValues = evaluateMsbuildProperties(projFile, [...unresolved].sort());
|
|
928
993
|
}
|
|
929
994
|
// SDK-style projects declare their version through the MSBuild properties
|
|
@@ -1351,6 +1416,32 @@ export function parseCsProjData(
|
|
|
1351
1416
|
// version set from a build-time property is unknown, not 1.0.0.
|
|
1352
1417
|
parentComponent.version = "1.0.0";
|
|
1353
1418
|
}
|
|
1419
|
+
// Only a build knows the value of a property that references another one
|
|
1420
|
+
const literal = (value) =>
|
|
1421
|
+
value && !value.includes("$(") ? value : undefined;
|
|
1422
|
+
// NuGet names a project's package by its PackageId, which defaults to the
|
|
1423
|
+
// assembly name, so a PackageId the project file states names the project.
|
|
1424
|
+
const declaredPackageId = literal(ownProperties.PackageId);
|
|
1425
|
+
if (declaredPackageId) {
|
|
1426
|
+
parentComponent.name = declaredPackageId;
|
|
1427
|
+
}
|
|
1428
|
+
// Restore evaluated the project with everything MSBuild imports and every
|
|
1429
|
+
// property it was given: a Version from Directory.Build.props, `-p:Version`
|
|
1430
|
+
// or `$(BuildNumber)`, a PackageId. Its project.assets.json roots the
|
|
1431
|
+
// restored dependency tree at that identity, so naming the project from its
|
|
1432
|
+
// file alone would make it two components.
|
|
1433
|
+
if (projectIdentity?.name) {
|
|
1434
|
+
parentComponent.name = projectIdentity.name;
|
|
1435
|
+
parentComponent.version = projectIdentity.version;
|
|
1436
|
+
}
|
|
1437
|
+
// The assembly the project builds keeps its name when the package differs
|
|
1438
|
+
const declaredAssemblyName = literal(ownProperties.AssemblyName);
|
|
1439
|
+
if (declaredAssemblyName && declaredAssemblyName !== parentComponent.name) {
|
|
1440
|
+
parentComponent.properties.push({
|
|
1441
|
+
name: "cdx:dotnet:assembly_name",
|
|
1442
|
+
value: declaredAssemblyName,
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1354
1445
|
// The purl is built once every PropertyGroup has been read, so a version
|
|
1355
1446
|
// declared after OutputType is not lost. A project that states no version
|
|
1356
1447
|
// gets a versionless purl: "latest" is not a version.
|
|
@@ -1370,6 +1461,8 @@ export function parseCsProjData(
|
|
|
1370
1461
|
pkgList,
|
|
1371
1462
|
parentComponent,
|
|
1372
1463
|
dependencies,
|
|
1464
|
+
// Version labels no static source settled, which only msbuild could
|
|
1465
|
+
unresolvedVersionLabels: msbuildInstalled ? [] : [...unresolved].sort(),
|
|
1373
1466
|
};
|
|
1374
1467
|
}
|
|
1375
1468
|
|
|
@@ -1417,8 +1510,10 @@ export function isReferencedDotnetPackageFile(packageFile) {
|
|
|
1417
1510
|
*
|
|
1418
1511
|
* @param {string} csProjData Raw JSON string of the project.assets.json file
|
|
1419
1512
|
* @param {string} assetsJsonFile Path to the project.assets.json file, used for evidence properties
|
|
1420
|
-
* @returns {{ pkgList: Object[], dependenciesList: Object[], projectPath: (string|undefined) }}
|
|
1421
|
-
* `projectPath` is the project file the restore output belongs to
|
|
1513
|
+
* @returns {{ pkgList: Object[], dependenciesList: Object[], projectPath: (string|undefined), outputPath: (string|undefined), projectIdentity: ({name: string, version: (string|undefined)}|undefined) }}
|
|
1514
|
+
* `projectPath` is the project file the restore output belongs to and `outputPath` the
|
|
1515
|
+
* directory restore wrote it to, both as restore recorded them. `projectIdentity` is the
|
|
1516
|
+
* package id and version restore evaluated for the project, which root the dependency tree.
|
|
1422
1517
|
*/
|
|
1423
1518
|
export function parseCsProjAssetsData(csProjData, assetsJsonFile) {
|
|
1424
1519
|
// extract name, operator, version from .NET package representation
|
|
@@ -1646,6 +1741,10 @@ export function parseCsProjAssetsData(csProjData, assetsJsonFile) {
|
|
|
1646
1741
|
pkgList,
|
|
1647
1742
|
dependenciesList,
|
|
1648
1743
|
projectPath,
|
|
1744
|
+
outputPath: csProjData.project?.restore?.outputPath,
|
|
1745
|
+
projectIdentity: rootRef
|
|
1746
|
+
? { name: rootPkg.name, version: rootPkg.version }
|
|
1747
|
+
: undefined,
|
|
1649
1748
|
};
|
|
1650
1749
|
}
|
|
1651
1750
|
|