autoremediator 0.17.0 → 0.19.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 +20 -27
- package/dist/api/change-request/index.d.ts +2 -1
- package/dist/api/change-request/index.d.ts.map +1 -1
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/options-schema.d.ts +3 -0
- package/dist/api/options-schema.d.ts.map +1 -1
- package/dist/api/patches/index.d.ts +1 -0
- package/dist/api/patches/index.d.ts.map +1 -1
- package/dist/api/patches/reconcile.d.ts +7 -0
- package/dist/api/patches/reconcile.d.ts.map +1 -0
- package/dist/api/patches/reconcile.test.d.ts +2 -0
- package/dist/api/patches/reconcile.test.d.ts.map +1 -0
- package/dist/api/remediate/validators.d.ts +3 -0
- package/dist/api/remediate/validators.d.ts.map +1 -1
- package/dist/{chunk-U4LIJIGD.js → chunk-7BORIBPY.js} +2476 -885
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/runners.d.ts +5 -0
- package/dist/cli/runners.d.ts.map +1 -1
- package/dist/cli/triage.d.ts +7 -0
- package/dist/cli/triage.d.ts.map +1 -0
- package/dist/cli/types.d.ts +5 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli.js +233 -6
- package/dist/index.js +2479 -889
- package/dist/index.js.map +1 -1
- package/dist/intelligence/sources/github-advisory.d.ts.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/openapi/server.js +1 -1
- package/dist/platform/evidence.d.ts +2 -0
- package/dist/platform/evidence.d.ts.map +1 -1
- package/dist/platform/package-manager/index.d.ts +1 -0
- package/dist/platform/package-manager/index.d.ts.map +1 -1
- package/dist/platform/supply-chain.d.ts +10 -0
- package/dist/platform/supply-chain.d.ts.map +1 -0
- package/dist/platform/supply-chain.test.d.ts +2 -0
- package/dist/platform/supply-chain.test.d.ts.map +1 -0
- package/dist/platform/types.d.ts +69 -6
- package/dist/platform/types.d.ts.map +1 -1
- package/dist/platform/workspace.d.ts +28 -0
- package/dist/platform/workspace.d.ts.map +1 -0
- package/dist/platform/workspace.test.d.ts +2 -0
- package/dist/platform/workspace.test.d.ts.map +1 -0
- package/dist/remediation/local/fallback.d.ts +2 -0
- package/dist/remediation/local/fallback.d.ts.map +1 -1
- package/dist/remediation/local/options.d.ts +3 -0
- package/dist/remediation/local/options.d.ts.map +1 -1
- package/dist/remediation/local/primary-strategy.d.ts +2 -9
- package/dist/remediation/local/primary-strategy.d.ts.map +1 -1
- package/dist/remediation/local/run.d.ts.map +1 -1
- package/dist/remediation/pipeline-runtime/tool-wrappers.d.ts.map +1 -1
- package/dist/remediation/proof-of-fix/runner.d.ts +16 -0
- package/dist/remediation/proof-of-fix/runner.d.ts.map +1 -0
- package/dist/remediation/proof-of-fix/runner.test.d.ts +2 -0
- package/dist/remediation/proof-of-fix/runner.test.d.ts.map +1 -0
- package/dist/remediation/refactor/call-site-finder.d.ts +15 -0
- package/dist/remediation/refactor/call-site-finder.d.ts.map +1 -0
- package/dist/remediation/refactor/refactor-agent.d.ts +34 -0
- package/dist/remediation/refactor/refactor-agent.d.ts.map +1 -0
- package/dist/remediation/refactor/refactor.test.d.ts +2 -0
- package/dist/remediation/refactor/refactor.test.d.ts.map +1 -0
- package/dist/remediation/strategies/patch-synthesis-prompt.d.ts.map +1 -1
- package/dist/remediation/tools/apply-patch-file/index.d.ts +5 -1
- package/dist/remediation/tools/apply-patch-file/index.d.ts.map +1 -1
- package/dist/remediation/tools/apply-version-bump.d.ts +2 -0
- package/dist/remediation/tools/apply-version-bump.d.ts.map +1 -1
- package/dist/remediation/tools/check-inventory.d.ts.map +1 -1
- package/dist/remediation/tools/check-reachability.d.ts +6 -1
- package/dist/remediation/tools/check-reachability.d.ts.map +1 -1
- package/dist/remediation/tools/generate-patch/helpers.d.ts +1 -0
- package/dist/remediation/tools/generate-patch/helpers.d.ts.map +1 -1
- package/dist/remediation/tools/generate-patch/index.d.ts +1 -0
- package/dist/remediation/tools/generate-patch/index.d.ts.map +1 -1
- package/dist/scanner/adapters/npm-audit.d.ts.map +1 -1
- package/dist/scanner/adapters/yarn-audit.d.ts.map +1 -1
- package/dist/scanner/delta-scan.d.ts.map +1 -1
- package/dist/scanner/lockfile-diff.d.ts +10 -0
- package/dist/scanner/lockfile-diff.d.ts.map +1 -0
- package/dist/scanner/lockfile-diff.test.d.ts +2 -0
- package/dist/scanner/lockfile-diff.test.d.ts.map +1 -0
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuJpC,wBAAgB,aAAa,IAAI,OAAO,CA+TvC"}
|
package/dist/cli/runners.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { runInteractiveTriage } from "./triage.js";
|
|
2
|
+
export { runInteractiveTriage };
|
|
1
3
|
import type { CommandOptions } from "./types.js";
|
|
2
4
|
export declare function runSingleCve(cveId: string, opts: CommandOptions): Promise<void>;
|
|
3
5
|
export declare function runScanInput(inputPath: string, opts: CommandOptions): Promise<void>;
|
|
@@ -23,4 +25,7 @@ export declare function runDiffAudit(opts: {
|
|
|
23
25
|
outputFormat?: string;
|
|
24
26
|
ci?: boolean;
|
|
25
27
|
}): Promise<void>;
|
|
28
|
+
export declare function runReconcilePatches(opts: Pick<CommandOptions, "cwd" | "patchesDir" | "packageManager" | "runTests" | "outputFormat"> & {
|
|
29
|
+
autoApply?: boolean;
|
|
30
|
+
}): Promise<void>;
|
|
26
31
|
//# sourceMappingURL=runners.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runners.d.ts","sourceRoot":"","sources":["../../src/cli/runners.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runners.d.ts","sourceRoot":"","sources":["../../src/cli/runners.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAGhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAkFjD,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAkJrF;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA+KzF;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,YAAY,GAAG,cAAc,CAAC,GAChE,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,YAAY,GAAG,cAAc,CAAC,GAChE,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,YAAY,GAAG,gBAAgB,GAAG,cAAc,CAAC,GACnF,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA+C3E;AAED,wBAAsB,YAAY,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6F/F;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBhB;AAED,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACJ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,CAAC,EAAE,OAAO,CAAC;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,CACR,cAAc,EACd,KAAK,GAAG,YAAY,GAAG,gBAAgB,GAAG,UAAU,GAAG,cAAc,CACtE,GAAG;IACF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GACA,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CommandOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Interactive developer CLI triage workflow.
|
|
4
|
+
* Prompts developer through security findings with actions to apply, skip, suppress, or quit.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runInteractiveTriage(inputPathOrOpts: string | Partial<CommandOptions>, maybeOpts?: Partial<CommandOptions>): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=triage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage.d.ts","sourceRoot":"","sources":["../../src/cli/triage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,EACjD,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAClC,OAAO,CAAC,IAAI,CAAC,CAyIf"}
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface CommandOptions {
|
|
|
9
9
|
preview: boolean;
|
|
10
10
|
simulationMode: boolean;
|
|
11
11
|
runTests: boolean;
|
|
12
|
+
typecheck?: boolean;
|
|
13
|
+
interactive?: boolean;
|
|
12
14
|
outputFormat: OutputFormat;
|
|
13
15
|
llmProvider?: "remote" | "local";
|
|
14
16
|
model?: string;
|
|
@@ -64,6 +66,9 @@ export interface CommandOptions {
|
|
|
64
66
|
campaignMode?: boolean;
|
|
65
67
|
offline: boolean;
|
|
66
68
|
intelligenceSnapshot?: string;
|
|
69
|
+
proofOfFix?: boolean;
|
|
70
|
+
requireProofOfFix?: boolean;
|
|
71
|
+
breakingChangeRefactor?: boolean;
|
|
67
72
|
}
|
|
68
73
|
export declare function isCveId(value: string): boolean;
|
|
69
74
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/cli/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,GAAG,OAAO,CAAC;AACvE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,eAAe,CAAC;AAEvE,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
evaluatePackage,
|
|
11
11
|
inspectPatchArtifact,
|
|
12
12
|
listPatchArtifacts,
|
|
13
|
+
parseScanInput,
|
|
14
|
+
parseScanInputFromAudit,
|
|
15
|
+
reconcilePatchArtifacts,
|
|
13
16
|
remediate,
|
|
14
17
|
remediateFromScan,
|
|
15
18
|
remediatePortfolio,
|
|
@@ -17,9 +20,10 @@ import {
|
|
|
17
20
|
toCiSummary,
|
|
18
21
|
toCycloneDxVex,
|
|
19
22
|
toSarifOutput,
|
|
23
|
+
uniqueCveIds,
|
|
20
24
|
updateOutdated,
|
|
21
25
|
validatePatchArtifact
|
|
22
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-7BORIBPY.js";
|
|
23
27
|
|
|
24
28
|
// src/cli/index.ts
|
|
25
29
|
import { fileURLToPath } from "url";
|
|
@@ -28,6 +32,150 @@ import { fileURLToPath } from "url";
|
|
|
28
32
|
import { Command } from "commander";
|
|
29
33
|
import { existsSync } from "fs";
|
|
30
34
|
|
|
35
|
+
// src/cli/triage.ts
|
|
36
|
+
import * as readline from "readline/promises";
|
|
37
|
+
import { stdin as input, stdout as output } from "process";
|
|
38
|
+
async function runInteractiveTriage(inputPathOrOpts, maybeOpts) {
|
|
39
|
+
const inputPath = typeof inputPathOrOpts === "string" ? inputPathOrOpts : inputPathOrOpts.input;
|
|
40
|
+
const opts = (typeof inputPathOrOpts === "object" ? inputPathOrOpts : maybeOpts) ?? {};
|
|
41
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
42
|
+
output.write("\n\u{1F50D} Scanning for security findings to triage...\n");
|
|
43
|
+
let findings = [];
|
|
44
|
+
try {
|
|
45
|
+
if (inputPath) {
|
|
46
|
+
findings = parseScanInput(inputPath, opts.format ?? "auto");
|
|
47
|
+
} else {
|
|
48
|
+
findings = await parseScanInputFromAudit({
|
|
49
|
+
cwd,
|
|
50
|
+
packageManager: opts.packageManager,
|
|
51
|
+
format: opts.format ?? "auto",
|
|
52
|
+
workspace: opts.workspace
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
} catch (err) {
|
|
56
|
+
output.write(
|
|
57
|
+
`Failed to load scan findings: ${err instanceof Error ? err.message : String(err)}
|
|
58
|
+
`
|
|
59
|
+
);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const cveIds = uniqueCveIds(findings);
|
|
63
|
+
if (cveIds.length === 0) {
|
|
64
|
+
output.write("\u2728 No vulnerabilities found to triage!\n\n");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
output.write(`Found ${cveIds.length} unique vulnerability(ies) to triage.
|
|
68
|
+
`);
|
|
69
|
+
const rl = readline.createInterface({ input, output });
|
|
70
|
+
let remediatedCount = 0;
|
|
71
|
+
let skippedCount = 0;
|
|
72
|
+
let suppressedCount = 0;
|
|
73
|
+
try {
|
|
74
|
+
for (let i = 0; i < cveIds.length; i++) {
|
|
75
|
+
const cveId = cveIds[i];
|
|
76
|
+
const matchingFindings = findings.filter(
|
|
77
|
+
(f) => f.cveId.toUpperCase() === cveId.toUpperCase()
|
|
78
|
+
);
|
|
79
|
+
const firstFinding = matchingFindings[0];
|
|
80
|
+
const pkgName = firstFinding?.packageName ?? "unknown package";
|
|
81
|
+
const severity = firstFinding?.severity ?? "UNKNOWN";
|
|
82
|
+
let safeVersion;
|
|
83
|
+
if (pkgName !== "unknown package") {
|
|
84
|
+
try {
|
|
85
|
+
const evalRes = await evaluatePackage(pkgName, { enrichIntelligence: true });
|
|
86
|
+
const matchingVuln = evalRes.vulnerabilities.find(
|
|
87
|
+
(v) => v.cveId.toUpperCase() === cveId.toUpperCase()
|
|
88
|
+
);
|
|
89
|
+
safeVersion = matchingVuln?.safeUpgradeVersion ?? evalRes.vulnerabilities.find((v) => v.safeUpgradeVersion)?.safeUpgradeVersion;
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
output.write("\n" + "=".repeat(60) + "\n");
|
|
94
|
+
output.write(`[${i + 1}/${cveIds.length}] Vulnerability: ${cveId}
|
|
95
|
+
`);
|
|
96
|
+
output.write(` Package: ${pkgName}
|
|
97
|
+
`);
|
|
98
|
+
output.write(` Severity: ${severity}
|
|
99
|
+
`);
|
|
100
|
+
if (safeVersion) {
|
|
101
|
+
output.write(` Safe Upstream Version: ${safeVersion}
|
|
102
|
+
`);
|
|
103
|
+
}
|
|
104
|
+
output.write("=".repeat(60) + "\n");
|
|
105
|
+
let answered = false;
|
|
106
|
+
while (!answered) {
|
|
107
|
+
const answer = await rl.question(
|
|
108
|
+
"Action: [a]pply fix, [s]kip, [x] suppress/vex, [q]uit triage? [a/s/x/q]: "
|
|
109
|
+
);
|
|
110
|
+
const choice = answer.trim().toLowerCase();
|
|
111
|
+
if (choice === "a" || choice === "apply") {
|
|
112
|
+
output.write(`Applying remediation for ${cveId}...
|
|
113
|
+
`);
|
|
114
|
+
try {
|
|
115
|
+
const report = await remediate(cveId, {
|
|
116
|
+
cwd,
|
|
117
|
+
packageManager: opts.packageManager,
|
|
118
|
+
patchesDir: opts.patchesDir,
|
|
119
|
+
policy: opts.policy,
|
|
120
|
+
runTests: opts.runTests,
|
|
121
|
+
constraints: {
|
|
122
|
+
directDependenciesOnly: opts.directDependenciesOnly,
|
|
123
|
+
preferVersionBump: opts.preferVersionBump,
|
|
124
|
+
workspace: opts.workspace
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
const applied = report.results.some((r) => r.applied);
|
|
128
|
+
if (applied) {
|
|
129
|
+
output.write(`\u2705 Successfully applied remediation for ${cveId}!
|
|
130
|
+
`);
|
|
131
|
+
remediatedCount++;
|
|
132
|
+
} else {
|
|
133
|
+
const reason = report.results[0]?.unresolvedReason ?? "unresolved";
|
|
134
|
+
output.write(`\u26A0\uFE0F Remediation could not be applied automatically (${reason}).
|
|
135
|
+
`);
|
|
136
|
+
skippedCount++;
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
output.write(
|
|
140
|
+
`\u274C Error remediating ${cveId}: ${err instanceof Error ? err.message : String(err)}
|
|
141
|
+
`
|
|
142
|
+
);
|
|
143
|
+
skippedCount++;
|
|
144
|
+
}
|
|
145
|
+
answered = true;
|
|
146
|
+
} else if (choice === "s" || choice === "skip" || choice === "") {
|
|
147
|
+
output.write(`Skipped ${cveId}.
|
|
148
|
+
`);
|
|
149
|
+
skippedCount++;
|
|
150
|
+
answered = true;
|
|
151
|
+
} else if (choice === "x" || choice === "suppress") {
|
|
152
|
+
output.write(`Marked ${cveId} as suppressed / VEX excluded.
|
|
153
|
+
`);
|
|
154
|
+
suppressedCount++;
|
|
155
|
+
answered = true;
|
|
156
|
+
} else if (choice === "q" || choice === "quit") {
|
|
157
|
+
output.write("Exiting triage session.\n");
|
|
158
|
+
return;
|
|
159
|
+
} else {
|
|
160
|
+
output.write("Invalid option. Please choose 'a', 's', 'x', or 'q'.\n");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
} finally {
|
|
165
|
+
rl.close();
|
|
166
|
+
output.write("\n=== Triage Summary ===\n");
|
|
167
|
+
output.write(`Total evaluated: ${cveIds.length}
|
|
168
|
+
`);
|
|
169
|
+
output.write(`Remediated: ${remediatedCount}
|
|
170
|
+
`);
|
|
171
|
+
output.write(`Suppressed: ${suppressedCount}
|
|
172
|
+
`);
|
|
173
|
+
output.write(`Skipped: ${skippedCount}
|
|
174
|
+
|
|
175
|
+
`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
31
179
|
// src/cli/runners.ts
|
|
32
180
|
import { readFileSync, writeFileSync } from "fs";
|
|
33
181
|
|
|
@@ -102,6 +250,7 @@ async function runSingleCve(cveId, opts) {
|
|
|
102
250
|
preview: opts.preview,
|
|
103
251
|
simulationMode: opts.simulationMode,
|
|
104
252
|
runTests: opts.runTests,
|
|
253
|
+
typecheck: opts.typecheck,
|
|
105
254
|
patchesDir: opts.patchesDir,
|
|
106
255
|
policy: opts.policy,
|
|
107
256
|
evidence: opts.evidence,
|
|
@@ -146,7 +295,10 @@ async function runSingleCve(cveId, opts) {
|
|
|
146
295
|
changeRequest,
|
|
147
296
|
dispositionPolicy: resolveDispositionPolicy(opts),
|
|
148
297
|
offlineIntelligence: opts.offline,
|
|
149
|
-
intelligenceSnapshotPath: opts.intelligenceSnapshot
|
|
298
|
+
intelligenceSnapshotPath: opts.intelligenceSnapshot,
|
|
299
|
+
proofOfFix: opts.proofOfFix,
|
|
300
|
+
requireProofOfFix: opts.requireProofOfFix,
|
|
301
|
+
breakingChangeRefactor: opts.breakingChangeRefactor
|
|
150
302
|
});
|
|
151
303
|
const reportAsScan = asSingleCveScanReport(report);
|
|
152
304
|
if (opts.outputFormat === "sarif") {
|
|
@@ -220,6 +372,10 @@ async function runSingleCve(cveId, opts) {
|
|
|
220
372
|
}
|
|
221
373
|
}
|
|
222
374
|
async function runScanInput(inputPath, opts) {
|
|
375
|
+
if (opts.interactive) {
|
|
376
|
+
await runInteractiveTriage(inputPath, opts);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
223
379
|
const changeRequest = resolveChangeRequestOptions(opts);
|
|
224
380
|
const report = await remediateFromScan(inputPath, {
|
|
225
381
|
cwd: opts.cwd,
|
|
@@ -232,6 +388,7 @@ async function runScanInput(inputPath, opts) {
|
|
|
232
388
|
preview: opts.preview,
|
|
233
389
|
simulationMode: opts.simulationMode,
|
|
234
390
|
runTests: opts.runTests,
|
|
391
|
+
typecheck: opts.typecheck,
|
|
235
392
|
llmProvider: opts.llmProvider,
|
|
236
393
|
model: opts.model,
|
|
237
394
|
modelPersonality: opts.modelPersonality,
|
|
@@ -275,7 +432,10 @@ async function runScanInput(inputPath, opts) {
|
|
|
275
432
|
changeRequest,
|
|
276
433
|
dispositionPolicy: resolveDispositionPolicy(opts),
|
|
277
434
|
offlineIntelligence: opts.offline,
|
|
278
|
-
intelligenceSnapshotPath: opts.intelligenceSnapshot
|
|
435
|
+
intelligenceSnapshotPath: opts.intelligenceSnapshot,
|
|
436
|
+
proofOfFix: opts.proofOfFix,
|
|
437
|
+
requireProofOfFix: opts.requireProofOfFix,
|
|
438
|
+
breakingChangeRefactor: opts.breakingChangeRefactor
|
|
279
439
|
});
|
|
280
440
|
if (opts.summaryFile) {
|
|
281
441
|
const summary = toCiSummary(report);
|
|
@@ -704,10 +864,42 @@ Introduced Findings:
|
|
|
704
864
|
process.exitCode = report.netRiskVerdict === "degraded" ? 1 : 0;
|
|
705
865
|
}
|
|
706
866
|
}
|
|
867
|
+
async function runReconcilePatches(opts) {
|
|
868
|
+
const report = await reconcilePatchArtifacts({
|
|
869
|
+
cwd: opts.cwd,
|
|
870
|
+
patchesDir: opts.patchesDir,
|
|
871
|
+
packageManager: opts.packageManager,
|
|
872
|
+
autoApply: opts.autoApply,
|
|
873
|
+
runTests: opts.runTests
|
|
874
|
+
});
|
|
875
|
+
if (opts.outputFormat === "json") {
|
|
876
|
+
logJson(report);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
process.stdout.write(`=== Patch Artifact Reconciliation ===
|
|
880
|
+
`);
|
|
881
|
+
process.stdout.write(`Reconciled (upgraded): ${report.reconciledCount}
|
|
882
|
+
`);
|
|
883
|
+
process.stdout.write(`Retained: ${report.retainedCount}
|
|
884
|
+
|
|
885
|
+
`);
|
|
886
|
+
for (const item of report.reconciled) {
|
|
887
|
+
process.stdout.write(`- [${item.status}] ${item.packageName} (${item.patchFilePath})
|
|
888
|
+
`);
|
|
889
|
+
if (item.safeUpstreamVersion) {
|
|
890
|
+
process.stdout.write(` Safe Upstream Version: ${item.safeUpstreamVersion}
|
|
891
|
+
`);
|
|
892
|
+
}
|
|
893
|
+
if (item.reason) {
|
|
894
|
+
process.stdout.write(` Reason: ${item.reason}
|
|
895
|
+
`);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
707
899
|
|
|
708
900
|
// src/cli/types.ts
|
|
709
901
|
function isCveId(value) {
|
|
710
|
-
return /^CVE-\d{4}-\d{1,7}$/i.test(value);
|
|
902
|
+
return /^CVE-\d{4}-\d{1,7}$/i.test(value) || /^GHSA-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}$/i.test(value);
|
|
711
903
|
}
|
|
712
904
|
|
|
713
905
|
// src/cli/validators.ts
|
|
@@ -749,7 +941,11 @@ function validateOutputFormat(outputFormat, supported, commandName) {
|
|
|
749
941
|
// src/cli/program.ts
|
|
750
942
|
function addSharedOptions(program, includeInput = false, includeSimulationMode = true) {
|
|
751
943
|
const parseBooleanFlag = (value) => value === "true";
|
|
752
|
-
program.option("--cwd <path>", OPTION_DESCRIPTIONS.cwd, process.cwd()).option("--package-manager <name>", OPTION_DESCRIPTIONS.packageManager).option("--patches-dir <path>", OPTION_DESCRIPTIONS.patchesDir).option("--dry-run", OPTION_DESCRIPTIONS.dryRun, false).option("--preview", OPTION_DESCRIPTIONS.preview, false).option("--run-tests", OPTION_DESCRIPTIONS.runTests, false).option(
|
|
944
|
+
program.option("--cwd <path>", OPTION_DESCRIPTIONS.cwd, process.cwd()).option("--package-manager <name>", OPTION_DESCRIPTIONS.packageManager).option("--patches-dir <path>", OPTION_DESCRIPTIONS.patchesDir).option("--dry-run", OPTION_DESCRIPTIONS.dryRun, false).option("--preview", OPTION_DESCRIPTIONS.preview, false).option("--run-tests", OPTION_DESCRIPTIONS.runTests, false).option(
|
|
945
|
+
"--typecheck",
|
|
946
|
+
"Enable typecheck validation (e.g. tsc --noEmit or npm run typecheck) after patching",
|
|
947
|
+
false
|
|
948
|
+
).option("-i, --interactive", "Launch interactive developer CLI triage workflow", false).option("--llm-provider <provider>", OPTION_DESCRIPTIONS.llmProvider).option("--model <name>", OPTION_DESCRIPTIONS.model).option("--model-personality <profile>", OPTION_DESCRIPTIONS.modelPersonality).option("--provider-safety-profile <profile>", OPTION_DESCRIPTIONS.providerSafetyProfile).option(
|
|
753
949
|
"--require-consensus-for-high-risk",
|
|
754
950
|
OPTION_DESCRIPTIONS.requireConsensusForHighRisk,
|
|
755
951
|
false
|
|
@@ -788,7 +984,11 @@ function addSharedOptions(program, includeInput = false, includeSimulationMode =
|
|
|
788
984
|
).option("--hold-for-transitive", OPTION_DESCRIPTIONS.dispositionPolicyHoldForTransitive, false).option("--escalate-on-kev", OPTION_DESCRIPTIONS.dispositionPolicyEscalateOnKev, false).option("--containment-mode", OPTION_DESCRIPTIONS.containmentMode, false).option("--campaign-mode", OPTION_DESCRIPTIONS.campaignMode, false).option("--offline", OPTION_DESCRIPTIONS.offlineIntelligence, false).option("--intelligence-snapshot <path>", OPTION_DESCRIPTIONS.intelligenceSnapshotPath).option("--create-change-request", OPTION_DESCRIPTIONS.createChangeRequest, false).option("--change-request-provider <provider>", OPTION_DESCRIPTIONS.changeRequestProvider).option("--change-request-grouping <grouping>", OPTION_DESCRIPTIONS.changeRequestGrouping).option("--change-request-repository <repository>", OPTION_DESCRIPTIONS.changeRequestRepository).option("--change-request-base-branch <branch>", OPTION_DESCRIPTIONS.changeRequestBaseBranch).option(
|
|
789
985
|
"--change-request-branch-prefix <prefix>",
|
|
790
986
|
OPTION_DESCRIPTIONS.changeRequestBranchPrefix
|
|
791
|
-
).option("--change-request-title-prefix <prefix>", OPTION_DESCRIPTIONS.changeRequestTitlePrefix)
|
|
987
|
+
).option("--change-request-title-prefix <prefix>", OPTION_DESCRIPTIONS.changeRequestTitlePrefix).option("--proof-of-fix", OPTION_DESCRIPTIONS.proofOfFix, false).option("--require-proof-of-fix", OPTION_DESCRIPTIONS.requireProofOfFix, false).option(
|
|
988
|
+
"--breaking-change-refactor",
|
|
989
|
+
OPTION_DESCRIPTIONS.breakingChangeRefactor,
|
|
990
|
+
false
|
|
991
|
+
);
|
|
792
992
|
if (includeSimulationMode) {
|
|
793
993
|
program.option("--simulation-mode", OPTION_DESCRIPTIONS.simulationMode, false);
|
|
794
994
|
}
|
|
@@ -890,6 +1090,26 @@ function createProgram() {
|
|
|
890
1090
|
await runValidatePatch(patchPath, merged);
|
|
891
1091
|
}
|
|
892
1092
|
);
|
|
1093
|
+
patches.command("reconcile").description(
|
|
1094
|
+
"Reconcile active patch artifacts against upstream registries to retire obsolete patches"
|
|
1095
|
+
).option("--cwd <path>", OPTION_DESCRIPTIONS.cwd, process.cwd()).option("--patches-dir <path>", OPTION_DESCRIPTIONS.patchesDir).option(
|
|
1096
|
+
"--auto-apply",
|
|
1097
|
+
"Automatically upgrade packages and remove retired patch artifacts",
|
|
1098
|
+
false
|
|
1099
|
+
).option("--run-tests", OPTION_DESCRIPTIONS.runTests, false).option("--package-manager <name>", OPTION_DESCRIPTIONS.packageManager).option("--output-format <format>", "Output format: text|json", "text").action(
|
|
1100
|
+
async (opts, command) => {
|
|
1101
|
+
const merged = {
|
|
1102
|
+
...command.optsWithGlobals(),
|
|
1103
|
+
...opts
|
|
1104
|
+
};
|
|
1105
|
+
validateOutputFormat(
|
|
1106
|
+
merged.outputFormat ?? "text",
|
|
1107
|
+
["text", "json"],
|
|
1108
|
+
"patches reconcile"
|
|
1109
|
+
);
|
|
1110
|
+
await runReconcilePatches(merged);
|
|
1111
|
+
}
|
|
1112
|
+
);
|
|
893
1113
|
program.command("reachability").description("Perform AST call-graph reachability analysis for a package or vulnerable symbol").requiredOption("--package <name>", "Target package name to search").option("--symbol <name>", "Optional specific vulnerable function or export symbol to check").option("--cwd <path>", OPTION_DESCRIPTIONS.cwd, process.cwd()).option("--output-format <format>", "Output format: text|json", "text").action(
|
|
894
1114
|
async (opts) => {
|
|
895
1115
|
validateOutputFormat(
|
|
@@ -931,12 +1151,19 @@ function createProgram() {
|
|
|
931
1151
|
);
|
|
932
1152
|
await runDiffAudit(opts);
|
|
933
1153
|
});
|
|
1154
|
+
program.command("triage [input]").description("Interactively triage discovered vulnerabilities step-by-step").option("--cwd <path>", OPTION_DESCRIPTIONS.cwd, process.cwd()).option("--package-manager <name>", OPTION_DESCRIPTIONS.packageManager).option("--patches-dir <path>", OPTION_DESCRIPTIONS.patchesDir).option("--format <format>", OPTION_DESCRIPTIONS.format, "auto").option("--run-tests", OPTION_DESCRIPTIONS.runTests, false).option("--policy <path>", OPTION_DESCRIPTIONS.policy).action(async (inputArg, opts) => {
|
|
1155
|
+
await runInteractiveTriage(inputArg ? inputArg : opts, opts);
|
|
1156
|
+
});
|
|
934
1157
|
addSharedOptions(
|
|
935
1158
|
program.argument("[target]", "Scanner output file path (or CVE ID fallback)").option("--format <type>", OPTION_DESCRIPTIONS.format, "auto").option("--summary-file <path>", "Write machine-readable scan summary JSON to path"),
|
|
936
1159
|
true
|
|
937
1160
|
).action(async (target, opts) => {
|
|
938
1161
|
validateSharedCommandOptions(opts);
|
|
939
1162
|
validateOutputFormat(opts.outputFormat, ["text", "json", "sarif"], "default");
|
|
1163
|
+
if (opts.interactive) {
|
|
1164
|
+
await runInteractiveTriage(opts.input ?? target ?? opts, opts);
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
940
1167
|
if (opts.audit) {
|
|
941
1168
|
await runScanInput(opts.input ?? target ?? "", opts);
|
|
942
1169
|
return;
|