autoremediator 0.11.0 → 0.12.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/dist/{chunk-GYCZ6L3O.js → chunk-575GEUAY.js} +399 -49
- package/dist/chunk-575GEUAY.js.map +1 -0
- package/dist/cli.js +186 -17
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +56 -8
- package/dist/index.js +398 -48
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +51 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/openapi/server.js +86 -4
- package/dist/openapi/server.js.map +1 -1
- package/llms.txt +4 -4
- package/package.json +1 -1
- package/dist/chunk-GYCZ6L3O.js.map +0 -1
|
@@ -40,7 +40,14 @@ var OPTION_DESCRIPTIONS = {
|
|
|
40
40
|
installPreferOffline: "Override prefer-offline flag behavior for install commands",
|
|
41
41
|
enforceFrozenLockfile: "Override frozen lockfile behavior for install commands",
|
|
42
42
|
workspace: "Workspace/package selector for scoped remediation in monorepos",
|
|
43
|
-
|
|
43
|
+
createChangeRequest: "Enable creation of native pull request / merge request after remediation",
|
|
44
|
+
changeRequestProvider: "Change request provider (github|gitlab)",
|
|
45
|
+
changeRequestGrouping: "Grouping strategy for change requests (all|per-cve|per-package)",
|
|
46
|
+
changeRequestRepository: "Repository slug override for change request creation",
|
|
47
|
+
changeRequestBaseBranch: "Base branch used for change request targeting",
|
|
48
|
+
changeRequestBranchPrefix: "Branch prefix for generated change request branches",
|
|
49
|
+
changeRequestTitlePrefix: "Title prefix for generated change requests",
|
|
50
|
+
includeTransitive: "Include transitive dependencies in the outdated check. Default: false.",
|
|
44
51
|
updateOutdated: "Run in update-outdated mode: bump all outdated npm packages without requiring a CVE.",
|
|
45
52
|
kevMandatory: "If true, CVEs with active CISA KEV status bypass severity filtering and are treated as mandatory",
|
|
46
53
|
epssThreshold: "EPSS probability threshold (0..1) above which a CVE is treated as mandatory regardless of severity",
|
|
@@ -104,6 +111,26 @@ function createRemediateOptionSchemaProperties(options) {
|
|
|
104
111
|
type: "object",
|
|
105
112
|
properties: createConstraintSchemaProperties()
|
|
106
113
|
},
|
|
114
|
+
changeRequest: {
|
|
115
|
+
type: "object",
|
|
116
|
+
properties: {
|
|
117
|
+
enabled: { type: "boolean", description: OPTION_DESCRIPTIONS.createChangeRequest },
|
|
118
|
+
provider: {
|
|
119
|
+
type: "string",
|
|
120
|
+
enum: ["github", "gitlab"],
|
|
121
|
+
description: OPTION_DESCRIPTIONS.changeRequestProvider
|
|
122
|
+
},
|
|
123
|
+
grouping: {
|
|
124
|
+
type: "string",
|
|
125
|
+
enum: ["all", "per-cve", "per-package"],
|
|
126
|
+
description: OPTION_DESCRIPTIONS.changeRequestGrouping
|
|
127
|
+
},
|
|
128
|
+
repository: { type: "string", description: OPTION_DESCRIPTIONS.changeRequestRepository },
|
|
129
|
+
baseBranch: { type: "string", description: OPTION_DESCRIPTIONS.changeRequestBaseBranch },
|
|
130
|
+
branchPrefix: { type: "string", description: OPTION_DESCRIPTIONS.changeRequestBranchPrefix },
|
|
131
|
+
titlePrefix: { type: "string", description: OPTION_DESCRIPTIONS.changeRequestTitlePrefix }
|
|
132
|
+
}
|
|
133
|
+
},
|
|
107
134
|
kevMandatory: { type: "boolean", description: OPTION_DESCRIPTIONS.kevMandatory },
|
|
108
135
|
epssThreshold: { type: "number", minimum: 0, maximum: 1, description: OPTION_DESCRIPTIONS.epssThreshold },
|
|
109
136
|
suppressionsFile: { type: "string", description: OPTION_DESCRIPTIONS.suppressionsFile },
|
|
@@ -152,7 +179,8 @@ function createScanReportSchemaProperties() {
|
|
|
152
179
|
idempotencyKey: { type: "string" },
|
|
153
180
|
llmUsageCount: { type: "number" },
|
|
154
181
|
estimatedCostUsd: { type: "number" },
|
|
155
|
-
totalLlmLatencyMs: { type: "number" }
|
|
182
|
+
totalLlmLatencyMs: { type: "number" },
|
|
183
|
+
changeRequests: { type: "array", items: { type: "object" } }
|
|
156
184
|
};
|
|
157
185
|
}
|
|
158
186
|
function createUpdateOutdatedOptionSchemaProperties() {
|
|
@@ -477,8 +505,13 @@ async function inspectPatchArtifact(patchFilePath, options = {}) {
|
|
|
477
505
|
};
|
|
478
506
|
}
|
|
479
507
|
|
|
480
|
-
// src/remediation/tools/
|
|
508
|
+
// src/remediation/tools/tool-compat.ts
|
|
481
509
|
import { tool } from "ai";
|
|
510
|
+
function defineTool(config) {
|
|
511
|
+
return tool(config);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/remediation/tools/check-inventory.ts
|
|
482
515
|
import { z } from "zod";
|
|
483
516
|
import { readFileSync as readFileSync3 } from "fs";
|
|
484
517
|
import { join as join5 } from "path";
|
|
@@ -602,7 +635,7 @@ function checkSlaBreach(cveId, severity, publishedAt, slaPolicy) {
|
|
|
602
635
|
}
|
|
603
636
|
|
|
604
637
|
// src/remediation/tools/check-inventory.ts
|
|
605
|
-
var checkInventoryTool =
|
|
638
|
+
var checkInventoryTool = defineTool({
|
|
606
639
|
description: "Read the project's package.json and installed dependencies to list packages and exact versions. Must be called before checking version matches.",
|
|
607
640
|
parameters: z.object({
|
|
608
641
|
cwd: z.string().describe("Absolute path to the consumer project's root directory"),
|
|
@@ -643,7 +676,7 @@ var checkInventoryTool = tool({
|
|
|
643
676
|
packages.push({
|
|
644
677
|
name,
|
|
645
678
|
version,
|
|
646
|
-
type: isDirect ? "direct" : "
|
|
679
|
+
type: isDirect ? "direct" : "transitive"
|
|
647
680
|
});
|
|
648
681
|
}
|
|
649
682
|
if (packages.length === 0) {
|
|
@@ -1188,7 +1221,6 @@ async function enrichWithNvd(details) {
|
|
|
1188
1221
|
}
|
|
1189
1222
|
|
|
1190
1223
|
// src/remediation/tools/check-reachability.ts
|
|
1191
|
-
import { tool as tool2 } from "ai";
|
|
1192
1224
|
import { z as z2 } from "zod";
|
|
1193
1225
|
import { readdirSync, readFileSync as readFileSync5, statSync } from "fs";
|
|
1194
1226
|
import { join as join7, extname } from "path";
|
|
@@ -1264,7 +1296,7 @@ function assessPackageReachability(cwd, packageName) {
|
|
|
1264
1296
|
reason: `No import or require of '${packageName}' found in ${files.length} source file(s).`
|
|
1265
1297
|
};
|
|
1266
1298
|
}
|
|
1267
|
-
var checkReachabilityTool =
|
|
1299
|
+
var checkReachabilityTool = defineTool({
|
|
1268
1300
|
description: "Assess whether an npm package is statically reachable (imported) from the project's source files. Returns reachable, not-reachable, or unknown.",
|
|
1269
1301
|
parameters: z2.object({
|
|
1270
1302
|
cwd: z2.string().describe("Project root directory"),
|
|
@@ -1276,7 +1308,6 @@ var checkReachabilityTool = tool2({
|
|
|
1276
1308
|
});
|
|
1277
1309
|
|
|
1278
1310
|
// src/remediation/tools/check-exploit-signal.ts
|
|
1279
|
-
import { tool as tool3 } from "ai";
|
|
1280
1311
|
import { z as z3 } from "zod";
|
|
1281
1312
|
var kevSchema = z3.object({
|
|
1282
1313
|
knownExploited: z3.boolean(),
|
|
@@ -1294,7 +1325,7 @@ var exploitSignalPolicySchema = z3.object({
|
|
|
1294
1325
|
kev: z3.object({ mandatory: z3.boolean() }).optional(),
|
|
1295
1326
|
epss: z3.object({ mandatory: z3.boolean(), threshold: z3.number() }).optional()
|
|
1296
1327
|
}).optional();
|
|
1297
|
-
var checkExploitSignalTool =
|
|
1328
|
+
var checkExploitSignalTool = defineTool({
|
|
1298
1329
|
description: "Evaluate KEV and EPSS exploit signals for a CVE against policy thresholds. Returns whether the exploit signal overrides severity filtering (mandatory gate).",
|
|
1299
1330
|
parameters: z3.object({
|
|
1300
1331
|
cveDetails: z3.object({
|
|
@@ -1385,7 +1416,7 @@ function buildSbom(packages, vulnerableNames, results) {
|
|
|
1385
1416
|
const entry = {
|
|
1386
1417
|
name: pkg.name,
|
|
1387
1418
|
version: pkg.version,
|
|
1388
|
-
scope: pkg.type === "direct" ? "direct" : "
|
|
1419
|
+
scope: pkg.type === "direct" ? "direct" : "transitive"
|
|
1389
1420
|
};
|
|
1390
1421
|
if (isVulnerable) {
|
|
1391
1422
|
entry.status = statusByPackage.get(pkg.name) ?? "unpatched";
|
|
@@ -1579,8 +1610,8 @@ async function queryOutdatedPackages(cwd, options = {}) {
|
|
|
1579
1610
|
const wantedVersion = entry.wanted ?? currentVersion;
|
|
1580
1611
|
const latestVersion = entry.latest ?? currentVersion;
|
|
1581
1612
|
if (!currentVersion || !latestVersion) continue;
|
|
1582
|
-
const dependencyScope = directDeps.has(name) ? "direct" : "
|
|
1583
|
-
if (!options.includeTransitive && dependencyScope === "
|
|
1613
|
+
const dependencyScope = directDeps.has(name) ? "direct" : "transitive";
|
|
1614
|
+
if (!options.includeTransitive && dependencyScope === "transitive") continue;
|
|
1584
1615
|
const isMajorBump = semver.valid(currentVersion) !== null && semver.valid(latestVersion) !== null && semver.major(latestVersion) > semver.major(currentVersion);
|
|
1585
1616
|
result.set(name, {
|
|
1586
1617
|
currentVersion,
|
|
@@ -1594,7 +1625,6 @@ async function queryOutdatedPackages(cwd, options = {}) {
|
|
|
1594
1625
|
}
|
|
1595
1626
|
|
|
1596
1627
|
// src/remediation/tools/apply-version-bump.ts
|
|
1597
|
-
import { tool as tool4 } from "ai";
|
|
1598
1628
|
import { z as z4 } from "zod";
|
|
1599
1629
|
import { join as join10 } from "path";
|
|
1600
1630
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
|
|
@@ -1641,7 +1671,7 @@ async function withRepoLock(cwd, fn, options) {
|
|
|
1641
1671
|
}
|
|
1642
1672
|
|
|
1643
1673
|
// src/remediation/tools/apply-version-bump.ts
|
|
1644
|
-
var applyVersionBumpTool =
|
|
1674
|
+
var applyVersionBumpTool = defineTool({
|
|
1645
1675
|
description: "Update package.json to use the safe version of a vulnerable package and run the project's package manager install. In dry-run mode, only reports what would change.",
|
|
1646
1676
|
parameters: z4.object({
|
|
1647
1677
|
cwd: z4.string().describe("Absolute path to the consumer project root"),
|
|
@@ -1734,8 +1764,8 @@ var applyVersionBumpTool = tool4({
|
|
|
1734
1764
|
fromVersion,
|
|
1735
1765
|
applied: false,
|
|
1736
1766
|
dryRun,
|
|
1737
|
-
unresolvedReason: "
|
|
1738
|
-
message: `"${packageName}" was not found in package.json dependencies (it may be a transitive
|
|
1767
|
+
unresolvedReason: "transitive-dependency",
|
|
1768
|
+
message: `"${packageName}" was not found in package.json dependencies (it may be a transitive dependency). Cannot auto-bump.`
|
|
1739
1769
|
};
|
|
1740
1770
|
}
|
|
1741
1771
|
const currentRange = pkgJson[depField][packageName];
|
|
@@ -1835,7 +1865,6 @@ var applyVersionBumpTool = tool4({
|
|
|
1835
1865
|
});
|
|
1836
1866
|
|
|
1837
1867
|
// src/remediation/tools/apply-package-override/index.ts
|
|
1838
|
-
import { tool as tool5 } from "ai";
|
|
1839
1868
|
import { z as z5 } from "zod";
|
|
1840
1869
|
import { join as join11 } from "path";
|
|
1841
1870
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
|
|
@@ -1918,7 +1947,7 @@ function restoreRecord(record, key, previousValue) {
|
|
|
1918
1947
|
}
|
|
1919
1948
|
|
|
1920
1949
|
// src/remediation/tools/apply-package-override/index.ts
|
|
1921
|
-
var applyPackageOverrideTool =
|
|
1950
|
+
var applyPackageOverrideTool = defineTool({
|
|
1922
1951
|
description: "Apply a package-manager-native package.json override for a vulnerable transitive dependency and reinstall. Uses npm overrides, pnpm.overrides, or yarn resolutions.",
|
|
1923
1952
|
parameters: z5.object({
|
|
1924
1953
|
cwd: z5.string().describe("Absolute path to the consumer project root"),
|
|
@@ -2092,7 +2121,7 @@ async function resolvePrimaryResult(params) {
|
|
|
2092
2121
|
const { vulnerable, cwd, packageManager, dryRun, policy, runTests, constraints } = params;
|
|
2093
2122
|
const pkg = vulnerable.installed;
|
|
2094
2123
|
const firstPatchedVersion = vulnerable.affected.firstPatchedVersion;
|
|
2095
|
-
if (pkg.type === "
|
|
2124
|
+
if (pkg.type === "transitive") {
|
|
2096
2125
|
if (constraints.directDependenciesOnly) {
|
|
2097
2126
|
return {
|
|
2098
2127
|
steps: 0,
|
|
@@ -2103,7 +2132,7 @@ async function resolvePrimaryResult(params) {
|
|
|
2103
2132
|
applied: false,
|
|
2104
2133
|
dryRun,
|
|
2105
2134
|
unresolvedReason: "constraint-blocked",
|
|
2106
|
-
message: `Constraint blocked remediation for
|
|
2135
|
+
message: `Constraint blocked remediation for transitive dependency "${pkg.name}".`
|
|
2107
2136
|
}
|
|
2108
2137
|
};
|
|
2109
2138
|
}
|
|
@@ -2229,12 +2258,11 @@ async function resolvePrimaryResult(params) {
|
|
|
2229
2258
|
}
|
|
2230
2259
|
|
|
2231
2260
|
// src/remediation/tools/fetch-package-source.ts
|
|
2232
|
-
import { tool as tool6 } from "ai";
|
|
2233
2261
|
import { z as z6 } from "zod";
|
|
2234
2262
|
import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, rm as rm2 } from "fs/promises";
|
|
2235
2263
|
import { join as join12 } from "path";
|
|
2236
2264
|
import { execa as execa8 } from "execa";
|
|
2237
|
-
var fetchPackageSourceTool =
|
|
2265
|
+
var fetchPackageSourceTool = defineTool({
|
|
2238
2266
|
description: "Download package tarball from npm and extract source files for CVE analysis. Supports custom file patterns (default: *.js, *.ts).",
|
|
2239
2267
|
parameters: z6.object({
|
|
2240
2268
|
packageName: z6.string().min(1).describe("The npm package name (e.g., 'lodash', '@scope/package')"),
|
|
@@ -2328,7 +2356,6 @@ var fetchPackageSourceTool = tool6({
|
|
|
2328
2356
|
});
|
|
2329
2357
|
|
|
2330
2358
|
// src/remediation/tools/generate-patch/index.ts
|
|
2331
|
-
import { tool as tool7 } from "ai";
|
|
2332
2359
|
import { z as z7 } from "zod";
|
|
2333
2360
|
import { generateText } from "ai";
|
|
2334
2361
|
|
|
@@ -2462,14 +2489,14 @@ function generateUnifiedDiff(original, fixed, filePath) {
|
|
|
2462
2489
|
}
|
|
2463
2490
|
|
|
2464
2491
|
// src/remediation/tools/generate-patch/index.ts
|
|
2465
|
-
var generatePatchTool =
|
|
2492
|
+
var generatePatchTool = defineTool({
|
|
2466
2493
|
description: "Generate a unified diff patch for a CVE using LLM analysis of vulnerable source code.",
|
|
2467
2494
|
parameters: z7.object({
|
|
2468
2495
|
packageName: z7.string().min(1).describe("The npm package name"),
|
|
2469
2496
|
vulnerableVersion: z7.string().describe("The vulnerable version string"),
|
|
2470
2497
|
cveId: z7.string().regex(/^CVE-\d{4}-\d+$/i).describe("CVE ID (e.g., CVE-2021-23337)"),
|
|
2471
2498
|
cveSummary: z7.string().min(10).describe("CVE description and impact"),
|
|
2472
|
-
sourceFiles: z7.record(z7.string()).describe(
|
|
2499
|
+
sourceFiles: z7.record(z7.string(), z7.string()).describe(
|
|
2473
2500
|
"Map of file paths to source code contents from fetch-package-source"
|
|
2474
2501
|
),
|
|
2475
2502
|
vulnerabilityCategory: z7.enum(["redos", "code-injection", "path-traversal", "unknown"]).optional().default("unknown").describe("Category of the vulnerability for better context"),
|
|
@@ -2531,7 +2558,7 @@ var generatePatchTool = tool7({
|
|
|
2531
2558
|
}
|
|
2532
2559
|
const inputChars = JSON.stringify(resolvedSourceFiles).length + cveSummary.length;
|
|
2533
2560
|
const modelInstance = await createModel(effectiveOptions, { inputChars });
|
|
2534
|
-
const modelName = modelInstance.modelId
|
|
2561
|
+
const modelName = typeof modelInstance === "string" ? modelInstance : "modelId" in modelInstance && typeof modelInstance.modelId === "string" ? modelInstance.modelId : "unknown-model";
|
|
2535
2562
|
const prompt = buildPatchPrompt({
|
|
2536
2563
|
cveId,
|
|
2537
2564
|
packageName,
|
|
@@ -2636,7 +2663,6 @@ var generatePatchTool = tool7({
|
|
|
2636
2663
|
});
|
|
2637
2664
|
|
|
2638
2665
|
// src/remediation/tools/apply-patch-file/index.ts
|
|
2639
|
-
import { tool as tool8 } from "ai";
|
|
2640
2666
|
import { z as z8 } from "zod";
|
|
2641
2667
|
import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
|
|
2642
2668
|
import { join as join14 } from "path";
|
|
@@ -2878,7 +2904,7 @@ function extractFailedTests(output) {
|
|
|
2878
2904
|
}
|
|
2879
2905
|
|
|
2880
2906
|
// src/remediation/tools/apply-patch-file/index.ts
|
|
2881
|
-
var applyPatchFileTool =
|
|
2907
|
+
var applyPatchFileTool = defineTool({
|
|
2882
2908
|
description: "Write generated patch file and apply it using package-manager-native patch flow when available, falling back to patch-package when needed.",
|
|
2883
2909
|
parameters: z8.object({
|
|
2884
2910
|
packageName: z8.string().min(1).describe("The npm package name"),
|
|
@@ -3224,7 +3250,7 @@ function resolvePatchProvider(provider) {
|
|
|
3224
3250
|
function shouldAttemptPatchFallback(result, preferVersionBump) {
|
|
3225
3251
|
if (preferVersionBump) return false;
|
|
3226
3252
|
if (result.applied || result.dryRun) return false;
|
|
3227
|
-
return result.unresolvedReason === "no-safe-version" || result.unresolvedReason === "install-failed" || result.unresolvedReason === "override-apply-failed" || result.unresolvedReason === "validation-failed" || result.unresolvedReason === "major-bump-required" || result.unresolvedReason === "
|
|
3253
|
+
return result.unresolvedReason === "no-safe-version" || result.unresolvedReason === "install-failed" || result.unresolvedReason === "override-apply-failed" || result.unresolvedReason === "validation-failed" || result.unresolvedReason === "major-bump-required" || result.unresolvedReason === "transitive-dependency";
|
|
3228
3254
|
}
|
|
3229
3255
|
async function tryLocalPatchFallback(params) {
|
|
3230
3256
|
const usage = [];
|
|
@@ -3844,7 +3870,6 @@ function createProgressEmitter(options) {
|
|
|
3844
3870
|
}
|
|
3845
3871
|
|
|
3846
3872
|
// src/remediation/tools/lookup-cve.ts
|
|
3847
|
-
import { tool as tool9 } from "ai";
|
|
3848
3873
|
import { z as z9 } from "zod";
|
|
3849
3874
|
|
|
3850
3875
|
// src/intelligence/sources/cisa-kev.ts
|
|
@@ -4123,7 +4148,7 @@ async function enrichWithExternalFeeds(details) {
|
|
|
4123
4148
|
}
|
|
4124
4149
|
|
|
4125
4150
|
// src/remediation/tools/lookup-cve.ts
|
|
4126
|
-
var lookupCveTool =
|
|
4151
|
+
var lookupCveTool = defineTool({
|
|
4127
4152
|
description: "Look up a CVE ID and return the list of affected npm packages, their vulnerable version ranges, and the first patched version. Always call this first.",
|
|
4128
4153
|
parameters: z9.object({
|
|
4129
4154
|
cveId: z9.string().regex(/^CVE-\d{4}-\d+$/i, "Must be a valid CVE ID like CVE-2021-23337")
|
|
@@ -4192,7 +4217,6 @@ var lookupCveTool = tool9({
|
|
|
4192
4217
|
});
|
|
4193
4218
|
|
|
4194
4219
|
// src/remediation/tools/check-version-match.ts
|
|
4195
|
-
import { tool as tool10 } from "ai";
|
|
4196
4220
|
import { z as z10 } from "zod";
|
|
4197
4221
|
import semver6 from "semver";
|
|
4198
4222
|
var affectedPackageSchema = z10.object({
|
|
@@ -4205,9 +4229,9 @@ var affectedPackageSchema = z10.object({
|
|
|
4205
4229
|
var inventoryPackageSchema = z10.object({
|
|
4206
4230
|
name: z10.string(),
|
|
4207
4231
|
version: z10.string(),
|
|
4208
|
-
type: z10.enum(["direct", "
|
|
4232
|
+
type: z10.enum(["direct", "transitive"])
|
|
4209
4233
|
});
|
|
4210
|
-
var checkVersionMatchTool =
|
|
4234
|
+
var checkVersionMatchTool = defineTool({
|
|
4211
4235
|
description: "Check which of the project's installed packages fall within the CVE's vulnerable version ranges. Returns only the packages that are actually vulnerable.",
|
|
4212
4236
|
parameters: z10.object({
|
|
4213
4237
|
installedPackages: z10.array(inventoryPackageSchema).describe("Output from the check-inventory tool"),
|
|
@@ -4242,9 +4266,8 @@ var checkVersionMatchTool = tool10({
|
|
|
4242
4266
|
});
|
|
4243
4267
|
|
|
4244
4268
|
// src/remediation/tools/find-fixed-version.ts
|
|
4245
|
-
import { tool as tool11 } from "ai";
|
|
4246
4269
|
import { z as z11 } from "zod";
|
|
4247
|
-
var findFixedVersionTool =
|
|
4270
|
+
var findFixedVersionTool = defineTool({
|
|
4248
4271
|
description: "Query the npm registry to find the safest published upgrade version for a package that is >= the first patched version. Prefer patch upgrades first, then minor, and only fall back to major when no same-major fix exists.",
|
|
4249
4272
|
parameters: z11.object({
|
|
4250
4273
|
packageName: z11.string().describe("The npm package name"),
|
|
@@ -4290,7 +4313,6 @@ var findFixedVersionTool = tool11({
|
|
|
4290
4313
|
});
|
|
4291
4314
|
|
|
4292
4315
|
// src/remediation/tools/check-suppression.ts
|
|
4293
|
-
import { tool as tool12 } from "ai";
|
|
4294
4316
|
import { z as z12 } from "zod";
|
|
4295
4317
|
var suppressionSchema = z12.object({
|
|
4296
4318
|
cveId: z12.string(),
|
|
@@ -4298,7 +4320,7 @@ var suppressionSchema = z12.object({
|
|
|
4298
4320
|
notes: z12.string().optional(),
|
|
4299
4321
|
expiresAt: z12.string().optional()
|
|
4300
4322
|
});
|
|
4301
|
-
var checkSuppressionTool =
|
|
4323
|
+
var checkSuppressionTool = defineTool({
|
|
4302
4324
|
description: "Check whether a CVE is suppressed by an active VEX suppression entry in the policy. Returns suppressed=true and the justification if an active match is found. Call this after check-version-match.",
|
|
4303
4325
|
parameters: z12.object({
|
|
4304
4326
|
cveId: z12.string().describe("The CVE ID to look up in suppressions"),
|
|
@@ -4413,7 +4435,7 @@ async function createPipelineRuntime(cveId, options) {
|
|
|
4413
4435
|
const constraints = options.constraints ?? {};
|
|
4414
4436
|
const prompt = `Patch vulnerable dependencies affected by ${cveId} in the project at: ${cwd}. Package manager: ${packageManager}.`;
|
|
4415
4437
|
const model = await createModel(options, { inputChars: prompt.length });
|
|
4416
|
-
const modelName = model.modelId
|
|
4438
|
+
const modelName = typeof model === "string" ? model : "modelId" in model && typeof model.modelId === "string" ? model.modelId : "unknown-model";
|
|
4417
4439
|
const systemPrompt = loadOrchestrationPrompt({
|
|
4418
4440
|
cveId,
|
|
4419
4441
|
cwd,
|
|
@@ -4465,7 +4487,7 @@ async function runRemediationPipeline(cveId, options = {}) {
|
|
|
4465
4487
|
system: systemPrompt,
|
|
4466
4488
|
prompt,
|
|
4467
4489
|
tools,
|
|
4468
|
-
|
|
4490
|
+
stopWhen: ({ steps }) => steps.length >= 25,
|
|
4469
4491
|
onStepFinish(stepResult) {
|
|
4470
4492
|
agentSteps += 1;
|
|
4471
4493
|
const toolResults = stepResult.toolResults ?? [];
|
|
@@ -4520,6 +4542,188 @@ async function runRemediationPipeline(cveId, options = {}) {
|
|
|
4520
4542
|
};
|
|
4521
4543
|
}
|
|
4522
4544
|
|
|
4545
|
+
// src/api/change-request/index.ts
|
|
4546
|
+
import { execa as execa11 } from "execa";
|
|
4547
|
+
function sanitizeBranchToken(value) {
|
|
4548
|
+
return value.toLowerCase().replace(/[^a-z0-9._/-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
4549
|
+
}
|
|
4550
|
+
function buildPlan(reports) {
|
|
4551
|
+
const cveIds = Array.from(new Set(reports.map((report) => report.cveId)));
|
|
4552
|
+
const packageNames = Array.from(
|
|
4553
|
+
new Set(
|
|
4554
|
+
reports.flatMap((report) => report.results.map((result) => result.packageName))
|
|
4555
|
+
)
|
|
4556
|
+
);
|
|
4557
|
+
const titleSuffix = cveIds.length === 1 ? cveIds[0] : `${cveIds.length} CVEs`;
|
|
4558
|
+
const title = `security remediation: ${titleSuffix}`;
|
|
4559
|
+
const body = [
|
|
4560
|
+
"Automated remediation generated by autoremediator.",
|
|
4561
|
+
"",
|
|
4562
|
+
`CVEs: ${cveIds.join(", ")}`,
|
|
4563
|
+
`Packages: ${packageNames.join(", ")}`
|
|
4564
|
+
].join("\n");
|
|
4565
|
+
return {
|
|
4566
|
+
cveIds,
|
|
4567
|
+
packageNames,
|
|
4568
|
+
title,
|
|
4569
|
+
body
|
|
4570
|
+
};
|
|
4571
|
+
}
|
|
4572
|
+
function resolveProvider2(options) {
|
|
4573
|
+
return options.provider ?? "github";
|
|
4574
|
+
}
|
|
4575
|
+
function resolveGrouping(options) {
|
|
4576
|
+
if (options.grouping && options.grouping !== "all") {
|
|
4577
|
+
throw new Error(
|
|
4578
|
+
"changeRequest.grouping currently supports only 'all' for deterministic branch creation."
|
|
4579
|
+
);
|
|
4580
|
+
}
|
|
4581
|
+
return "all";
|
|
4582
|
+
}
|
|
4583
|
+
async function detectCurrentBranch(cwd) {
|
|
4584
|
+
const result = await execa11("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
4585
|
+
cwd,
|
|
4586
|
+
stdio: "pipe"
|
|
4587
|
+
});
|
|
4588
|
+
return result.stdout.trim();
|
|
4589
|
+
}
|
|
4590
|
+
async function ensureRepoHasChanges(cwd) {
|
|
4591
|
+
const diff = await execa11("git", ["status", "--porcelain"], {
|
|
4592
|
+
cwd,
|
|
4593
|
+
stdio: "pipe"
|
|
4594
|
+
});
|
|
4595
|
+
return diff.stdout.trim().length > 0;
|
|
4596
|
+
}
|
|
4597
|
+
function toBranchName(prefix, cveIds) {
|
|
4598
|
+
const token = sanitizeBranchToken(cveIds.join("-") || "remediation");
|
|
4599
|
+
return `${sanitizeBranchToken(prefix)}/${token}-${Date.now()}`;
|
|
4600
|
+
}
|
|
4601
|
+
async function createGitHubRequest(params) {
|
|
4602
|
+
const args = ["pr", "create", "--head", params.head, "--base", params.base, "--title", params.title, "--body", params.body];
|
|
4603
|
+
if (params.repository) {
|
|
4604
|
+
args.push("--repo", params.repository);
|
|
4605
|
+
}
|
|
4606
|
+
if (params.draft) {
|
|
4607
|
+
args.push("--draft");
|
|
4608
|
+
}
|
|
4609
|
+
const result = await execa11("gh", args, {
|
|
4610
|
+
cwd: params.cwd,
|
|
4611
|
+
stdio: "pipe"
|
|
4612
|
+
});
|
|
4613
|
+
return result.stdout.trim() || void 0;
|
|
4614
|
+
}
|
|
4615
|
+
async function createGitLabRequest(params) {
|
|
4616
|
+
const args = [
|
|
4617
|
+
"mr",
|
|
4618
|
+
"create",
|
|
4619
|
+
"--source-branch",
|
|
4620
|
+
params.source,
|
|
4621
|
+
"--target-branch",
|
|
4622
|
+
params.target,
|
|
4623
|
+
"--title",
|
|
4624
|
+
params.title,
|
|
4625
|
+
"--description",
|
|
4626
|
+
params.body
|
|
4627
|
+
];
|
|
4628
|
+
if (params.repository) {
|
|
4629
|
+
args.push("-R", params.repository);
|
|
4630
|
+
}
|
|
4631
|
+
if (params.draft) {
|
|
4632
|
+
args.push("--draft");
|
|
4633
|
+
}
|
|
4634
|
+
const result = await execa11("glab", args, {
|
|
4635
|
+
cwd: params.cwd,
|
|
4636
|
+
stdio: "pipe"
|
|
4637
|
+
});
|
|
4638
|
+
return result.stdout.trim() || void 0;
|
|
4639
|
+
}
|
|
4640
|
+
async function createChangeRequestsForReports(params) {
|
|
4641
|
+
const { cwd, options, reports } = params;
|
|
4642
|
+
const provider = resolveProvider2(options);
|
|
4643
|
+
const grouping = resolveGrouping(options);
|
|
4644
|
+
const plan = buildPlan(reports);
|
|
4645
|
+
const titlePrefix = options.titlePrefix?.trim();
|
|
4646
|
+
const title = titlePrefix ? `${titlePrefix} ${plan.title}` : plan.title;
|
|
4647
|
+
const body = options.bodyFooter ? `${plan.body}
|
|
4648
|
+
|
|
4649
|
+
${options.bodyFooter}` : plan.body;
|
|
4650
|
+
try {
|
|
4651
|
+
const hasChanges = await ensureRepoHasChanges(cwd);
|
|
4652
|
+
if (!hasChanges) {
|
|
4653
|
+
return [
|
|
4654
|
+
{
|
|
4655
|
+
provider,
|
|
4656
|
+
grouping,
|
|
4657
|
+
repository: options.repository,
|
|
4658
|
+
branchName: "",
|
|
4659
|
+
title,
|
|
4660
|
+
body,
|
|
4661
|
+
created: false,
|
|
4662
|
+
cveIds: plan.cveIds,
|
|
4663
|
+
packageNames: plan.packageNames,
|
|
4664
|
+
error: "No repository changes to include in change request."
|
|
4665
|
+
}
|
|
4666
|
+
];
|
|
4667
|
+
}
|
|
4668
|
+
const baseBranch = options.baseBranch ?? await detectCurrentBranch(cwd);
|
|
4669
|
+
const branchPrefix = options.branchPrefix ?? "autoremediator";
|
|
4670
|
+
const branchName = toBranchName(branchPrefix, plan.cveIds);
|
|
4671
|
+
const pushRemote = options.pushRemote ?? "origin";
|
|
4672
|
+
await execa11("git", ["checkout", "-b", branchName], { cwd, stdio: "pipe" });
|
|
4673
|
+
await execa11("git", ["add", "-A"], { cwd, stdio: "pipe" });
|
|
4674
|
+
await execa11("git", ["commit", "-m", title], { cwd, stdio: "pipe" });
|
|
4675
|
+
await execa11("git", ["push", "-u", pushRemote, branchName], { cwd, stdio: "pipe" });
|
|
4676
|
+
const url = provider === "github" ? await createGitHubRequest({
|
|
4677
|
+
cwd,
|
|
4678
|
+
repository: options.repository,
|
|
4679
|
+
head: branchName,
|
|
4680
|
+
base: baseBranch,
|
|
4681
|
+
title,
|
|
4682
|
+
body,
|
|
4683
|
+
draft: options.draft
|
|
4684
|
+
}) : await createGitLabRequest({
|
|
4685
|
+
cwd,
|
|
4686
|
+
repository: options.repository,
|
|
4687
|
+
source: branchName,
|
|
4688
|
+
target: baseBranch,
|
|
4689
|
+
title,
|
|
4690
|
+
body,
|
|
4691
|
+
draft: options.draft
|
|
4692
|
+
});
|
|
4693
|
+
return [
|
|
4694
|
+
{
|
|
4695
|
+
provider,
|
|
4696
|
+
grouping,
|
|
4697
|
+
repository: options.repository,
|
|
4698
|
+
branchName,
|
|
4699
|
+
title,
|
|
4700
|
+
body,
|
|
4701
|
+
created: true,
|
|
4702
|
+
draft: options.draft,
|
|
4703
|
+
url,
|
|
4704
|
+
cveIds: plan.cveIds,
|
|
4705
|
+
packageNames: plan.packageNames
|
|
4706
|
+
}
|
|
4707
|
+
];
|
|
4708
|
+
} catch (error) {
|
|
4709
|
+
return [
|
|
4710
|
+
{
|
|
4711
|
+
provider,
|
|
4712
|
+
grouping,
|
|
4713
|
+
repository: options.repository,
|
|
4714
|
+
branchName: "",
|
|
4715
|
+
title,
|
|
4716
|
+
body,
|
|
4717
|
+
created: false,
|
|
4718
|
+
draft: options.draft,
|
|
4719
|
+
cveIds: plan.cveIds,
|
|
4720
|
+
packageNames: plan.packageNames,
|
|
4721
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4722
|
+
}
|
|
4723
|
+
];
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4523
4727
|
// src/api/context.ts
|
|
4524
4728
|
function buildRequestId() {
|
|
4525
4729
|
return `req-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -4752,12 +4956,24 @@ async function remediate(cveId, options = {}) {
|
|
|
4752
4956
|
constraints,
|
|
4753
4957
|
resumedFromCache: false
|
|
4754
4958
|
};
|
|
4959
|
+
if (options.changeRequest?.enabled) {
|
|
4960
|
+
finalReport.changeRequests = await createChangeRequestsForReports({
|
|
4961
|
+
cwd,
|
|
4962
|
+
options: options.changeRequest,
|
|
4963
|
+
reports: [finalReport]
|
|
4964
|
+
});
|
|
4965
|
+
}
|
|
4755
4966
|
if (options.idempotencyKey && !options.dryRun && !options.preview) {
|
|
4756
4967
|
storeIdempotentReport(cwd, options.idempotencyKey, normalizedCveId, finalReport);
|
|
4757
4968
|
}
|
|
4758
4969
|
return finalReport;
|
|
4759
4970
|
}
|
|
4760
4971
|
async function planRemediation(cveId, options = {}) {
|
|
4972
|
+
if (Object.hasOwn(options, "dryRun") || Object.hasOwn(options, "preview")) {
|
|
4973
|
+
throw new Error(
|
|
4974
|
+
"planRemediation always runs with dryRun=true and preview=true. Remove dryRun/preview from options."
|
|
4975
|
+
);
|
|
4976
|
+
}
|
|
4761
4977
|
return remediate(cveId, {
|
|
4762
4978
|
...options,
|
|
4763
4979
|
preview: true,
|
|
@@ -4768,7 +4984,7 @@ async function planRemediation(cveId, options = {}) {
|
|
|
4768
4984
|
// src/scanner/parse-input.ts
|
|
4769
4985
|
import { extname as extname2 } from "path";
|
|
4770
4986
|
import { readFileSync as readFileSync13 } from "fs";
|
|
4771
|
-
import { execa as
|
|
4987
|
+
import { execa as execa12 } from "execa";
|
|
4772
4988
|
|
|
4773
4989
|
// src/scanner/adapters/npm-audit.ts
|
|
4774
4990
|
import { readFileSync as readFileSync10 } from "fs";
|
|
@@ -4917,7 +5133,7 @@ async function parseScanInputFromAudit(params) {
|
|
|
4917
5133
|
}
|
|
4918
5134
|
const command = resolveAuditCommand(pm, { workspace: params.workspace });
|
|
4919
5135
|
const [cmd, ...args] = command;
|
|
4920
|
-
const result = await
|
|
5136
|
+
const result = await execa12(cmd, args, {
|
|
4921
5137
|
cwd: params.cwd,
|
|
4922
5138
|
stdio: "pipe",
|
|
4923
5139
|
reject: false
|
|
@@ -5224,6 +5440,11 @@ async function remediateFromScan(inputPath, options = {}) {
|
|
|
5224
5440
|
};
|
|
5225
5441
|
finalizeEvidence(evidence);
|
|
5226
5442
|
const evidenceFile = options.evidence === false ? void 0 : writeEvidenceLog(cwd, evidence);
|
|
5443
|
+
const changeRequests = options.changeRequest?.enabled ? await createChangeRequestsForReports({
|
|
5444
|
+
cwd,
|
|
5445
|
+
options: options.changeRequest,
|
|
5446
|
+
reports
|
|
5447
|
+
}) : void 0;
|
|
5227
5448
|
return {
|
|
5228
5449
|
schemaVersion: "1.0",
|
|
5229
5450
|
status,
|
|
@@ -5246,14 +5467,119 @@ async function remediateFromScan(inputPath, options = {}) {
|
|
|
5246
5467
|
idempotencyKey: options.idempotencyKey,
|
|
5247
5468
|
llmUsageCount: llmUsageTotals.llmUsageCount > 0 ? llmUsageTotals.llmUsageCount : void 0,
|
|
5248
5469
|
estimatedCostUsd: llmUsageTotals.estimatedCostUsd,
|
|
5249
|
-
totalLlmLatencyMs: llmUsageTotals.totalLlmLatencyMs
|
|
5470
|
+
totalLlmLatencyMs: llmUsageTotals.totalLlmLatencyMs,
|
|
5471
|
+
changeRequests
|
|
5472
|
+
};
|
|
5473
|
+
}
|
|
5474
|
+
|
|
5475
|
+
// src/api/portfolio/index.ts
|
|
5476
|
+
function toTargetStatusFromRemediation(report) {
|
|
5477
|
+
const failed = report.results.some((result) => !result.applied && !result.dryRun);
|
|
5478
|
+
const succeeded = report.results.some((result) => result.applied || result.dryRun);
|
|
5479
|
+
if (!failed) return "ok";
|
|
5480
|
+
return succeeded ? "partial" : "failed";
|
|
5481
|
+
}
|
|
5482
|
+
function normalizeTargetInput(target) {
|
|
5483
|
+
return {
|
|
5484
|
+
cveId: target.cveId?.trim() || void 0,
|
|
5485
|
+
inputPath: target.inputPath?.trim() || void 0,
|
|
5486
|
+
audit: target.audit ?? false
|
|
5487
|
+
};
|
|
5488
|
+
}
|
|
5489
|
+
function validateTarget(target, index) {
|
|
5490
|
+
if (!target.cwd || typeof target.cwd !== "string") {
|
|
5491
|
+
throw new Error(`Invalid portfolio target at index ${index}: cwd is required.`);
|
|
5492
|
+
}
|
|
5493
|
+
const { cveId, inputPath, audit } = normalizeTargetInput(target);
|
|
5494
|
+
const hasScanInput = Boolean(inputPath) || audit;
|
|
5495
|
+
if (Boolean(cveId) === hasScanInput) {
|
|
5496
|
+
throw new Error(
|
|
5497
|
+
`Invalid portfolio target at index ${index}: provide exactly one mode (cveId OR inputPath/audit).`
|
|
5498
|
+
);
|
|
5499
|
+
}
|
|
5500
|
+
}
|
|
5501
|
+
async function remediatePortfolio(targets, options = {}) {
|
|
5502
|
+
const normalizedTargets = Array.isArray(targets) ? targets : [];
|
|
5503
|
+
if (normalizedTargets.length === 0) {
|
|
5504
|
+
throw new Error("Portfolio requires at least one target.");
|
|
5505
|
+
}
|
|
5506
|
+
normalizedTargets.forEach((target, index) => validateTarget(target, index));
|
|
5507
|
+
const results = [];
|
|
5508
|
+
const changeRequests = [];
|
|
5509
|
+
let successCount = 0;
|
|
5510
|
+
let failedCount = 0;
|
|
5511
|
+
for (const target of normalizedTargets) {
|
|
5512
|
+
const { cveId, inputPath, audit } = normalizeTargetInput(target);
|
|
5513
|
+
try {
|
|
5514
|
+
if (cveId) {
|
|
5515
|
+
const remediationReport = await remediate(cveId, {
|
|
5516
|
+
...options,
|
|
5517
|
+
cwd: target.cwd,
|
|
5518
|
+
source: options.source
|
|
5519
|
+
});
|
|
5520
|
+
const status = toTargetStatusFromRemediation(remediationReport);
|
|
5521
|
+
results.push({
|
|
5522
|
+
target,
|
|
5523
|
+
status,
|
|
5524
|
+
remediationReport,
|
|
5525
|
+
changeRequests: remediationReport.changeRequests
|
|
5526
|
+
});
|
|
5527
|
+
if (remediationReport.changeRequests?.length) {
|
|
5528
|
+
changeRequests.push(...remediationReport.changeRequests);
|
|
5529
|
+
}
|
|
5530
|
+
if (status === "failed") {
|
|
5531
|
+
failedCount += 1;
|
|
5532
|
+
} else {
|
|
5533
|
+
successCount += 1;
|
|
5534
|
+
}
|
|
5535
|
+
continue;
|
|
5536
|
+
}
|
|
5537
|
+
const scanReport = await remediateFromScan(inputPath ?? "", {
|
|
5538
|
+
...options,
|
|
5539
|
+
cwd: target.cwd,
|
|
5540
|
+
audit,
|
|
5541
|
+
format: target.format,
|
|
5542
|
+
source: options.source
|
|
5543
|
+
});
|
|
5544
|
+
results.push({
|
|
5545
|
+
target,
|
|
5546
|
+
status: scanReport.status,
|
|
5547
|
+
scanReport,
|
|
5548
|
+
changeRequests: scanReport.changeRequests
|
|
5549
|
+
});
|
|
5550
|
+
if (scanReport.changeRequests?.length) {
|
|
5551
|
+
changeRequests.push(...scanReport.changeRequests);
|
|
5552
|
+
}
|
|
5553
|
+
if (scanReport.status === "failed") {
|
|
5554
|
+
failedCount += 1;
|
|
5555
|
+
} else {
|
|
5556
|
+
successCount += 1;
|
|
5557
|
+
}
|
|
5558
|
+
} catch (error) {
|
|
5559
|
+
results.push({
|
|
5560
|
+
target,
|
|
5561
|
+
status: "failed",
|
|
5562
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5563
|
+
});
|
|
5564
|
+
failedCount += 1;
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5567
|
+
const overallStatus = failedCount === 0 ? "ok" : successCount > 0 ? "partial" : "failed";
|
|
5568
|
+
return {
|
|
5569
|
+
schemaVersion: "1.0",
|
|
5570
|
+
status: overallStatus,
|
|
5571
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5572
|
+
targets: results,
|
|
5573
|
+
successCount,
|
|
5574
|
+
failedCount,
|
|
5575
|
+
changeRequests: changeRequests.length > 0 ? changeRequests : void 0
|
|
5250
5576
|
};
|
|
5251
5577
|
}
|
|
5252
5578
|
|
|
5253
5579
|
// src/api/update-outdated/index.ts
|
|
5254
5580
|
import { join as join17 } from "path";
|
|
5255
5581
|
import { readFileSync as readFileSync14, writeFileSync as writeFileSync6 } from "fs";
|
|
5256
|
-
import { execa as
|
|
5582
|
+
import { execa as execa13 } from "execa";
|
|
5257
5583
|
async function applyBump(params) {
|
|
5258
5584
|
const pkgPath = join17(params.cwd, "package.json");
|
|
5259
5585
|
let pkgJson;
|
|
@@ -5283,7 +5609,7 @@ async function applyBump(params) {
|
|
|
5283
5609
|
writeFileSync6(pkgPath, JSON.stringify(pkgJson, null, 2) + "\n", "utf8");
|
|
5284
5610
|
try {
|
|
5285
5611
|
const [installCmd, ...installArgs] = params.installCommand;
|
|
5286
|
-
await
|
|
5612
|
+
await execa13(installCmd, installArgs, { cwd: params.cwd, stdio: "pipe" });
|
|
5287
5613
|
} catch (err) {
|
|
5288
5614
|
pkgJson[depField][params.packageName] = currentRange;
|
|
5289
5615
|
writeFileSync6(pkgPath, JSON.stringify(pkgJson, null, 2) + "\n", "utf8");
|
|
@@ -5296,13 +5622,13 @@ async function applyBump(params) {
|
|
|
5296
5622
|
if (params.runTests) {
|
|
5297
5623
|
try {
|
|
5298
5624
|
const [testCmd, ...testArgs] = params.testCommand;
|
|
5299
|
-
await
|
|
5625
|
+
await execa13(testCmd, testArgs, { cwd: params.cwd, stdio: "pipe" });
|
|
5300
5626
|
} catch (err) {
|
|
5301
5627
|
pkgJson[depField][params.packageName] = currentRange;
|
|
5302
5628
|
writeFileSync6(pkgPath, JSON.stringify(pkgJson, null, 2) + "\n", "utf8");
|
|
5303
5629
|
try {
|
|
5304
5630
|
const [rollbackCmd, ...rollbackArgs] = params.installCommand;
|
|
5305
|
-
await
|
|
5631
|
+
await execa13(rollbackCmd, rollbackArgs, { cwd: params.cwd, stdio: "pipe" });
|
|
5306
5632
|
} catch {
|
|
5307
5633
|
}
|
|
5308
5634
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -5455,6 +5781,28 @@ async function updateOutdated(options = {}) {
|
|
|
5455
5781
|
};
|
|
5456
5782
|
finalizeEvidence(evidence);
|
|
5457
5783
|
const evidenceFile = options.evidence === false ? void 0 : writeEvidenceLog(cwd, evidence);
|
|
5784
|
+
const changeRequests = options.changeRequest?.enabled && successCount > 0 ? await createChangeRequestsForReports({
|
|
5785
|
+
cwd,
|
|
5786
|
+
options: options.changeRequest,
|
|
5787
|
+
reports: [
|
|
5788
|
+
{
|
|
5789
|
+
cveId: "UPDATE-OUTDATED",
|
|
5790
|
+
cveDetails: null,
|
|
5791
|
+
vulnerablePackages: [],
|
|
5792
|
+
results: outdatedPackages.filter((pkg) => !pkg.isMajorBump).map((pkg) => ({
|
|
5793
|
+
packageName: pkg.name,
|
|
5794
|
+
strategy: "version-bump",
|
|
5795
|
+
fromVersion: pkg.currentVersion,
|
|
5796
|
+
toVersion: pkg.latestVersion,
|
|
5797
|
+
applied: true,
|
|
5798
|
+
dryRun: Boolean(options.dryRun),
|
|
5799
|
+
message: `Updated ${pkg.name} to ${pkg.latestVersion}`
|
|
5800
|
+
})),
|
|
5801
|
+
agentSteps: 0,
|
|
5802
|
+
summary: "update-outdated"
|
|
5803
|
+
}
|
|
5804
|
+
]
|
|
5805
|
+
}) : void 0;
|
|
5458
5806
|
return {
|
|
5459
5807
|
schemaVersion: "1.0",
|
|
5460
5808
|
status,
|
|
@@ -5468,7 +5816,8 @@ async function updateOutdated(options = {}) {
|
|
|
5468
5816
|
patchCount: 0,
|
|
5469
5817
|
constraints,
|
|
5470
5818
|
correlation,
|
|
5471
|
-
provenance
|
|
5819
|
+
provenance,
|
|
5820
|
+
changeRequests
|
|
5472
5821
|
};
|
|
5473
5822
|
}
|
|
5474
5823
|
|
|
@@ -5562,7 +5911,8 @@ export {
|
|
|
5562
5911
|
remediate,
|
|
5563
5912
|
planRemediation,
|
|
5564
5913
|
remediateFromScan,
|
|
5914
|
+
remediatePortfolio,
|
|
5565
5915
|
updateOutdated,
|
|
5566
5916
|
PACKAGE_VERSION
|
|
5567
5917
|
};
|
|
5568
|
-
//# sourceMappingURL=chunk-
|
|
5918
|
+
//# sourceMappingURL=chunk-575GEUAY.js.map
|