@openrewrite/recipes-nodejs 0.37.0-20260106-083133 → 0.37.0-20260106-104324

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.
Files changed (36) hide show
  1. package/dist/security/dependency-vulnerability-check.d.ts +6 -54
  2. package/dist/security/dependency-vulnerability-check.d.ts.map +1 -1
  3. package/dist/security/dependency-vulnerability-check.js +133 -259
  4. package/dist/security/dependency-vulnerability-check.js.map +1 -1
  5. package/dist/security/index.d.ts +3 -0
  6. package/dist/security/index.d.ts.map +1 -1
  7. package/dist/security/index.js +3 -0
  8. package/dist/security/index.js.map +1 -1
  9. package/dist/security/npm-utils.d.ts +8 -2
  10. package/dist/security/npm-utils.d.ts.map +1 -1
  11. package/dist/security/npm-utils.js +114 -14
  12. package/dist/security/npm-utils.js.map +1 -1
  13. package/dist/security/override-utils.d.ts +23 -0
  14. package/dist/security/override-utils.d.ts.map +1 -0
  15. package/dist/security/override-utils.js +169 -0
  16. package/dist/security/override-utils.js.map +1 -0
  17. package/dist/security/remove-redundant-overrides.d.ts +1 -10
  18. package/dist/security/remove-redundant-overrides.d.ts.map +1 -1
  19. package/dist/security/remove-redundant-overrides.js +4 -152
  20. package/dist/security/remove-redundant-overrides.js.map +1 -1
  21. package/dist/security/types.d.ts +42 -0
  22. package/dist/security/types.d.ts.map +1 -0
  23. package/dist/security/types.js +7 -0
  24. package/dist/security/types.js.map +1 -0
  25. package/dist/security/version-utils.d.ts +13 -0
  26. package/dist/security/version-utils.d.ts.map +1 -0
  27. package/dist/security/version-utils.js +173 -0
  28. package/dist/security/version-utils.js.map +1 -0
  29. package/package.json +1 -1
  30. package/src/security/dependency-vulnerability-check.ts +232 -485
  31. package/src/security/index.ts +3 -0
  32. package/src/security/npm-utils.ts +172 -37
  33. package/src/security/override-utils.ts +253 -0
  34. package/src/security/remove-redundant-overrides.ts +9 -211
  35. package/src/security/types.ts +116 -0
  36. package/src/security/version-utils.ts +198 -0
@@ -49,8 +49,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
49
49
  };
50
50
  Object.defineProperty(exports, "__esModule", { value: true });
51
51
  exports.DependencyVulnerabilityCheck = void 0;
52
- exports.extractVersionPrefix = extractVersionPrefix;
53
- exports.applyVersionPrefix = applyVersionPrefix;
54
52
  const rewrite_1 = require("@openrewrite/rewrite");
55
53
  const json_1 = require("@openrewrite/rewrite/json");
56
54
  const text_1 = require("@openrewrite/rewrite/text");
@@ -60,9 +58,9 @@ const semver = __importStar(require("semver"));
60
58
  const path = __importStar(require("path"));
61
59
  const vulnerability_1 = require("./vulnerability");
62
60
  const npm_utils_1 = require("./npm-utils");
