@vyuhlabs/dxkit 2.1.0 → 2.2.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/CHANGELOG.md +92 -0
- package/README.md +9 -9
- package/dist/agents/extract.d.ts +25 -0
- package/dist/agents/extract.d.ts.map +1 -0
- package/dist/agents/extract.js +186 -0
- package/dist/agents/extract.js.map +1 -0
- package/dist/agents/schemas.d.ts +106 -0
- package/dist/agents/schemas.d.ts.map +1 -0
- package/dist/agents/schemas.js +86 -0
- package/dist/agents/schemas.js.map +1 -0
- package/dist/agents/session.d.ts +28 -0
- package/dist/agents/session.d.ts.map +1 -0
- package/dist/agents/session.js +223 -0
- package/dist/agents/session.js.map +1 -0
- package/dist/analyzers/bom/gather.d.ts +12 -1
- package/dist/analyzers/bom/gather.d.ts.map +1 -1
- package/dist/analyzers/bom/gather.js +46 -0
- package/dist/analyzers/bom/gather.js.map +1 -1
- package/dist/analyzers/bom/index.d.ts.map +1 -1
- package/dist/analyzers/bom/index.js +37 -0
- package/dist/analyzers/bom/index.js.map +1 -1
- package/dist/analyzers/bom/types.d.ts +20 -0
- package/dist/analyzers/bom/types.d.ts.map +1 -1
- package/dist/analyzers/index.d.ts +3 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +6 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/security/report.d.ts +6 -0
- package/dist/analyzers/security/report.d.ts.map +1 -0
- package/dist/analyzers/security/report.js +118 -0
- package/dist/analyzers/security/report.js.map +1 -0
- package/dist/analyzers/tools/dotnet.d.ts +8 -0
- package/dist/analyzers/tools/dotnet.d.ts.map +1 -0
- package/dist/analyzers/tools/dotnet.js +81 -0
- package/dist/analyzers/tools/dotnet.js.map +1 -0
- package/dist/analyzers/tools/gather-cache.d.ts +16 -0
- package/dist/analyzers/tools/gather-cache.d.ts.map +1 -0
- package/dist/analyzers/tools/gather-cache.js +126 -0
- package/dist/analyzers/tools/gather-cache.js.map +1 -0
- package/dist/analyzers/tools/go.d.ts +8 -0
- package/dist/analyzers/tools/go.d.ts.map +1 -0
- package/dist/analyzers/tools/go.js +84 -0
- package/dist/analyzers/tools/go.js.map +1 -0
- package/dist/analyzers/tools/node.d.ts +8 -0
- package/dist/analyzers/tools/node.d.ts.map +1 -0
- package/dist/analyzers/tools/node.js +160 -0
- package/dist/analyzers/tools/node.js.map +1 -0
- package/dist/analyzers/tools/python.d.ts +8 -0
- package/dist/analyzers/tools/python.d.ts.map +1 -0
- package/dist/analyzers/tools/python.js +81 -0
- package/dist/analyzers/tools/python.js.map +1 -0
- package/dist/analyzers/tools/rust.d.ts +8 -0
- package/dist/analyzers/tools/rust.d.ts.map +1 -0
- package/dist/analyzers/tools/rust.js +86 -0
- package/dist/analyzers/tools/rust.js.map +1 -0
- package/dist/analyzers/xlsx/bom.d.ts.map +1 -1
- package/dist/analyzers/xlsx/bom.js +11 -1
- package/dist/analyzers/xlsx/bom.js.map +1 -1
- package/dist/languages/capabilities/types.d.ts +1 -0
- package/dist/languages/capabilities/types.d.ts.map +1 -1
- package/dist/languages/csharp.d.ts +41 -6
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +225 -35
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts +35 -0
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +156 -0
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/python.d.ts +49 -0
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +202 -17
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/rust.d.ts +15 -0
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +93 -0
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/typescript.d.ts +17 -0
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +106 -0
- package/dist/languages/typescript.js.map +1 -1
- package/package.json +1 -1
- package/templates/.ai/templates/session-checkpoint-template.md +97 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gatherPythonMetrics = gatherPythonMetrics;
|
|
4
|
+
const runner_1 = require("./runner");
|
|
5
|
+
const tool_registry_1 = require("./tool-registry");
|
|
6
|
+
/** Gather Python-specific metrics. */
|
|
7
|
+
function gatherPythonMetrics(cwd) {
|
|
8
|
+
const metrics = {
|
|
9
|
+
toolsUsed: [],
|
|
10
|
+
toolsUnavailable: [],
|
|
11
|
+
};
|
|
12
|
+
// ruff (lint)
|
|
13
|
+
const ruff = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS.ruff, cwd);
|
|
14
|
+
if (ruff.available && ruff.path) {
|
|
15
|
+
const raw = (0, runner_1.run)(`${ruff.path} check . --output-format json 2>/dev/null`, cwd, 60000);
|
|
16
|
+
if (raw) {
|
|
17
|
+
try {
|
|
18
|
+
const results = JSON.parse(raw);
|
|
19
|
+
if (Array.isArray(results)) {
|
|
20
|
+
// ruff doesn't distinguish error/warning by default — all are errors
|
|
21
|
+
metrics.lintErrors = results.length;
|
|
22
|
+
metrics.lintWarnings = 0;
|
|
23
|
+
metrics.lintTool = 'ruff';
|
|
24
|
+
metrics.toolsUsed.push('ruff');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
metrics.toolsUnavailable.push('ruff (parse error)');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// Empty output = no errors
|
|
33
|
+
metrics.lintErrors = 0;
|
|
34
|
+
metrics.lintWarnings = 0;
|
|
35
|
+
metrics.lintTool = 'ruff';
|
|
36
|
+
metrics.toolsUsed.push('ruff');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
metrics.toolsUnavailable.push('ruff');
|
|
41
|
+
}
|
|
42
|
+
// pip-audit (dependency vulnerabilities)
|
|
43
|
+
const pipAudit = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS['pip-audit'], cwd);
|
|
44
|
+
if (pipAudit.available && pipAudit.path) {
|
|
45
|
+
const raw = (0, runner_1.run)(`${pipAudit.path} --format json 2>/dev/null`, cwd, 120000);
|
|
46
|
+
if (raw) {
|
|
47
|
+
try {
|
|
48
|
+
const data = JSON.parse(raw);
|
|
49
|
+
let medium = 0;
|
|
50
|
+
for (const dep of data.dependencies || []) {
|
|
51
|
+
// pip-audit doesn't provide severity — count all as medium
|
|
52
|
+
medium += (dep.vulns || []).length;
|
|
53
|
+
}
|
|
54
|
+
const critical = 0;
|
|
55
|
+
const high = 0;
|
|
56
|
+
const low = 0;
|
|
57
|
+
metrics.depVulnCritical = critical;
|
|
58
|
+
metrics.depVulnHigh = high;
|
|
59
|
+
metrics.depVulnMedium = medium;
|
|
60
|
+
metrics.depVulnLow = low;
|
|
61
|
+
metrics.depAuditTool = 'pip-audit';
|
|
62
|
+
metrics.toolsUsed.push('pip-audit');
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
metrics.toolsUnavailable.push('pip-audit (parse error)');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
metrics.toolsUnavailable.push('pip-audit');
|
|
71
|
+
}
|
|
72
|
+
// Test framework detection (don't run tests — just detect)
|
|
73
|
+
if ((0, runner_1.fileExists)(cwd, 'pytest.ini', 'conftest.py') || (0, runner_1.fileExists)(cwd, 'pyproject.toml')) {
|
|
74
|
+
const pyproject = (0, runner_1.run)('cat pyproject.toml 2>/dev/null', cwd);
|
|
75
|
+
if (pyproject?.includes('[tool.pytest') || (0, runner_1.fileExists)(cwd, 'pytest.ini', 'conftest.py')) {
|
|
76
|
+
metrics.testFramework = 'pytest';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return metrics;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=python.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python.js","sourceRoot":"","sources":["../../../src/analyzers/tools/python.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rust tool runner — clippy, cargo-audit.
|
|
3
|
+
* Layer 1: language-specific tools for Rust projects.
|
|
4
|
+
*/
|
|
5
|
+
import { HealthMetrics } from '../types';
|
|
6
|
+
/** Gather Rust-specific metrics. */
|
|
7
|
+
export declare function gatherRustMetrics(cwd: string): Partial<HealthMetrics>;
|
|
8
|
+
//# sourceMappingURL=rust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/rust.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAoBzC,oCAAoC;AACpC,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA0ErE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gatherRustMetrics = gatherRustMetrics;
|
|
4
|
+
const runner_1 = require("./runner");
|
|
5
|
+
const tool_registry_1 = require("./tool-registry");
|
|
6
|
+
/** Gather Rust-specific metrics. */
|
|
7
|
+
function gatherRustMetrics(cwd) {
|
|
8
|
+
const metrics = {
|
|
9
|
+
toolsUsed: [],
|
|
10
|
+
toolsUnavailable: [],
|
|
11
|
+
};
|
|
12
|
+
// clippy
|
|
13
|
+
const clippy = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS.clippy, cwd);
|
|
14
|
+
if (clippy.available) {
|
|
15
|
+
const raw = (0, runner_1.run)('cargo clippy --message-format json 2>/dev/null', cwd, 120000);
|
|
16
|
+
if (raw) {
|
|
17
|
+
let errors = 0;
|
|
18
|
+
let warnings = 0;
|
|
19
|
+
for (const line of raw.split('\n')) {
|
|
20
|
+
if (!line.trim())
|
|
21
|
+
continue;
|
|
22
|
+
try {
|
|
23
|
+
const msg = JSON.parse(line);
|
|
24
|
+
if (msg.reason === 'compiler-message' && msg.message) {
|
|
25
|
+
if (msg.message.level === 'error')
|
|
26
|
+
errors++;
|
|
27
|
+
else if (msg.message.level === 'warning')
|
|
28
|
+
warnings++;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
/* skip non-JSON lines */
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
metrics.lintErrors = errors;
|
|
36
|
+
metrics.lintWarnings = warnings;
|
|
37
|
+
metrics.lintTool = 'clippy';
|
|
38
|
+
metrics.toolsUsed.push('clippy');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
metrics.toolsUnavailable.push('clippy');
|
|
43
|
+
}
|
|
44
|
+
// cargo-audit
|
|
45
|
+
const audit = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS['cargo-audit'], cwd);
|
|
46
|
+
if (audit.available && audit.path) {
|
|
47
|
+
const raw = (0, runner_1.run)(`${audit.path} audit --json 2>/dev/null`, cwd, 60000);
|
|
48
|
+
if (raw) {
|
|
49
|
+
try {
|
|
50
|
+
const data = JSON.parse(raw);
|
|
51
|
+
if (data.vulnerabilities) {
|
|
52
|
+
let critical = 0, high = 0, medium = 0, low = 0;
|
|
53
|
+
for (const v of data.vulnerabilities.list || []) {
|
|
54
|
+
const sev = v.advisory?.severity?.toLowerCase();
|
|
55
|
+
if (sev === 'critical')
|
|
56
|
+
critical++;
|
|
57
|
+
else if (sev === 'high')
|
|
58
|
+
high++;
|
|
59
|
+
else if (sev === 'medium')
|
|
60
|
+
medium++;
|
|
61
|
+
else
|
|
62
|
+
low++;
|
|
63
|
+
}
|
|
64
|
+
metrics.depVulnCritical = critical;
|
|
65
|
+
metrics.depVulnHigh = high;
|
|
66
|
+
metrics.depVulnMedium = medium;
|
|
67
|
+
metrics.depVulnLow = low;
|
|
68
|
+
metrics.depAuditTool = 'cargo-audit';
|
|
69
|
+
metrics.toolsUsed.push('cargo-audit');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
metrics.toolsUnavailable.push('cargo-audit (parse error)');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
metrics.toolsUnavailable.push('cargo-audit');
|
|
79
|
+
}
|
|
80
|
+
// Test framework detection
|
|
81
|
+
if ((0, runner_1.fileExists)(cwd, 'Cargo.toml')) {
|
|
82
|
+
metrics.testFramework = 'cargo-test';
|
|
83
|
+
}
|
|
84
|
+
return metrics;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=rust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rust.js","sourceRoot":"","sources":["../../../src/analyzers/tools/rust.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bom.d.ts","sourceRoot":"","sources":["../../../src/analyzers/xlsx/bom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,cAAc,CAAC;AAqC3D;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"bom.d.ts","sourceRoot":"","sources":["../../../src/analyzers/xlsx/bom.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,cAAc,CAAC;AAqC3D;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAkFlE"}
|
|
@@ -95,7 +95,17 @@ async function toBomXlsx(report) {
|
|
|
95
95
|
const vulnLines = sortedVulns.map((v) => {
|
|
96
96
|
const title = (v.summary ?? '').replace(/\s+/g, ' ').trim().slice(0, ADVISORY_SUMMARY_MAX);
|
|
97
97
|
const cvss = v.cvssScore !== undefined ? ` [CVSS ${v.cvssScore.toFixed(1)}]` : '';
|
|
98
|
-
|
|
98
|
+
// Top-level attribution: tells the reviewer which direct manifest
|
|
99
|
+
// dep to upgrade. Missing when the pack couldn't parse the graph
|
|
100
|
+
// (e.g. TS repo with no lockfile) — silent in that case so the
|
|
101
|
+
// column stays clean.
|
|
102
|
+
const tops = v.topLevelDep ?? [];
|
|
103
|
+
let via = '';
|
|
104
|
+
if (tops.length === 1)
|
|
105
|
+
via = ` via ${tops[0]}`;
|
|
106
|
+
else if (tops.length > 1)
|
|
107
|
+
via = ` via ${tops[0]} (+${tops.length - 1} more)`;
|
|
108
|
+
return title ? `${v.id}${cvss}${via}: ${title}` : `${v.id}${cvss}${via}`;
|
|
99
109
|
});
|
|
100
110
|
const vulnerabilityIssues = e.vulns.length === 0 ? NO_VULNS_ISSUES : vulnLines.join('; ');
|
|
101
111
|
const resolution = e.vulns.length === 0 ? NO_VULNS_RESOLUTION : e.upgradeAdvice;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bom.js","sourceRoot":"","sources":["../../../src/analyzers/xlsx/bom.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;AA8CH,
|
|
1
|
+
{"version":3,"file":"bom.js","sourceRoot":"","sources":["../../../src/analyzers/xlsx/bom.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/languages/capabilities/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,cAAc;IAE7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAI1B,IAAI,EAAE,MAAM,CAAC;IAIb,QAAQ,EAAE,MAAM,cAAc,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IAInB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAK1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAInB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/languages/capabilities/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,cAAc;IAE7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAI1B,IAAI,EAAE,MAAM,CAAC;IAIb,QAAQ,EAAE,MAAM,cAAc,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IAInB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAK1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAInB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAWtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAc,SAAQ,kBAAkB;IACvD,6DAA6D;IAC7D,MAAM,EAAE,cAAc,CAAC;IACvB,sEAAsE;IACtE,UAAU,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,kGAAkG;AAClG,MAAM,WAAW,UAAW,SAAQ,kBAAkB;IACpD,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,gFAAgF;AAChF,MAAM,WAAW,cAAe,SAAQ,kBAAkB;IACxD,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,0DAA0D;AAC1D,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,mGAAmG;IACnG,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,aAAc,SAAQ,kBAAkB;IACvD,QAAQ,CAAC,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/D,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;CAC1D;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAe,SAAQ,kBAAkB;IACxD,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;CACzC;AAED,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,cAAc,CAAC;IAC/B,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAc,SAAQ,kBAAkB;IACvD,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACvC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,0DAA0D;AAC1D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,cAAc,CAAC;IAC/B,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,QAAQ,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAC5C,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,oBAAoB,CAAC;IACxB,CAAC,EAAE,oBAAoB,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,SAAS,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAC5C;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,sFAAsF;IACtF,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -3,17 +3,52 @@ import type { DepVulnFinding, SeverityCounts } from './capabilities/types';
|
|
|
3
3
|
import type { LanguageSupport } from './types';
|
|
4
4
|
export declare function parseCoberturaXml(raw: string, sourceFile: string, cwd: string): Coverage | null;
|
|
5
5
|
/**
|
|
6
|
-
* Pure parser for `dotnet list package --vulnerable --
|
|
7
|
-
* Extracted from the gather function so it can be
|
|
8
|
-
* a real .NET SDK on the dev machine (10h.5
|
|
9
|
-
* runs the full pipeline). Returns null when
|
|
10
|
-
* otherwise returns counts + findings ready
|
|
11
|
-
* enrichment.
|
|
6
|
+
* Pure parser for `dotnet list package --vulnerable --include-transitive
|
|
7
|
+
* --format json`. Extracted from the gather function so it can be
|
|
8
|
+
* unit-tested without a real .NET SDK on the dev machine (10h.5
|
|
9
|
+
* release-time validation runs the full pipeline). Returns null when
|
|
10
|
+
* the input is malformed; otherwise returns counts + findings ready
|
|
11
|
+
* for downstream alias enrichment + top-level attribution.
|
|
12
|
+
*
|
|
13
|
+
* Both top-level and transitive packages are iterated. Top-level
|
|
14
|
+
* findings carry `topLevelDep = [self]` (they ARE manifest deps);
|
|
15
|
+
* transitive findings emit with `topLevelDep` unset — the gather
|
|
16
|
+
* function then fills it from `project.assets.json` if available.
|
|
17
|
+
* Leaving attribution unset on transitives when assets.json is absent
|
|
18
|
+
* matches Python's venv-missing behavior: degrade gracefully rather
|
|
19
|
+
* than invent false parents.
|
|
12
20
|
*/
|
|
13
21
|
export declare function parseDotnetVulnerableOutput(raw: string): {
|
|
14
22
|
counts: SeverityCounts;
|
|
15
23
|
findings: DepVulnFinding[];
|
|
16
24
|
} | null;
|
|
25
|
+
/**
|
|
26
|
+
* Pure parser for `obj/project.assets.json`. Extracts the forward
|
|
27
|
+
* dep graph keyed by package name (collapsing versions — same as
|
|
28
|
+
* TS/Go/Rust packs) plus the set of top-level (direct manifest)
|
|
29
|
+
* package names across every target framework declared in `project`.
|
|
30
|
+
*
|
|
31
|
+
* Multi-framework projects: graphs are merged across target
|
|
32
|
+
* frameworks into a single name-level edge map. Top-level set is
|
|
33
|
+
* the union of declared direct deps across frameworks. This
|
|
34
|
+
* over-attributes slightly if a package is direct in netstandard2.0
|
|
35
|
+
* but transitive in net8.0 — it gets listed as a top-level — but the
|
|
36
|
+
* simplification beats per-framework multi-reporting complexity.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseProjectAssetsJson(raw: string): {
|
|
39
|
+
topLevels: string[];
|
|
40
|
+
edges: Map<string, Set<string>>;
|
|
41
|
+
} | null;
|
|
42
|
+
/**
|
|
43
|
+
* BFS the parsed asset graph to produce a per-package-name index of
|
|
44
|
+
* its top-level ancestors. Mirrors `buildTsTopLevelDepIndex` /
|
|
45
|
+
* `buildRustTopLevelDepIndex` in shape and semantics; attribution is
|
|
46
|
+
* coarse (name-level) and unions across multiple reachable parents.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildCsharpTopLevelDepIndex(parsed: {
|
|
49
|
+
topLevels: ReadonlyArray<string>;
|
|
50
|
+
edges: ReadonlyMap<string, ReadonlySet<string>>;
|
|
51
|
+
}): Map<string, string[]>;
|
|
17
52
|
/**
|
|
18
53
|
* Capture C# `using` directives from source text, including
|
|
19
54
|
* `using static Foo`, aliased (`using X = Foo.Bar`), and plain forms.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../src/languages/csharp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,6BAA6B,CAAC;AAM1E,OAAO,KAAK,EAEV,cAAc,EAQd,cAAc,EAEf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAwD/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAoC/F;
|
|
1
|
+
{"version":3,"file":"csharp.d.ts","sourceRoot":"","sources":["../../src/languages/csharp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,6BAA6B,CAAC;AAM1E,OAAO,KAAK,EAEV,cAAc,EAQd,cAAc,EAEf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAwD/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAoC/F;AAuGD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,GACV;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,GAAG,IAAI,CA0D/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,GACV;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,IAAI,CAqCjE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACjC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;CACjD,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAsBxB;AAgPD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQjE;AAsKD,eAAO,MAAM,MAAM,EAAE,eAsCpB,CAAC"}
|
package/dist/languages/csharp.js
CHANGED
|
@@ -36,6 +36,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.csharp = void 0;
|
|
37
37
|
exports.parseCoberturaXml = parseCoberturaXml;
|
|
38
38
|
exports.parseDotnetVulnerableOutput = parseDotnetVulnerableOutput;
|
|
39
|
+
exports.parseProjectAssetsJson = parseProjectAssetsJson;
|
|
40
|
+
exports.buildCsharpTopLevelDepIndex = buildCsharpTopLevelDepIndex;
|
|
39
41
|
exports.extractCsharpImportsRaw = extractCsharpImportsRaw;
|
|
40
42
|
const fs = __importStar(require("fs"));
|
|
41
43
|
const path = __importStar(require("path"));
|
|
@@ -168,12 +170,20 @@ function extractGhsaIdFromUrl(url) {
|
|
|
168
170
|
return m ? m[0].toUpperCase() : null;
|
|
169
171
|
}
|
|
170
172
|
/**
|
|
171
|
-
* Pure parser for `dotnet list package --vulnerable --
|
|
172
|
-
* Extracted from the gather function so it can be
|
|
173
|
-
* a real .NET SDK on the dev machine (10h.5
|
|
174
|
-
* runs the full pipeline). Returns null when
|
|
175
|
-
* otherwise returns counts + findings ready
|
|
176
|
-
* enrichment.
|
|
173
|
+
* Pure parser for `dotnet list package --vulnerable --include-transitive
|
|
174
|
+
* --format json`. Extracted from the gather function so it can be
|
|
175
|
+
* unit-tested without a real .NET SDK on the dev machine (10h.5
|
|
176
|
+
* release-time validation runs the full pipeline). Returns null when
|
|
177
|
+
* the input is malformed; otherwise returns counts + findings ready
|
|
178
|
+
* for downstream alias enrichment + top-level attribution.
|
|
179
|
+
*
|
|
180
|
+
* Both top-level and transitive packages are iterated. Top-level
|
|
181
|
+
* findings carry `topLevelDep = [self]` (they ARE manifest deps);
|
|
182
|
+
* transitive findings emit with `topLevelDep` unset — the gather
|
|
183
|
+
* function then fills it from `project.assets.json` if available.
|
|
184
|
+
* Leaving attribution unset on transitives when assets.json is absent
|
|
185
|
+
* matches Python's venv-missing behavior: degrade gracefully rather
|
|
186
|
+
* than invent false parents.
|
|
177
187
|
*/
|
|
178
188
|
function parseDotnetVulnerableOutput(raw) {
|
|
179
189
|
let data;
|
|
@@ -188,44 +198,202 @@ function parseDotnetVulnerableOutput(raw) {
|
|
|
188
198
|
let medium = 0;
|
|
189
199
|
let low = 0;
|
|
190
200
|
const findings = [];
|
|
201
|
+
const emit = (pkgId, resolvedVersion, advisories, topLevelDep) => {
|
|
202
|
+
for (const adv of advisories) {
|
|
203
|
+
const severity = normalizeDotnetSeverity(adv.severity);
|
|
204
|
+
if (severity === 'critical')
|
|
205
|
+
critical++;
|
|
206
|
+
else if (severity === 'high')
|
|
207
|
+
high++;
|
|
208
|
+
else if (severity === 'medium')
|
|
209
|
+
medium++;
|
|
210
|
+
else
|
|
211
|
+
low++;
|
|
212
|
+
const ghsa = extractGhsaIdFromUrl(adv.advisoryUrl);
|
|
213
|
+
const id = ghsa ?? `nuget-${pkgId}@${resolvedVersion ?? 'unknown'}`;
|
|
214
|
+
const finding = {
|
|
215
|
+
id,
|
|
216
|
+
package: pkgId,
|
|
217
|
+
installedVersion: resolvedVersion,
|
|
218
|
+
tool: 'dotnet-vulnerable',
|
|
219
|
+
severity,
|
|
220
|
+
};
|
|
221
|
+
if (topLevelDep && topLevelDep.length > 0)
|
|
222
|
+
finding.topLevelDep = topLevelDep;
|
|
223
|
+
if (ghsa)
|
|
224
|
+
finding.aliases = [ghsa];
|
|
225
|
+
if (adv.advisoryUrl)
|
|
226
|
+
finding.references = [adv.advisoryUrl];
|
|
227
|
+
findings.push(finding);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
191
230
|
for (const proj of data.projects ?? []) {
|
|
192
231
|
for (const fw of proj.frameworks ?? []) {
|
|
193
232
|
for (const pkg of fw.topLevelPackages ?? []) {
|
|
194
233
|
if (!pkg.id)
|
|
195
234
|
continue;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
else
|
|
205
|
-
low++;
|
|
206
|
-
const ghsa = extractGhsaIdFromUrl(adv.advisoryUrl);
|
|
207
|
-
// No GHSA URL means we have nothing addressable — fall back
|
|
208
|
-
// to a synthetic id so the finding is still emitted (the
|
|
209
|
-
// counts already incremented, and bom render needs a row).
|
|
210
|
-
const id = ghsa ?? `nuget-${pkg.id}@${pkg.resolvedVersion ?? 'unknown'}`;
|
|
211
|
-
const finding = {
|
|
212
|
-
id,
|
|
213
|
-
package: pkg.id,
|
|
214
|
-
installedVersion: pkg.resolvedVersion,
|
|
215
|
-
tool: 'dotnet-vulnerable',
|
|
216
|
-
severity,
|
|
217
|
-
};
|
|
218
|
-
if (ghsa)
|
|
219
|
-
finding.aliases = [ghsa];
|
|
220
|
-
if (adv.advisoryUrl)
|
|
221
|
-
finding.references = [adv.advisoryUrl];
|
|
222
|
-
findings.push(finding);
|
|
223
|
-
}
|
|
235
|
+
emit(pkg.id, pkg.resolvedVersion, pkg.advisories ?? [], [pkg.id]);
|
|
236
|
+
}
|
|
237
|
+
for (const pkg of fw.transitivePackages ?? []) {
|
|
238
|
+
if (!pkg.id)
|
|
239
|
+
continue;
|
|
240
|
+
// topLevelDep stays unset; `attachCsharpTopLevelAttribution`
|
|
241
|
+
// downstream fills it from project.assets.json when available.
|
|
242
|
+
emit(pkg.id, pkg.resolvedVersion, pkg.advisories ?? [], undefined);
|
|
224
243
|
}
|
|
225
244
|
}
|
|
226
245
|
}
|
|
227
246
|
return { counts: { critical, high, medium, low }, findings };
|
|
228
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Pure parser for `obj/project.assets.json`. Extracts the forward
|
|
250
|
+
* dep graph keyed by package name (collapsing versions — same as
|
|
251
|
+
* TS/Go/Rust packs) plus the set of top-level (direct manifest)
|
|
252
|
+
* package names across every target framework declared in `project`.
|
|
253
|
+
*
|
|
254
|
+
* Multi-framework projects: graphs are merged across target
|
|
255
|
+
* frameworks into a single name-level edge map. Top-level set is
|
|
256
|
+
* the union of declared direct deps across frameworks. This
|
|
257
|
+
* over-attributes slightly if a package is direct in netstandard2.0
|
|
258
|
+
* but transitive in net8.0 — it gets listed as a top-level — but the
|
|
259
|
+
* simplification beats per-framework multi-reporting complexity.
|
|
260
|
+
*/
|
|
261
|
+
function parseProjectAssetsJson(raw) {
|
|
262
|
+
let data;
|
|
263
|
+
try {
|
|
264
|
+
data = JSON.parse(raw);
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
if (!data.targets && !data.project)
|
|
270
|
+
return null;
|
|
271
|
+
const nameOf = (key) => {
|
|
272
|
+
// Keys are `Pkg/Version` — split on '/' and take the package part.
|
|
273
|
+
const slash = key.indexOf('/');
|
|
274
|
+
return slash < 0 ? key : key.slice(0, slash);
|
|
275
|
+
};
|
|
276
|
+
const edges = new Map();
|
|
277
|
+
for (const target of Object.values(data.targets ?? {})) {
|
|
278
|
+
for (const [pkgVerKey, pkgEntry] of Object.entries(target)) {
|
|
279
|
+
const srcName = nameOf(pkgVerKey);
|
|
280
|
+
const deps = pkgEntry?.dependencies;
|
|
281
|
+
if (!deps)
|
|
282
|
+
continue;
|
|
283
|
+
const bucket = edges.get(srcName) ?? new Set();
|
|
284
|
+
for (const depName of Object.keys(deps)) {
|
|
285
|
+
bucket.add(depName);
|
|
286
|
+
}
|
|
287
|
+
edges.set(srcName, bucket);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const topLevels = new Set();
|
|
291
|
+
for (const fw of Object.values(data.project?.frameworks ?? {})) {
|
|
292
|
+
for (const name of Object.keys(fw?.dependencies ?? {})) {
|
|
293
|
+
topLevels.add(name);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return { topLevels: [...topLevels].sort(), edges };
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* BFS the parsed asset graph to produce a per-package-name index of
|
|
300
|
+
* its top-level ancestors. Mirrors `buildTsTopLevelDepIndex` /
|
|
301
|
+
* `buildRustTopLevelDepIndex` in shape and semantics; attribution is
|
|
302
|
+
* coarse (name-level) and unions across multiple reachable parents.
|
|
303
|
+
*/
|
|
304
|
+
function buildCsharpTopLevelDepIndex(parsed) {
|
|
305
|
+
const result = new Map();
|
|
306
|
+
for (const top of parsed.topLevels) {
|
|
307
|
+
const visited = new Set();
|
|
308
|
+
const queue = [top];
|
|
309
|
+
while (queue.length > 0) {
|
|
310
|
+
const name = queue.shift();
|
|
311
|
+
if (visited.has(name))
|
|
312
|
+
continue;
|
|
313
|
+
visited.add(name);
|
|
314
|
+
const bucket = result.get(name) ?? new Set();
|
|
315
|
+
bucket.add(top);
|
|
316
|
+
result.set(name, bucket);
|
|
317
|
+
for (const child of parsed.edges.get(name) ?? []) {
|
|
318
|
+
if (!visited.has(child))
|
|
319
|
+
queue.push(child);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const sorted = new Map();
|
|
324
|
+
for (const [name, parents] of result) {
|
|
325
|
+
sorted.set(name, [...parents].sort());
|
|
326
|
+
}
|
|
327
|
+
return sorted;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Locate the nearest `obj/project.assets.json` under cwd (NuGet's
|
|
331
|
+
* lockfile equivalent, created by `dotnet restore`). Unlike the
|
|
332
|
+
* shared `findMatchingRecursive`, we cannot skip `obj/` here —
|
|
333
|
+
* that's literally where the file lives. Walks up to 4 levels deep
|
|
334
|
+
* to handle solutions with nested projects. Returns the absolute
|
|
335
|
+
* path of the first match, or null.
|
|
336
|
+
*
|
|
337
|
+
* Multi-project solutions currently use the first-found file's
|
|
338
|
+
* graph — noted as a known limitation in the phase commit.
|
|
339
|
+
*/
|
|
340
|
+
function findProjectAssetsJson(cwd, maxDepth = 4) {
|
|
341
|
+
function search(dir, depth) {
|
|
342
|
+
if (depth > maxDepth)
|
|
343
|
+
return null;
|
|
344
|
+
let entries;
|
|
345
|
+
try {
|
|
346
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
// Direct-child shortcut: if this directory is `obj`, check for
|
|
352
|
+
// the file right here before recursing.
|
|
353
|
+
for (const e of entries) {
|
|
354
|
+
if (e.isFile() && e.name === 'project.assets.json') {
|
|
355
|
+
// Only accept if parent directory is `obj`.
|
|
356
|
+
if (path.basename(dir) === 'obj')
|
|
357
|
+
return path.join(dir, e.name);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
for (const e of entries) {
|
|
361
|
+
if (e.name.startsWith('.') ||
|
|
362
|
+
['node_modules', 'bin', 'TestResults', 'packages'].includes(e.name)) {
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
if (e.isDirectory()) {
|
|
366
|
+
const nested = search(path.join(dir, e.name), depth + 1);
|
|
367
|
+
if (nested)
|
|
368
|
+
return nested;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
return search(cwd, 0);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Read + parse `obj/project.assets.json` and build the top-level
|
|
377
|
+
* attribution index. Returns an empty map on any failure — transitive
|
|
378
|
+
* findings simply ship without attribution rather than blocking the
|
|
379
|
+
* scan. Matches Python pack's missing-venv semantics.
|
|
380
|
+
*/
|
|
381
|
+
function loadCsharpTopLevelDepIndex(cwd) {
|
|
382
|
+
const assetsPath = findProjectAssetsJson(cwd);
|
|
383
|
+
if (!assetsPath)
|
|
384
|
+
return new Map();
|
|
385
|
+
let raw;
|
|
386
|
+
try {
|
|
387
|
+
raw = fs.readFileSync(assetsPath, 'utf-8');
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
return new Map();
|
|
391
|
+
}
|
|
392
|
+
const parsed = parseProjectAssetsJson(raw);
|
|
393
|
+
if (!parsed)
|
|
394
|
+
return new Map();
|
|
395
|
+
return buildCsharpTopLevelDepIndex(parsed);
|
|
396
|
+
}
|
|
229
397
|
/**
|
|
230
398
|
* Single source of truth for the csharp pack's dep-vuln gathering.
|
|
231
399
|
* Consumed by `csharpDepVulnsProvider` (capability dispatcher). Runs
|
|
@@ -240,13 +408,35 @@ function parseDotnetVulnerableOutput(raw) {
|
|
|
240
408
|
async function gatherCsharpDepVulnsResult(cwd) {
|
|
241
409
|
if (!hasCsharpProject(cwd))
|
|
242
410
|
return { kind: 'tool-missing' };
|
|
243
|
-
|
|
411
|
+
// `--include-transitive` (10h.4.4.c) extends the scan to indirect
|
|
412
|
+
// deps; without it NuGet would only report vulns where the
|
|
413
|
+
// vulnerable package is itself declared in .csproj. Transitive
|
|
414
|
+
// attribution lands via `project.assets.json` below.
|
|
415
|
+
const vulnRaw = (0, runner_1.run)('dotnet list package --vulnerable --include-transitive --format json 2>/dev/null', cwd, 120000);
|
|
244
416
|
if (!vulnRaw)
|
|
245
417
|
return { kind: 'no-output' };
|
|
246
418
|
const parsed = parseDotnetVulnerableOutput(vulnRaw);
|
|
247
419
|
if (!parsed)
|
|
248
420
|
return { kind: 'parse-error' };
|
|
249
421
|
const { counts, findings } = parsed;
|
|
422
|
+
// Attach top-level attribution to transitive findings (top-level
|
|
423
|
+
// findings already carry self-attribution from the parser). Skipped
|
|
424
|
+
// when project.assets.json is absent — user hasn't run
|
|
425
|
+
// `dotnet restore`, or the obj/ dir was cleaned. Findings ship with
|
|
426
|
+
// `topLevelDep` unset in that case, matching Python's no-venv path.
|
|
427
|
+
const transitiveNeedsAttribution = findings.some((f) => !f.topLevelDep || f.topLevelDep.length === 0);
|
|
428
|
+
if (transitiveNeedsAttribution) {
|
|
429
|
+
const topLevelIndex = loadCsharpTopLevelDepIndex(cwd);
|
|
430
|
+
if (topLevelIndex.size > 0) {
|
|
431
|
+
for (const f of findings) {
|
|
432
|
+
if (f.topLevelDep && f.topLevelDep.length > 0)
|
|
433
|
+
continue;
|
|
434
|
+
const parents = topLevelIndex.get(f.package);
|
|
435
|
+
if (parents && parents.length > 0)
|
|
436
|
+
f.topLevelDep = parents;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
250
440
|
// Alias-fallback CVSS pass: dotnet --vulnerable ships zero CVSS data
|
|
251
441
|
// per advisory; the GHSA id (extracted from advisoryUrl) is the only
|
|
252
442
|
// anchor. resolveCvssScores looks up via GHSA → CVE alias chain.
|