63
- const ALL_DEPENDENCY_SCOPES = [
64
- 'dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'
65
- ];
61
+ const version_utils_1 = require("./version-utils");
62
+ const types_1 = require("./types");
63
+ const override_utils_1 = require("./override-utils");
66
64
  class VulnerabilityReportRow {
67
65
  constructor(sourcePath, cve, packageName, version, fixedVersion, lastAffectedVersion, upgradeable, summary, severity, depth, cwes, isDirect, dependencyPath) {
68
66
  this.sourcePath = sourcePath;
@@ -189,9 +187,6 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
189
187
  shouldScanTransitives() {
190
188
  return this.transitiveFixStrategy !== 'report';
191
189
  }
192
- shouldFixTransitives() {
193
- return this.transitiveFixStrategy !== 'report';
194
- }
195
190
  shouldVerifyTransitiveFixes() {
196
191
  return this.transitiveFixStrategy === 'override' ||
197
192
  this.transitiveFixStrategy === 'prefer-direct-upgrade';
@@ -199,7 +194,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
199
194
  filterRemainingTransitiveFixes(fixes, lockFileContent, packageManager, db) {
200
195
  const result = [];
201
196
  for (const fix of fixes) {
202
- if (!fix.isTransitive || fix.fixViaDirectUpgrade) {
197
+ if (!fix.isTransitive || (fix.fixViaDirectUpgrades && fix.fixViaDirectUpgrades.length > 0)) {
203
198
  result.push(fix);
204
199
  continue;
205
200
  }
@@ -217,7 +212,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
217
212
  isVersionStillVulnerable(packageName, version, cves, db) {
218
213
  const vulns = db.getVulnerabilities(packageName);
219
214
  for (const vuln of vulns) {
220
- if (cves.includes(vuln.cve) && this.isVersionAffected(version, vuln)) {
215
+ if (cves.includes(vuln.cve) && (0, version_utils_1.isVersionAffected)(version, vuln)) {
221
216
  return true;
222
217
  }
223
218
  }
@@ -235,100 +230,6 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
235
230
  }
236
231
  return this.cvePatternRegex.test(vulnerability.cve);
237
232
  }
238
- isVersionAffected(version, vulnerability) {
239
- try {
240
- const v = semver.parse(version);
241
- if (!v)
242
- return false;
243
- if (vulnerability.introducedVersion && vulnerability.introducedVersion !== '0') {
244
- const introduced = semver.parse(vulnerability.introducedVersion);
245
- if (introduced && semver.lt(v, introduced)) {
246
- return false;
247
- }
248
- }
249
- if (vulnerability.fixedVersion) {
250
- const fixed = semver.parse(vulnerability.fixedVersion);
251
- if (fixed && semver.gte(v, fixed)) {
252
- return false;
253
- }
254
- return true;
255
- }
256
- if (vulnerability.lastAffectedVersion) {
257
- const lastAffected = semver.parse(vulnerability.lastAffectedVersion);
258
- if (lastAffected && semver.gt(v, lastAffected)) {
259
- return false;
260
- }
261
- return true;
262
- }
263
- return true;
264
- }
265
- catch (_a) {
266
- return false;
267
- }
268
- }
269
- isUpgradeableWithinDelta(currentVersion, vulnerability) {
270
- if (this.isReportOnly()) {
271
- return false;
272
- }
273
- try {
274
- const current = semver.parse(currentVersion);
275
- if (!current)
276
- return false;
277
- const delta = this.maximumUpgradeDelta;
278
- if (vulnerability.fixedVersion) {
279
- const fixed = semver.parse(vulnerability.fixedVersion);
280
- if (!fixed)
281
- return false;
282
- switch (delta) {
283
- case 'patch':
284
- return current.major === fixed.major && current.minor === fixed.minor;
285
- case 'minor':
286
- return current.major === fixed.major;
287
- case 'major':
288
- return true;
289
- case 'none':
290
- return false;
291
- }
292
- }
293
- if (vulnerability.lastAffectedVersion) {
294
- const lastAffected = semver.parse(vulnerability.lastAffectedVersion);
295
- if (!lastAffected)
296
- return false;
297
- switch (delta) {
298
- case 'patch':
299
- return current.major === lastAffected.major &&
300
- current.minor === lastAffected.minor;
301
- case 'minor':
302
- return current.major === lastAffected.major;
303
- case 'major':
304
- return true;
305
- case 'none':
306
- return false;
307
- }
308
- }
309
- return false;
310
- }
311
- catch (_a) {
312
- return false;
313
- }
314
- }
315
- getUpgradeVersion(vulnerability) {
316
- if (vulnerability.fixedVersion) {
317
- return vulnerability.fixedVersion;
318
- }
319
- return undefined;
320
- }
321
- getVersionPrefixForDelta() {
322
- switch (this.maximumUpgradeDelta) {
323
- case 'patch':
324
- return '~';
325
- case 'minor':
326
- case 'major':
327
- return '^';
328
- default:
329
- return '';
330
- }
331
- }
332
233
  renderPath(scope, path) {
333
234
  const parts = [];
334
235
  if (scope) {
@@ -339,6 +240,39 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
339
240
  }
340
241
  return parts.join(' > ');
341
242
  }
243
+ findAllDirectDepsForTransitive(marker, transitivePackageName, scopesToCheck) {
244
+ const results = [];
245
+ for (const scope of scopesToCheck) {
246
+ const deps = marker[scope] || [];
247
+ for (const dep of deps) {
248
+ if (dep.resolved && this.hasTransitiveInTree(dep.resolved, transitivePackageName, new Set())) {
249
+ results.push({
250
+ name: dep.resolved.name,
251
+ version: dep.resolved.version,
252
+ scope
253
+ });
254
+ }
255
+ }
256
+ }
257
+ return results;
258
+ }
259
+ hasTransitiveInTree(resolved, targetPackageName, visited) {
260
+ const key = `${resolved.name}@${resolved.version}`;
261
+ if (visited.has(key))
262
+ return false;
263
+ visited.add(key);
264
+ if (resolved.dependencies) {
265
+ for (const child of resolved.dependencies) {
266
+ if (child.name === targetPackageName) {
267
+ return true;
268
+ }
269
+ if (child.resolved && this.hasTransitiveInTree(child.resolved, targetPackageName, visited)) {
270
+ return true;
271
+ }
272
+ }
273
+ }
274
+ return false;
275
+ }
342
276
  findVulnerabilities(resolved, db, depth, isDirect, scope, path, visited, results) {
343
277
  const key = `${resolved.name}@${resolved.version}`;
344
278
  if (visited.has(key))
@@ -353,7 +287,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
353
287
  if (!this.matchesCvePattern(vuln)) {
354
288
  continue;
355
289
  }
356
- if (this.isVersionAffected(resolved.version, vuln)) {
290
+ if ((0, version_utils_1.isVersionAffected)(resolved.version, vuln)) {
357
291
  results.push({
358
292
  resolved,
359
293
  vulnerability: vuln,
@@ -385,7 +319,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
385
319
  for (const dep of deps) {
386
320
  if (!dep.resolved)
387
321
  continue;
388
- const declaredMinVersion = this.extractMinimumVersion(dep.versionConstraint);
322
+ const declaredMinVersion = (0, version_utils_1.extractMinimumVersion)(dep.versionConstraint);
389
323
  if (!declaredMinVersion)
390
324
  continue;
391
325
  if (declaredMinVersion === dep.resolved.version)
@@ -401,8 +335,8 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
401
335
  if (!this.matchesCvePattern(vuln)) {
402
336
  continue;
403
337
  }
404
- if (this.isVersionAffected(declaredMinVersion, vuln) &&
405
- !this.isVersionAffected(dep.resolved.version, vuln)) {
338
+ if ((0, version_utils_1.isVersionAffected)(declaredMinVersion, vuln) &&
339
+ !(0, version_utils_1.isVersionAffected)(dep.resolved.version, vuln)) {
406
340
  affectedCves.push(vuln.cve);
407
341
  affectedCveSummaries.set(vuln.cve, vuln.summary);
408
342
  const fixVersion = vuln.fixedVersion;
@@ -433,20 +367,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
433
367
  if (this.isReportOnly()) {
434
368
  return false;
435
369
  }
436
- return this.isVersionWithinDelta(fromVersion, toVersion);
437
- }
438
- extractMinimumVersion(constraint) {
439
- if (!constraint)
440
- return undefined;
441
- if (semver.valid(constraint)) {
442
- return constraint;
443
- }
444
- const match = constraint.match(/^[~^>=<]*\s*(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/);
445
- if (match && semver.valid(match[1])) {
446
- return match[1];
447
- }
448
- const coerced = semver.coerce(constraint);
449
- return coerced === null || coerced === void 0 ? void 0 : coerced.version;
370
+ return (0, version_utils_1.isVersionWithinDelta)(fromVersion, toVersion, this.maximumUpgradeDelta);
450
371
  }
451
372
  findHighestSafeVersion(packageName, originalVersion, initialFixVersion, db, visited = new Set()) {
452
373
  if (visited.has(initialFixVersion)) {
@@ -454,15 +375,15 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
454
375
  }
455
376
  visited.add(initialFixVersion);
456
377
  const vulnsInFixVersion = db.getVulnerabilities(packageName)
457
- .filter(v => this.isVersionAffected(initialFixVersion, v));
378
+ .filter(v => (0, version_utils_1.isVersionAffected)(initialFixVersion, v));
458
379
  if (vulnsInFixVersion.length === 0) {
459
380
  return initialFixVersion;
460
381
  }
461
382
  let highestFixVersion = initialFixVersion;
462
383
  for (const vuln of vulnsInFixVersion) {
463
- const fixVersion = this.getUpgradeVersion(vuln);
384
+ const fixVersion = (0, version_utils_1.getUpgradeVersion)(vuln);
464
385
  if (fixVersion && semver.valid(fixVersion)) {
465
- if (this.isVersionWithinDelta(originalVersion, fixVersion)) {
386
+ if ((0, version_utils_1.isVersionWithinDelta)(originalVersion, fixVersion, this.maximumUpgradeDelta)) {
466
387
  if (semver.gt(fixVersion, highestFixVersion)) {
467
388
  highestFixVersion = fixVersion;
468
389
  }
@@ -474,29 +395,6 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
474
395
  }
475
396
  return initialFixVersion;
476
397
  }
477
- isVersionWithinDelta(originalVersion, targetVersion) {
478
- try {
479
- const original = semver.parse(originalVersion);
480
- const target = semver.parse(targetVersion);
481
- if (!original || !target)
482
- return false;
483
- switch (this.maximumUpgradeDelta) {
484
- case 'patch':
485
- return original.major === target.major && original.minor === target.minor;
486
- case 'minor':
487
- return original.major === target.major;
488
- case 'major':
489
- return true;
490
- case 'none':
491
- return false;
492
- default:
493
- return false;
494
- }
495
- }
496
- catch (_a) {
497
- return false;
498
- }
499
- }
500
398
  computeFixes(vulnerabilities, db, projectContext) {
501
399
  return __awaiter(this, void 0, void 0, function* () {
502
400
  var _a, _b, _c, _d, _e, _f, _g;
@@ -531,23 +429,27 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
531
429
  let isTransitive = true;
532
430
  let scope;
533
431
  let originalVersion;
534
- let directDepInfo;
432
+ const directDepInfosMap = new Map();
535
433
  for (const vuln of vulns) {
536
434
  if (!originalVersion) {
537
435
  originalVersion = vuln.resolved.version;
538
436
  }
539
- if (!vuln.isDirect && vuln.path.length > 0 && !directDepInfo) {
437
+ if (!vuln.isDirect && vuln.path.length > 0) {
540
438
  const directDep = vuln.path[0];
541
- directDepInfo = {
542
- name: directDep.name,
543
- version: directDep.version,
544
- scope: vuln.scope || 'dependencies'
545
- };
439
+ const depScope = vuln.scope || 'dependencies';
440
+ const key = `${directDep.name}@${depScope}`;
441
+ if (!directDepInfosMap.has(key)) {
442
+ directDepInfosMap.set(key, {
443
+ name: directDep.name,
444
+ version: directDep.version,
445
+ scope: depScope
446
+ });
447
+ }
546
448
  }
547
- if (!this.isUpgradeableWithinDelta(vuln.resolved.version, vuln.vulnerability)) {
449
+ if (this.isReportOnly() || !(0, version_utils_1.isUpgradeableWithinDelta)(vuln.resolved.version, vuln.vulnerability, this.maximumUpgradeDelta)) {
548
450
  continue;
549
451
  }
550
- const fixVersion = this.getUpgradeVersion(vuln.vulnerability);
452
+ const fixVersion = (0, version_utils_1.getUpgradeVersion)(vuln.vulnerability);
551
453
  if (fixVersion) {
552
454
  const fixMajor = (_g = semver.parse(fixVersion)) === null || _g === void 0 ? void 0 : _g.major;
553
455
  const shouldConsiderFix = hasMultipleMajorVersions
@@ -566,8 +468,18 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
566
468
  scope = vuln.scope;
567
469
  }
568
470
  }
471
+ if (isTransitive && (projectContext === null || projectContext === void 0 ? void 0 : projectContext.marker) && (projectContext === null || projectContext === void 0 ? void 0 : projectContext.scopesToCheck)) {
472
+ const allDirectDeps = this.findAllDirectDepsForTransitive(projectContext.marker, packageName, projectContext.scopesToCheck);
473
+ for (const dep of allDirectDeps) {
474
+ const key = `${dep.name}@${dep.scope}`;
475
+ if (!directDepInfosMap.has(key)) {
476
+ directDepInfosMap.set(key, dep);
477
+ }
478
+ }
479
+ }
569
480
  if (highestFixVersion && cves.length > 0 && originalVersion) {
570
481
  const safeVersion = this.findHighestSafeVersion(packageName, originalVersion, highestFixVersion, db);
482
+ const directDepInfosArray = Array.from(directDepInfosMap.values());
571
483
  const fix = {
572
484
  packageName,
573
485
  newVersion: safeVersion || highestFixVersion,
@@ -576,11 +488,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
576
488
  cveSummaries,
577
489
  scope,
578
490
  originalMajorVersion: originalMajor,
579
- directDepInfo: isTransitive && directDepInfo ? {
580
- name: directDepInfo.name,
581
- version: directDepInfo.version,
582
- scope: directDepInfo.scope
583
- } : undefined
491
+ directDepInfos: isTransitive && directDepInfosArray.length > 0 ? directDepInfosArray : undefined
584
492
  };
585
493
  fixes.push(fix);
586
494
  }
@@ -588,47 +496,50 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
588
496
  return fixes;
589
497
  });
590
498
  }
591
- tryFindDirectDepUpgrade(transitivePackageName, requiredFixVersion, directDepInfo, projectContext, db) {
592
- return __awaiter(this, void 0, void 0, function* () {
593
- const isVulnerable = (version) => {
594
- try {
595
- return semver.lt(version, requiredFixVersion);
596
- }
597
- catch (_a) {
598
- return true;
599
- }
600
- };
601
- const isWithinDelta = (from, to) => {
602
- return this.isVersionWithinDelta(from, to);
603
- };
604
- try {
605
- const upgradeVersion = yield (0, npm_utils_1.findDirectUpgradeThatFixesTransitive)(projectContext.packageManager, directDepInfo.name, directDepInfo.version, transitivePackageName, isVulnerable, isWithinDelta, projectContext.originalPackageJson, directDepInfo.scope, projectContext.configFiles);
606
- return upgradeVersion;
607
- }
608
- catch (_a) {
609
- return undefined;
610
- }
611
- });
612
- }
613
- tryDirectUpgradesForTransitives(fixes, updateInfo, db) {
499
+ tryDirectUpgradesForTransitives(fixes, updateInfo) {
614
500
  return __awaiter(this, void 0, void 0, function* () {
615
501
  const result = [];
616
502
  for (const fix of fixes) {
617
- if (!fix.directDepInfo) {
503
+ if (!fix.directDepInfos || fix.directDepInfos.length === 0) {
618
504
  result.push(fix);
619
505
  continue;
620
506
  }
621
- const directUpgradeVersion = yield this.tryFindDirectDepUpgrade(fix.packageName, fix.newVersion, fix.directDepInfo, {
622
- packageManager: updateInfo.packageManager,
623
- originalPackageJson: updateInfo.originalPackageJson,
624
- configFiles: updateInfo.configFiles
625
- }, db);
626
- if (directUpgradeVersion) {
627
- result.push(Object.assign(Object.assign({}, fix), { fixViaDirectUpgrade: {
628
- directDepName: fix.directDepInfo.name,
507
+ const candidateUpgrades = [];
508
+ const isVulnerable = (version) => {
509
+ try {
510
+ return semver.lt(version, fix.newVersion);
511
+ }
512
+ catch (_a) {
513
+ return true;
514
+ }
515
+ };
516
+ const isWithinDelta = (from, to) => {
517
+ return (0, version_utils_1.isVersionWithinDelta)(from, to, this.maximumUpgradeDelta);
518
+ };
519
+ for (const directDepInfo of fix.directDepInfos) {
520
+ const directUpgradeVersion = yield (0, npm_utils_1.findDirectUpgradeWithSafeTransitiveInIsolation)(updateInfo.packageManager, directDepInfo.name, directDepInfo.version, fix.packageName, isVulnerable, isWithinDelta, directDepInfo.scope, updateInfo.configFiles);
521
+ if (directUpgradeVersion) {
522
+ candidateUpgrades.push({
523
+ directDepName: directDepInfo.name,
629
524
  directDepVersion: directUpgradeVersion,
630
- directDepScope: fix.directDepInfo.scope
631
- } }));
525
+ directDepScope: directDepInfo.scope
526
+ });
527
+ }
528
+ }
529
+ if (candidateUpgrades.length > 0) {
530
+ const foundAllUpgrades = candidateUpgrades.length === fix.directDepInfos.length;
531
+ if (foundAllUpgrades) {
532
+ const allFixed = yield (0, npm_utils_1.verifyAllUpgradesFixTransitive)(updateInfo.packageManager, candidateUpgrades.map(u => ({
533
+ name: u.directDepName,
534
+ version: u.directDepVersion,
535
+ scope: u.directDepScope
536
+ })), fix.packageName, isVulnerable, updateInfo.originalPackageJson, updateInfo.configFiles);
537
+ if (allFixed) {
538
+ result.push(Object.assign(Object.assign({}, fix), { fixViaDirectUpgrades: candidateUpgrades }));
539
+ continue;
540
+ }
541
+ }
542
+ result.push(Object.assign(Object.assign({}, fix), { fixViaDirectUpgrades: candidateUpgrades }));
632
543
  }
633
544
  else {
634
545
  result.push(fix);
@@ -680,7 +591,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
680
591
  const visited = new Set();
681
592
  const scopesToCheck = recipe.scope
682
593
  ? [recipe.scope]
683
- : ALL_DEPENDENCY_SCOPES;
594
+ : types_1.ALL_DEPENDENCY_SCOPES;
684
595
  for (const scope of scopesToCheck) {
685
596
  const deps = marker[scope] || [];
686
597
  for (const dep of deps) {
@@ -713,7 +624,9 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
713
624
  fixes = yield recipe.computeFixes(vulnerabilities, acc.db, {
714
625
  packageManager: pm,
715
626
  originalPackageJson,
716
- configFiles: Object.keys(configFiles).length > 0 ? configFiles : undefined
627
+ configFiles: Object.keys(configFiles).length > 0 ? configFiles : undefined,
628
+ marker,
629
+ scopesToCheck
717
630
  });
718
631
  }
719
632
  if (recipe.fixDeclaredVersions) {
@@ -844,7 +757,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
844
757
  const vulnerabilities = acc.vulnerableByProject.get(doc.sourcePath);
845
758
  if (vulnerabilities && vulnerabilities.length > 0) {
846
759
  for (const vuln of vulnerabilities) {
847
- const upgradeable = recipe.isUpgradeableWithinDelta(vuln.resolved.version, vuln.vulnerability);
760
+ const upgradeable = !recipe.isReportOnly() && (0, version_utils_1.isUpgradeableWithinDelta)(vuln.resolved.version, vuln.vulnerability, recipe.maximumUpgradeDelta);
848
761
  recipe.vulnerabilityReport.insertRow(ctx, new VulnerabilityReportRow(doc.sourcePath, vuln.vulnerability.cve, vuln.resolved.name, vuln.resolved.version, vuln.vulnerability.fixedVersion || '', vuln.vulnerability.lastAffectedVersion || '', upgradeable, vuln.vulnerability.summary, vuln.vulnerability.severity, vuln.depth, vuln.vulnerability.cwes, vuln.isDirect, recipe.renderPath(vuln.scope, vuln.path)));
849
762
  }
850
763
  }
@@ -1011,8 +924,8 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
1011
924
  }
1012
925
  runPackageManagerInstall(acc, updateInfo, fixes) {
1013
926
  return __awaiter(this, void 0, void 0, function* () {
1014
- const directFixes = fixes.filter(f => !f.isTransitive || f.fixViaDirectUpgrade);
1015
- const transitiveFixes = fixes.filter(f => f.isTransitive && !f.fixViaDirectUpgrade);
927
+ const directFixes = fixes.filter(f => !f.isTransitive || (f.fixViaDirectUpgrades && f.fixViaDirectUpgrades.length > 0));
928
+ const transitiveFixes = fixes.filter(f => f.isTransitive && (!f.fixViaDirectUpgrades || f.fixViaDirectUpgrades.length === 0));
1016
929
  if (this.shouldVerifyTransitiveFixes() && transitiveFixes.length > 0) {
1017
930
  const phase1PackageJson = this.createModifiedPackageJson(updateInfo.originalPackageJson, directFixes, updateInfo.packageManager);
1018
931
  const phase1Result = yield (0, javascript_1.runInstallInTempDir)(updateInfo.packageManager, phase1PackageJson, {
@@ -1032,7 +945,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
1032
945
  return;
1033
946
  }
1034
947
  if (this.transitiveFixStrategy === 'prefer-direct-upgrade') {
1035
- remainingTransitiveFixes = yield this.tryDirectUpgradesForTransitives(remainingTransitiveFixes, updateInfo, acc.db);
948
+ remainingTransitiveFixes = yield this.tryDirectUpgradesForTransitives(remainingTransitiveFixes, updateInfo);
1036
949
  }
1037
950
  const finalFixes = [...directFixes, ...remainingTransitiveFixes];
1038
951
  const finalPackageJson = this.createModifiedPackageJson(updateInfo.originalPackageJson, finalFixes, updateInfo.packageManager);
@@ -1053,21 +966,18 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
1053
966
  return __awaiter(this, void 0, void 0, function* () {
1054
967
  const memberPaths = acc.workspaceRoots.get(rootPath) || [];
1055
968
  const pm = rootUpdateInfo.packageManager;
1056
- const allDirectFixes = [];
1057
969
  const allTransitiveFixes = [];
1058
970
  const rootFixes = acc.fixesByProject.get(rootPath) || [];
1059
- const rootDirectFixes = rootFixes.filter(f => !f.isTransitive || f.fixViaDirectUpgrade);
1060
- const rootTransitiveFixes = rootFixes.filter(f => f.isTransitive && !f.fixViaDirectUpgrade);
1061
- allDirectFixes.push(...rootDirectFixes);
971
+ const rootDirectFixes = rootFixes.filter(f => !f.isTransitive || (f.fixViaDirectUpgrades && f.fixViaDirectUpgrades.length > 0));
972
+ const rootTransitiveFixes = rootFixes.filter(f => f.isTransitive && (!f.fixViaDirectUpgrades || f.fixViaDirectUpgrades.length === 0));
1062
973
  allTransitiveFixes.push(...rootTransitiveFixes);
1063
974
  const memberDirectFixes = new Map();
1064
975
  for (const memberPath of memberPaths) {
1065
976
  const memberFixes = acc.fixesByProject.get(memberPath) || [];
1066
- const directFixes = memberFixes.filter(f => !f.isTransitive || f.fixViaDirectUpgrade);
1067
- const transitiveFixes = memberFixes.filter(f => f.isTransitive && !f.fixViaDirectUpgrade);
977
+ const directFixes = memberFixes.filter(f => !f.isTransitive || (f.fixViaDirectUpgrades && f.fixViaDirectUpgrades.length > 0));
978
+ const transitiveFixes = memberFixes.filter(f => f.isTransitive && (!f.fixViaDirectUpgrades || f.fixViaDirectUpgrades.length === 0));
1068
979
  if (directFixes.length > 0) {
1069
980
  memberDirectFixes.set(memberPath, directFixes);
1070
- allDirectFixes.push(...directFixes);
1071
981
  }
1072
982
  allTransitiveFixes.push(...transitiveFixes);
1073
983
  }
@@ -1110,7 +1020,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
1110
1020
  return;
1111
1021
  }
1112
1022
  if (this.transitiveFixStrategy === 'prefer-direct-upgrade') {
1113
- remainingTransitiveFixes = yield this.tryDirectUpgradesForTransitives(remainingTransitiveFixes, rootUpdateInfo, acc.db);
1023
+ remainingTransitiveFixes = yield this.tryDirectUpgradesForTransitives(remainingTransitiveFixes, rootUpdateInfo);
1114
1024
  }
1115
1025
  const finalRootPackageJson = this.createModifiedPackageJson(rootOriginalContent, [...rootDirectFixes, ...remainingTransitiveFixes], pm);
1116
1026
  const finalResult = yield (0, javascript_1.runWorkspaceInstallInTempDir)(pm, finalRootPackageJson, {
@@ -1134,7 +1044,7 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
1134
1044
  if (!fix.isTransitive && fix.scope) {
1135
1045
  if (packageJson[fix.scope] && packageJson[fix.scope][fix.packageName]) {
1136
1046
  const originalVersion = packageJson[fix.scope][fix.packageName];
1137
- packageJson[fix.scope][fix.packageName] = applyVersionPrefix(originalVersion, fix.newVersion);
1047
+ packageJson[fix.scope][fix.packageName] = (0, version_utils_1.applyVersionPrefix)(originalVersion, fix.newVersion);
1138
1048
  }
1139
1049
  }
1140
1050
  }
@@ -1154,19 +1064,21 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
1154
1064
  if (!fix.isTransitive && fix.scope) {
1155
1065
  if (packageJson[fix.scope] && packageJson[fix.scope][fix.packageName]) {
1156
1066
  const originalVersion = packageJson[fix.scope][fix.packageName];
1157
- packageJson[fix.scope][fix.packageName] = applyVersionPrefix(originalVersion, fix.newVersion);
1067
+ packageJson[fix.scope][fix.packageName] = (0, version_utils_1.applyVersionPrefix)(originalVersion, fix.newVersion);
1158
1068
  }
1159
1069
  }
1160
1070
  else if (fix.isTransitive) {
1161
- if (fix.fixViaDirectUpgrade) {
1162
- const { directDepName, directDepVersion, directDepScope } = fix.fixViaDirectUpgrade;
1163
- if ((_a = packageJson[directDepScope]) === null || _a === void 0 ? void 0 : _a[directDepName]) {
1164
- const originalVersion = packageJson[directDepScope][directDepName];
1165
- packageJson[directDepScope][directDepName] = applyVersionPrefix(originalVersion, directDepVersion);
1166
- continue;
1071
+ if (fix.fixViaDirectUpgrades && fix.fixViaDirectUpgrades.length > 0) {
1072
+ for (const upgrade of fix.fixViaDirectUpgrades) {
1073
+ const { directDepName, directDepVersion, directDepScope } = upgrade;
1074
+ if ((_a = packageJson[directDepScope]) === null || _a === void 0 ? void 0 : _a[directDepName]) {
1075
+ const originalVersion = packageJson[directDepScope][directDepName];
1076
+ packageJson[directDepScope][directDepName] = (0, version_utils_1.applyVersionPrefix)(originalVersion, directDepVersion);
1077
+ }
1167
1078
  }
1079
+ continue;
1168
1080
  }
1169
- const directDepScope = findDirectDependencyScope(packageJson, fix.packageName);
1081
+ const directDepScope = (0, override_utils_1.findDirectDependencyScope)(packageJson, fix.packageName);
1170
1082
  if (directDepScope) {
1171
1083
  const directVersion = packageJson[directDepScope][fix.packageName];
1172
1084
  const directMajor = semver.major(semver.coerce(directVersion) || '0.0.0');
@@ -1182,13 +1094,13 @@ class DependencyVulnerabilityCheck extends rewrite_1.ScanningRecipe {
1182
1094
  }
1183
1095
  continue;
1184
1096
  }
1185
- packageJson[directDepScope][fix.packageName] = applyVersionPrefix(directVersion, fix.newVersion);
1097
+ packageJson[directDepScope][fix.packageName] = (0, version_utils_1.applyVersionPrefix)(directVersion, fix.newVersion);
1186
1098
  continue;
1187
1099
  }
1188
1100
  const packageFixes = fixesByPackage.get(fix.packageName) || [];
1189
1101
  const hasMultipleMajorVersions = packageFixes.length > 1 &&
1190
1102
  new Set(packageFixes.map(f => f.originalMajorVersion)).size > 1;
1191
- const existingOverrides = getOverridesFromPackageJson(packageJson, packageManager);
1103
+ const existingOverrides = (0, override_utils_1.getOverridesFromPackageJson)(packageJson, packageManager);
1192
1104
  const hasExistingVersionSpecificOverrides = existingOverrides &&
1193
1105
  Object.keys(existingOverrides).some(key => key.startsWith(`${fix.packageName}@`));
1194
1106
  const isYarn = packageManager === "YarnClassic" ||
@@ -1338,42 +1250,4 @@ __decorate([
1338
1250
  example: "true"
1339
1251
  })
1340
1252
  ], DependencyVulnerabilityCheck.prototype, "addOverrideComments", void 0);
1341
- function extractVersionPrefix(versionString) {
1342
- const match = versionString.match(/^([~^]|>=?|<=?|=)?(.*)$/);
1343
- if (match) {
1344
- return {
1345
- prefix: match[1] || '',
1346
- version: match[2]
1347
- };
1348
- }
1349
- return { prefix: '', version: versionString };
1350
- }
1351
- function applyVersionPrefix(originalVersion, newVersion) {
1352
- const { prefix } = extractVersionPrefix(originalVersion);
1353
- return prefix + newVersion;
1354
- }
1355
- function findDirectDependencyScope(packageJson, packageName) {
1356
- var _a;
1357
- for (const scope of ALL_DEPENDENCY_SCOPES) {
1358
- if ((_a = packageJson[scope]) === null || _a === void 0 ? void 0 : _a[packageName]) {
1359
- return scope;
1360
- }
1361
- }
1362
- return undefined;
1363
- }
1364
- function getOverridesFromPackageJson(packageJson, packageManager) {
1365
- var _a;
1366
- switch (packageManager) {
1367
- case "Npm":
1368
- case "Bun":
1369
- return packageJson.overrides;
1370
- case "Pnpm":
1371
- return (_a = packageJson.pnpm) === null || _a === void 0 ? void 0 : _a.overrides;
1372
- case "YarnClassic":
1373
- case "YarnBerry":
1374
- return packageJson.resolutions;
1375
- default:
1376
- return undefined;
1377
- }
1378
- }
1379
1253
  //# sourceMappingURL=dependency-vulnerability-check.js.map