sentinello 3.8.0 → 3.8.2

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 (2) hide show
  1. package/dist/cli.cjs +639 -216
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -2680,16 +2680,16 @@ var require_parse2 = __commonJS({
2680
2680
  return self2.pull(4).then(function(data) {
2681
2681
  if (data.length === 0)
2682
2682
  return;
2683
- const signature = data.readUInt32LE(0);
2684
- if (signature === 875721283) {
2683
+ const signature2 = data.readUInt32LE(0);
2684
+ if (signature2 === 875721283) {
2685
2685
  return self2._readCrxHeader();
2686
2686
  }
2687
- if (signature === 67324752) {
2687
+ if (signature2 === 67324752) {
2688
2688
  return self2._readFile();
2689
- } else if (signature === 33639248) {
2689
+ } else if (signature2 === 33639248) {
2690
2690
  self2.reachedCD = true;
2691
2691
  return self2._readCentralDirectoryFileHeader();
2692
- } else if (signature === 101010256) {
2692
+ } else if (signature2 === 101010256) {
2693
2693
  return self2._readEndOfCentralDirectoryRecord();
2694
2694
  } else if (self2.reachedCD) {
2695
2695
  const includeEof = true;
@@ -2697,7 +2697,7 @@ var require_parse2 = __commonJS({
2697
2697
  return self2._readEndOfCentralDirectoryRecord();
2698
2698
  });
2699
2699
  } else
2700
- self2.emit("error", new Error("invalid signature: 0x" + signature.toString(16)));
2700
+ self2.emit("error", new Error("invalid signature: 0x" + signature2.toString(16)));
2701
2701
  }).then((function(loop) {
2702
2702
  if (loop) {
2703
2703
  return self2._readRecord();
@@ -5487,8 +5487,8 @@ var require_graceful_fs = __commonJS({
5487
5487
  fs2.createReadStream = createReadStream;
5488
5488
  fs2.createWriteStream = createWriteStream2;
5489
5489
  var fs$readFile = fs2.readFile;
5490
- fs2.readFile = readFile13;
5491
- function readFile13(path, options, cb) {
5490
+ fs2.readFile = readFile14;
5491
+ function readFile14(path, options, cb) {
5492
5492
  if (typeof options === "function")
5493
5493
  cb = options, options = null;
5494
5494
  return go$readFile(path, options, cb);
@@ -6874,7 +6874,7 @@ var require_jsonfile = __commonJS({
6874
6874
  }
6875
6875
  return obj2;
6876
6876
  }
6877
- var readFile13 = universalify.fromPromise(_readFile);
6877
+ var readFile14 = universalify.fromPromise(_readFile);
6878
6878
  function readFileSync2(file2, options = {}) {
6879
6879
  if (typeof options === "string") {
6880
6880
  options = { encoding: options };
@@ -6906,7 +6906,7 @@ var require_jsonfile = __commonJS({
6906
6906
  return fs.writeFileSync(file2, str2, options);
6907
6907
  }
6908
6908
  module2.exports = {
6909
- readFile: readFile13,
6909
+ readFile: readFile14,
6910
6910
  readFileSync: readFileSync2,
6911
6911
  writeFile: writeFile4,
6912
6912
  writeFileSync
@@ -12784,13 +12784,13 @@ var require_directory = __commonJS({
12784
12784
  var parseDateTime = require_parseDateTime();
12785
12785
  var parseBuffer = require_parseBuffer();
12786
12786
  var Bluebird = require_bluebird();
12787
- var signature = Buffer.alloc(4);
12788
- signature.writeUInt32LE(101010256, 0);
12787
+ var signature2 = Buffer.alloc(4);
12788
+ signature2.writeUInt32LE(101010256, 0);
12789
12789
  function getCrxHeader(source) {
12790
12790
  const sourceStream = source.stream(0).pipe(PullStream());
12791
12791
  return sourceStream.pull(4).then(function(data) {
12792
- const signature2 = data.readUInt32LE(0);
12793
- if (signature2 === 875721283) {
12792
+ const signature3 = data.readUInt32LE(0);
12793
+ if (signature3 === 875721283) {
12794
12794
  let crxHeader;
12795
12795
  return sourceStream.pull(12).then(function(data2) {
12796
12796
  crxHeader = parseBuffer.parse(data2, [
@@ -12853,7 +12853,7 @@ var require_directory = __commonJS({
12853
12853
  source.stream(Math.max(0, size - tailSize)).on("error", function(error62) {
12854
12854
  endDir.emit("error", error62);
12855
12855
  }).pipe(endDir);
12856
- return endDir.pull(signature);
12856
+ return endDir.pull(signature2);
12857
12857
  }).then(function() {
12858
12858
  return Bluebird.props({ directory: endDir.pull(22), crxHeader });
12859
12859
  }).then(function(d) {
@@ -13113,6 +13113,7 @@ var SEVERITY_WEIGHT = {
13113
13113
  critical: 5,
13114
13114
  high: 4,
13115
13115
  moderate: 3,
13116
+ unrated: 3,
13116
13117
  low: 2,
13117
13118
  info: 1
13118
13119
  };
@@ -13133,7 +13134,7 @@ function maxSeverity(severities) {
13133
13134
  for (const s of severities) {
13134
13135
  const normalized = s.trim().toLowerCase();
13135
13136
  const known = SEVERITY_WEIGHT[normalized];
13136
- if (known !== void 0 && known > bestWeight) {
13137
+ if (known !== void 0 && (known > bestWeight || known === bestWeight && normalized === "moderate")) {
13137
13138
  bestWeight = known;
13138
13139
  best = normalized;
13139
13140
  }
@@ -13174,6 +13175,7 @@ var REASON_CODE_VALUES = [
13174
13175
  "ambiguous_dependency_spec",
13175
13176
  "unsupported_lockfile",
13176
13177
  "ecosystem_source_disabled",
13178
+ "source_not_applicable",
13177
13179
  "timeout"
13178
13180
  ];
13179
13181
  var SOURCE_UNAVAILABLE_REASON_CODES = [
@@ -13747,7 +13749,7 @@ var ECOSYSTEMS = [
13747
13749
  status: "stable",
13748
13750
  osvEcosystem: "npm",
13749
13751
  gemnasiumPackageType: "npm",
13750
- resolverKinds: ["package-lock.json", "pnpm-lock.yaml", "yarn.lock"],
13752
+ resolverKinds: ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lock", "bun.lockb"],
13751
13753
  manifestKinds: ["package.json"],
13752
13754
  comparator: "semver",
13753
13755
  wayOut: true,
@@ -13821,6 +13823,9 @@ function getSource(id) {
13821
13823
  }
13822
13824
  return null;
13823
13825
  }
13826
+ function sourceAppliesToPackageManager(source, packageManager) {
13827
+ return !(source === "npm-audit" && packageManager === "bun");
13828
+ }
13824
13829
  function requireEcosystemId(id) {
13825
13830
  const def = getEcosystem(id);
13826
13831
  if (def === null) throw new Error("unknown ecosystem " + JSON.stringify(id));
@@ -13855,6 +13860,8 @@ var MANIFEST_PACKAGE_MANAGERS = {
13855
13860
  "package-lock.json": "npm",
13856
13861
  "pnpm-lock.yaml": "pnpm",
13857
13862
  "yarn.lock": "yarn",
13863
+ "bun.lock": "bun",
13864
+ "bun.lockb": "bun",
13858
13865
  "package.json": "unknown",
13859
13866
  "poetry.lock": "poetry",
13860
13867
  "Pipfile.lock": "pipenv",
@@ -13904,6 +13911,7 @@ var REASON_CODE_LABELS = {
13904
13911
  ambiguous_dependency_spec: "Ambiguous dependency spec",
13905
13912
  unsupported_lockfile: "Unsupported lockfile",
13906
13913
  ecosystem_source_disabled: "No source enabled for ecosystem",
13914
+ source_not_applicable: "npm audit does not read bun.lock",
13907
13915
  timeout: "Timeout"
13908
13916
  },
13909
13917
  "es": {
@@ -13935,6 +13943,7 @@ var REASON_CODE_LABELS = {
13935
13943
  ambiguous_dependency_spec: "Especificaci\xF3n de dependencia ambigua",
13936
13944
  unsupported_lockfile: "Lockfile no compatible",
13937
13945
  ecosystem_source_disabled: "Sin fuente habilitada para el ecosistema",
13946
+ source_not_applicable: "npm audit no lee bun.lock",
13938
13947
  timeout: "Tiempo de espera agotado"
13939
13948
  },
13940
13949
  "fr": {
@@ -13966,6 +13975,7 @@ var REASON_CODE_LABELS = {
13966
13975
  ambiguous_dependency_spec: "Sp\xE9cification de d\xE9pendance ambigu\xEB",
13967
13976
  unsupported_lockfile: "Lockfile non pris en charge",
13968
13977
  ecosystem_source_disabled: "Aucune source activ\xE9e pour l\u2019\xE9cosyst\xE8me",
13978
+ source_not_applicable: "npm audit ne lit pas bun.lock",
13969
13979
  timeout: "D\xE9lai d\xE9pass\xE9"
13970
13980
  },
13971
13981
  "de": {
@@ -13997,6 +14007,7 @@ var REASON_CODE_LABELS = {
13997
14007
  ambiguous_dependency_spec: "Mehrdeutige Abh\xE4ngigkeitsangabe",
13998
14008
  unsupported_lockfile: "Nicht unterst\xFCtzte Lockfile",
13999
14009
  ecosystem_source_disabled: "Keine Quelle f\xFCr \xD6kosystem aktiviert",
14010
+ source_not_applicable: "npm audit liest bun.lock nicht",
14000
14011
  timeout: "Zeit\xFCberschreitung"
14001
14012
  },
14002
14013
  "pt-BR": {
@@ -14028,6 +14039,7 @@ var REASON_CODE_LABELS = {
14028
14039
  ambiguous_dependency_spec: "Especifica\xE7\xE3o de depend\xEAncia amb\xEDgua",
14029
14040
  unsupported_lockfile: "Lockfile n\xE3o suportado",
14030
14041
  ecosystem_source_disabled: "Nenhuma fonte habilitada para o ecossistema",
14042
+ source_not_applicable: "npm audit n\xE3o l\xEA bun.lock",
14031
14043
  timeout: "Tempo esgotado"
14032
14044
  },
14033
14045
  "it": {
@@ -14059,6 +14071,7 @@ var REASON_CODE_LABELS = {
14059
14071
  ambiguous_dependency_spec: "Specifica di dipendenza ambigua",
14060
14072
  unsupported_lockfile: "Lockfile non supportato",
14061
14073
  ecosystem_source_disabled: "Nessuna fonte abilitata per l\u2019ecosistema",
14074
+ source_not_applicable: "npm audit non legge bun.lock",
14062
14075
  timeout: "Timeout scaduto"
14063
14076
  },
14064
14077
  "ja": {
@@ -14090,6 +14103,7 @@ var REASON_CODE_LABELS = {
14090
14103
  ambiguous_dependency_spec: "\u4F9D\u5B58\u95A2\u4FC2\u306E\u6307\u5B9A\u304C\u66D6\u6627",
14091
14104
  unsupported_lockfile: "\u672A\u5BFE\u5FDC\u306E\u30ED\u30C3\u30AF\u30D5\u30A1\u30A4\u30EB",
14092
14105
  ecosystem_source_disabled: "\u30A8\u30B3\u30B7\u30B9\u30C6\u30E0\u306B\u6709\u52B9\u306A\u30BD\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093",
14106
+ source_not_applicable: "npm audit \u306F bun.lock \u3092\u8AAD\u307F\u53D6\u308A\u307E\u305B\u3093",
14093
14107
  timeout: "\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8"
14094
14108
  },
14095
14109
  "zh-CN": {
@@ -14121,6 +14135,7 @@ var REASON_CODE_LABELS = {
14121
14135
  ambiguous_dependency_spec: "\u4F9D\u8D56\u9879\u89C4\u8303\u4E0D\u660E\u786E",
14122
14136
  unsupported_lockfile: "\u4E0D\u652F\u6301\u7684\u9501\u6587\u4EF6",
14123
14137
  ecosystem_source_disabled: "\u8BE5\u751F\u6001\u7CFB\u7EDF\u672A\u542F\u7528\u4EFB\u4F55\u6765\u6E90",
14138
+ source_not_applicable: "npm audit \u4E0D\u8BFB\u53D6 bun.lock",
14124
14139
  timeout: "\u8D85\u65F6"
14125
14140
  },
14126
14141
  "ko": {
@@ -14152,6 +14167,7 @@ var REASON_CODE_LABELS = {
14152
14167
  ambiguous_dependency_spec: "\uBAA8\uD638\uD55C \uC758\uC874\uC131 \uBA85\uC138",
14153
14168
  unsupported_lockfile: "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC7A0\uAE08 \uD30C\uC77C",
14154
14169
  ecosystem_source_disabled: "\uC0DD\uD0DC\uACC4\uC5D0 \uD65C\uC131\uD654\uB41C \uC18C\uC2A4 \uC5C6\uC74C",
14170
+ source_not_applicable: "npm audit\uB294 bun.lock\uC744 \uC77D\uC9C0 \uC54A\uC74C",
14155
14171
  timeout: "\uC2DC\uAC04 \uCD08\uACFC"
14156
14172
  },
14157
14173
  "ru": {
@@ -14183,6 +14199,7 @@ var REASON_CODE_LABELS = {
14183
14199
  ambiguous_dependency_spec: "\u041D\u0435\u043E\u0434\u043D\u043E\u0437\u043D\u0430\u0447\u043D\u0430\u044F \u0441\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0438",
14184
14200
  unsupported_lockfile: "\u041D\u0435\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043C\u044B\u0439 lockfile",
14185
14201
  ecosystem_source_disabled: "\u041D\u0435\u0442 \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A\u0430 \u0434\u043B\u044F \u044D\u043A\u043E\u0441\u0438\u0441\u0442\u0435\u043C\u044B",
14202
+ source_not_applicable: "npm audit \u043D\u0435 \u0447\u0438\u0442\u0430\u0435\u0442 bun.lock",
14186
14203
  timeout: "\u0422\u0430\u0439\u043C-\u0430\u0443\u0442"
14187
14204
  }
14188
14205
  };
@@ -14322,6 +14339,7 @@ var REASON_SIDE = {
14322
14339
  gemnasium_db_not_seeded: "environment",
14323
14340
  gemnasium_db_unavailable: "environment",
14324
14341
  ecosystem_source_disabled: "environment",
14342
+ source_not_applicable: "environment",
14325
14343
  timeout: "environment"
14326
14344
  };
14327
14345
  function failureReasonCode(code) {
@@ -14402,6 +14420,12 @@ var NOT_YET_RUN_LABELS = {
14402
14420
  };
14403
14421
 
14404
14422
  // ../../packages/core/src/fix-status.ts
14423
+ function fixKindOf(f) {
14424
+ if (f.fixStatus !== "released" || !f.fixVersion) return null;
14425
+ const comparator = comparatorForEcosystem(f.ecosystem);
14426
+ const normalized = comparator?.normalize(f.fixVersion) ?? null;
14427
+ return normalized !== null && comparator.releaseKind(normalized) === "pseudo" ? "untagged_commit" : "release";
14428
+ }
14405
14429
  function isoDate2(at) {
14406
14430
  return new Date(at).toISOString().slice(0, 10);
14407
14431
  }
@@ -14420,12 +14444,17 @@ function staleSuffix(check2) {
14420
14444
  return " \xB7 cached data from " + isoDate2(check2.packageDataAsOf);
14421
14445
  }
14422
14446
  function describeNotRechecked(reason) {
14423
- const project = reason.projectState === "cannot_scan" ? "the project cannot be scanned" : "the project cannot be fully scanned";
14424
- if (reason.manifests !== null) return "copies in " + reason.manifests.join(", ") + " not re-checked \u2014 " + project + ": " + reasonCodeLabel(reason.reasonCode);
14447
+ const project = projectCannotBeScanned(reason);
14448
+ if (reason.manifests !== null) return "copies in " + reason.manifests.join(", ") + " not re-checked \u2014 " + project + reasonCodeLabel(reason.reasonCode);
14425
14449
  const when = reason.lastOkScanAt === null ? "never scanned successfully" : "last scanned successfully " + isoDate2(reason.lastOkScanAt);
14426
- return "not re-checked \u2014 " + project + ": " + reasonCodeLabel(reason.reasonCode) + " (" + when + ")";
14450
+ return "not re-checked \u2014 " + project + reasonCodeLabel(reason.reasonCode) + " (" + when + ")";
14451
+ }
14452
+ function projectCannotBeScanned(reason) {
14453
+ if (reason.projectState === "cannot_scan") return "the project cannot be scanned: ";
14454
+ return reason.projectState === "partial" || reason.manifests !== null ? "the project cannot be fully scanned: " : "";
14427
14455
  }
14428
14456
  function describeFix(f, style) {
14457
+ if (f.noticeKind) return "no fix to chase \u2014 this is a notice (" + f.noticeKind + "), not a vulnerability";
14429
14458
  const notRechecked = f.notRecheckedBecause ?? null;
14430
14459
  if (notRechecked === null) return describeSettledFix(f, style);
14431
14460
  if (f.fixCheck === null) return describeNotRechecked(notRechecked);
@@ -14435,6 +14464,7 @@ function describeSettledFix(f, style) {
14435
14464
  const check2 = f.fixCheck;
14436
14465
  if (check2 === null) return "fix not re-checked yet \u2014 rescan pending";
14437
14466
  if (f.fixStatus === "released" && f.fixVersion) {
14467
+ if (fixKindOf(f) === "untagged_commit") return "upgrade to " + style.code(f.fixVersion) + " (an untagged commit: no tagged release has the fix)" + staleSuffix(check2);
14438
14468
  return "upgrade to " + style.code(f.fixVersion) + staleSuffix(check2);
14439
14469
  }
14440
14470
  if (f.fixStatus === "none_released") {
@@ -14460,6 +14490,93 @@ function describeFixDisagreement(f, style) {
14460
14490
  return "sources disagree: " + listed + " \u2014 " + style.code(f.fixVersion) + " is outside " + outside;
14461
14491
  }
14462
14492
 
14493
+ // ../../packages/core/src/reason-fix-hints.ts
14494
+ var REASON_FIX_HINTS = {
14495
+ "en": {
14496
+ no_lockfile: "commit the lockfile your package manager writes",
14497
+ unknown_pm: "name the package manager in package.json, or commit its lockfile",
14498
+ yarn_v1_unsupported: "move to Yarn 2 or later, npm or pnpm",
14499
+ partial_dependency_graph: "pin what comes from git, a local path or a URL to a released version where you can",
14500
+ ambiguous_dependency_spec: "pin exact versions (== in requirements.txt) or commit a lockfile",
14501
+ unsupported_lockfile: "regenerate it in a format Sentinello reads: npm install with npm 7 or later, or bun install --save-text-lockfile"
14502
+ },
14503
+ "es": {
14504
+ no_lockfile: "haz commit del lockfile que escribe tu gestor de paquetes",
14505
+ unknown_pm: "indica el gestor de paquetes en package.json o haz commit de su lockfile",
14506
+ yarn_v1_unsupported: "pasa a Yarn 2 o posterior, npm o pnpm",
14507
+ partial_dependency_graph: "fija en una versi\xF3n publicada lo que venga de git, de una ruta local o de una URL, cuando puedas",
14508
+ ambiguous_dependency_spec: "fija versiones exactas (== en requirements.txt) o haz commit de un lockfile",
14509
+ unsupported_lockfile: "regen\xE9ralo en un formato que Sentinello lea: npm install con npm 7 o posterior, o bun install --save-text-lockfile"
14510
+ },
14511
+ "fr": {
14512
+ no_lockfile: "committez le lockfile \xE9crit par votre gestionnaire de paquets",
14513
+ unknown_pm: "indiquez le gestionnaire de paquets dans package.json, ou committez son lockfile",
14514
+ yarn_v1_unsupported: "passez \xE0 Yarn 2 ou ult\xE9rieur, npm ou pnpm",
14515
+ partial_dependency_graph: "\xE9pinglez sur une version publi\xE9e ce qui vient de git, d'un chemin local ou d'une URL, si possible",
14516
+ ambiguous_dependency_spec: "\xE9pinglez des versions exactes (== dans requirements.txt) ou committez un lockfile",
14517
+ unsupported_lockfile: "r\xE9g\xE9n\xE9rez-le dans un format que Sentinello lit : npm install avec npm 7 ou ult\xE9rieur, ou bun install --save-text-lockfile"
14518
+ },
14519
+ "de": {
14520
+ no_lockfile: "committe die Lockfile, die dein Paketmanager schreibt",
14521
+ unknown_pm: "nenne den Paketmanager in package.json oder committe seine Lockfile",
14522
+ yarn_v1_unsupported: "wechsle zu Yarn 2 oder neuer, npm oder pnpm",
14523
+ partial_dependency_graph: "pinne, was aus git, einem lokalen Pfad oder einer URL kommt, wo m\xF6glich auf eine ver\xF6ffentlichte Version",
14524
+ ambiguous_dependency_spec: "pinne exakte Versionen (== in requirements.txt) oder committe eine Lockfile",
14525
+ unsupported_lockfile: "erzeuge sie in einem Format neu, das Sentinello liest: npm install mit npm 7 oder neuer, oder bun install --save-text-lockfile"
14526
+ },
14527
+ "pt-BR": {
14528
+ no_lockfile: "fa\xE7a commit do lockfile que seu gerenciador de pacotes escreve",
14529
+ unknown_pm: "indique o gerenciador de pacotes no package.json ou fa\xE7a commit do lockfile dele",
14530
+ yarn_v1_unsupported: "migre para Yarn 2 ou posterior, npm ou pnpm",
14531
+ partial_dependency_graph: "fixe em uma vers\xE3o publicada o que vem do git, de um caminho local ou de uma URL, quando poss\xEDvel",
14532
+ ambiguous_dependency_spec: "fixe vers\xF5es exatas (== no requirements.txt) ou fa\xE7a commit de um lockfile",
14533
+ unsupported_lockfile: "gere-o de novo em um formato que o Sentinello leia: npm install com npm 7 ou posterior, ou bun install --save-text-lockfile"
14534
+ },
14535
+ "it": {
14536
+ no_lockfile: "esegui il commit del lockfile scritto dal tuo gestore di pacchetti",
14537
+ unknown_pm: "indica il gestore di pacchetti in package.json o esegui il commit del suo lockfile",
14538
+ yarn_v1_unsupported: "passa a Yarn 2 o successivo, npm o pnpm",
14539
+ partial_dependency_graph: "fissa su una versione pubblicata ci\xF2 che viene da git, da un percorso locale o da un URL, dove puoi",
14540
+ ambiguous_dependency_spec: "fissa versioni esatte (== in requirements.txt) o esegui il commit di un lockfile",
14541
+ unsupported_lockfile: "rigeneralo in un formato che Sentinello legge: npm install con npm 7 o successivo, oppure bun install --save-text-lockfile"
14542
+ },
14543
+ "ja": {
14544
+ no_lockfile: "\u30D1\u30C3\u30B1\u30FC\u30B8\u30DE\u30CD\u30FC\u30B8\u30E3\u30FC\u304C\u751F\u6210\u3059\u308B lockfile \u3092\u30B3\u30DF\u30C3\u30C8\u3057\u3066\u304F\u3060\u3055\u3044",
14545
+ unknown_pm: "package.json \u3067\u30D1\u30C3\u30B1\u30FC\u30B8\u30DE\u30CD\u30FC\u30B8\u30E3\u30FC\u3092\u6307\u5B9A\u3059\u308B\u304B\u3001\u305D\u306E lockfile \u3092\u30B3\u30DF\u30C3\u30C8\u3057\u3066\u304F\u3060\u3055\u3044",
14546
+ yarn_v1_unsupported: "Yarn 2 \u4EE5\u964D\u3001npm\u3001pnpm \u306E\u3044\u305A\u308C\u304B\u306B\u79FB\u884C\u3057\u3066\u304F\u3060\u3055\u3044",
14547
+ partial_dependency_graph: "git\u3001\u30ED\u30FC\u30AB\u30EB\u30D1\u30B9\u3001URL \u304B\u3089\u53D6\u5F97\u3057\u3066\u3044\u308B\u3082\u306E\u306F\u3001\u53EF\u80FD\u306A\u7BC4\u56F2\u3067\u516C\u958B\u6E08\u307F\u30D0\u30FC\u30B8\u30E7\u30F3\u306B\u56FA\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
14548
+ ambiguous_dependency_spec: "\u6B63\u78BA\u306A\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u56FA\u5B9A\u3059\u308B\uFF08requirements.txt \u306E ==\uFF09\u304B\u3001lockfile \u3092\u30B3\u30DF\u30C3\u30C8\u3057\u3066\u304F\u3060\u3055\u3044",
14549
+ unsupported_lockfile: "Sentinello \u304C\u8AAD\u3081\u308B\u5F62\u5F0F\u3067\u518D\u751F\u6210\u3057\u3066\u304F\u3060\u3055\u3044: npm 7 \u4EE5\u964D\u306E npm install\u3001\u307E\u305F\u306F bun install --save-text-lockfile"
14550
+ },
14551
+ "zh-CN": {
14552
+ no_lockfile: "\u63D0\u4EA4\u5305\u7BA1\u7406\u5668\u751F\u6210\u7684 lockfile",
14553
+ unknown_pm: "\u5728 package.json \u4E2D\u6307\u660E\u5305\u7BA1\u7406\u5668\uFF0C\u6216\u63D0\u4EA4\u5176 lockfile",
14554
+ yarn_v1_unsupported: "\u8FC1\u79FB\u5230 Yarn 2 \u6216\u66F4\u9AD8\u7248\u672C\u3001npm \u6216 pnpm",
14555
+ partial_dependency_graph: "\u5C3D\u53EF\u80FD\u5C06\u6765\u81EA git\u3001\u672C\u5730\u8DEF\u5F84\u6216 URL \u7684\u4F9D\u8D56\u56FA\u5B9A\u5230\u5DF2\u53D1\u5E03\u7248\u672C",
14556
+ ambiguous_dependency_spec: "\u56FA\u5B9A\u786E\u5207\u7248\u672C\uFF08requirements.txt \u4E2D\u4F7F\u7528 ==\uFF09\u6216\u63D0\u4EA4 lockfile",
14557
+ unsupported_lockfile: "\u4EE5 Sentinello \u53EF\u8BFB\u7684\u683C\u5F0F\u91CD\u65B0\u751F\u6210\uFF1A\u4F7F\u7528 npm 7 \u6216\u66F4\u9AD8\u7248\u672C\u8FD0\u884C npm install\uFF0C\u6216\u8FD0\u884C bun install --save-text-lockfile"
14558
+ },
14559
+ "ko": {
14560
+ no_lockfile: "\uD328\uD0A4\uC9C0 \uAD00\uB9AC\uC790\uAC00 \uC0DD\uC131\uD558\uB294 lockfile\uC744 \uCEE4\uBC0B\uD558\uC138\uC694",
14561
+ unknown_pm: "package.json\uC5D0 \uD328\uD0A4\uC9C0 \uAD00\uB9AC\uC790\uB97C \uC9C0\uC815\uD558\uAC70\uB098 \uD574\uB2F9 lockfile\uC744 \uCEE4\uBC0B\uD558\uC138\uC694",
14562
+ yarn_v1_unsupported: "Yarn 2 \uC774\uC0C1, npm \uB610\uB294 pnpm\uC73C\uB85C \uC62E\uAE30\uC138\uC694",
14563
+ partial_dependency_graph: "git, \uB85C\uCEEC \uACBD\uB85C, URL\uC5D0\uC11C \uAC00\uC838\uC624\uB294 \uD56D\uBAA9\uC740 \uAC00\uB2A5\uD55C \uACBD\uC6B0 \uAC8C\uC2DC\uB41C \uBC84\uC804\uC73C\uB85C \uACE0\uC815\uD558\uC138\uC694",
14564
+ ambiguous_dependency_spec: "\uC815\uD655\uD55C \uBC84\uC804\uC744 \uACE0\uC815\uD558\uAC70\uB098(requirements.txt\uC758 ==) lockfile\uC744 \uCEE4\uBC0B\uD558\uC138\uC694",
14565
+ unsupported_lockfile: "Sentinello\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 \uD615\uC2DD\uC73C\uB85C \uB2E4\uC2DC \uC0DD\uC131\uD558\uC138\uC694: npm 7 \uC774\uC0C1\uC758 npm install \uB610\uB294 bun install --save-text-lockfile"
14566
+ },
14567
+ "ru": {
14568
+ no_lockfile: "\u0437\u0430\u043A\u043E\u043C\u043C\u0438\u0442\u044C\u0442\u0435 lockfile, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0441\u043E\u0437\u0434\u0430\u0451\u0442 \u0432\u0430\u0448 \u043C\u0435\u043D\u0435\u0434\u0436\u0435\u0440 \u043F\u0430\u043A\u0435\u0442\u043E\u0432",
14569
+ unknown_pm: "\u0443\u043A\u0430\u0436\u0438\u0442\u0435 \u043C\u0435\u043D\u0435\u0434\u0436\u0435\u0440 \u043F\u0430\u043A\u0435\u0442\u043E\u0432 \u0432 package.json \u0438\u043B\u0438 \u0437\u0430\u043A\u043E\u043C\u043C\u0438\u0442\u044C\u0442\u0435 \u0435\u0433\u043E lockfile",
14570
+ yarn_v1_unsupported: "\u043F\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043D\u0430 Yarn 2 \u0438\u043B\u0438 \u043D\u043E\u0432\u0435\u0435, npm \u0438\u043B\u0438 pnpm",
14571
+ partial_dependency_graph: "\u043F\u043E \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u0438 \u0437\u0430\u043A\u0440\u0435\u043F\u0438\u0442\u0435 \u043D\u0430 \u043E\u043F\u0443\u0431\u043B\u0438\u043A\u043E\u0432\u0430\u043D\u043D\u043E\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u043E, \u0447\u0442\u043E \u0431\u0435\u0440\u0451\u0442\u0441\u044F \u0438\u0437 git, \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043F\u0443\u0442\u0438 \u0438\u043B\u0438 URL",
14572
+ ambiguous_dependency_spec: "\u0437\u0430\u043A\u0440\u0435\u043F\u0438\u0442\u0435 \u0442\u043E\u0447\u043D\u044B\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 (== \u0432 requirements.txt) \u0438\u043B\u0438 \u0437\u0430\u043A\u043E\u043C\u043C\u0438\u0442\u044C\u0442\u0435 lockfile",
14573
+ unsupported_lockfile: "\u0441\u043E\u0437\u0434\u0430\u0439\u0442\u0435 \u0435\u0433\u043E \u0437\u0430\u043D\u043E\u0432\u043E \u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0435, \u043A\u043E\u0442\u043E\u0440\u044B\u0439 \u0447\u0438\u0442\u0430\u0435\u0442 Sentinello: npm install \u0441 npm 7 \u0438\u043B\u0438 \u043D\u043E\u0432\u0435\u0435 \u043B\u0438\u0431\u043E bun install --save-text-lockfile"
14574
+ }
14575
+ };
14576
+ function reasonFixHint(code, locale = "en") {
14577
+ return REASON_FIX_HINTS[locale][code] ?? null;
14578
+ }
14579
+
14463
14580
  // ../../packages/core/src/scan-state-text.ts
14464
14581
  function scanReasonLabel(reason, locale = "en") {
14465
14582
  if (reason.reasonCode === "not_yet_run") return NOT_YET_RUN_LABELS[locale];
@@ -14469,7 +14586,7 @@ function labelScanState(state, locale = "en") {
14469
14586
  return {
14470
14587
  state: state.state,
14471
14588
  reasons: state.reasons.map(function labelled(reason) {
14472
- return { ...reason, label: scanReasonLabel(reason, locale) };
14589
+ return { ...reason, label: scanReasonLabel(reason, locale), fixHint: reasonFixHint(reason.reasonCode, locale) };
14473
14590
  })
14474
14591
  };
14475
14592
  }
@@ -14503,14 +14620,15 @@ function groupScanReasons(reasons, locale = "en") {
14503
14620
  if (!group.subjects.includes(subject)) group.subjects.push(subject);
14504
14621
  continue;
14505
14622
  }
14506
- out.push({ reasonCode: reason.reasonCode, side: reason.side, label: scanReasonLabel(reason, locale), subjects: [subject] });
14623
+ out.push({ reasonCode: reason.reasonCode, side: reason.side, label: scanReasonLabel(reason, locale), subjects: [subject], fixHint: reasonFixHint(reason.reasonCode, locale) });
14507
14624
  }
14508
14625
  return out;
14509
14626
  }
14510
- function describeScanReasons(reasons, locale = "en") {
14627
+ function describeScanReasons(reasons, locale = "en", withFix = false) {
14511
14628
  return groupScanReasons(reasons, locale).map(function line(g) {
14512
14629
  if (g.side === null) return g.subjects.join(", ") + ": " + g.label;
14513
- return g.label + " (" + SCAN_STATE_SIDE_SHORT[g.side] + ")";
14630
+ const whose = g.label + " (" + SCAN_STATE_SIDE_SHORT[g.side] + ")";
14631
+ return withFix && g.fixHint !== null ? whose + ": " + g.fixHint : whose;
14514
14632
  }).join(" \xB7 ");
14515
14633
  }
14516
14634
  function describeGroupedReasonLong(group) {
@@ -14531,9 +14649,9 @@ function asError(err) {
14531
14649
  // ../../packages/core/src/advisory-rows.ts
14532
14650
  var OSV_NORMALIZER_VERSIONS = {
14533
14651
  npm: 8,
14534
- PyPI: 8,
14652
+ PyPI: 9,
14535
14653
  Go: 8,
14536
- "crates.io": 8,
14654
+ "crates.io": 9,
14537
14655
  RubyGems: 8
14538
14656
  };
14539
14657
  function osvNormalizerVersion(ecosystem) {
@@ -14659,7 +14777,7 @@ function escapeForMarkdown(value) {
14659
14777
  }
14660
14778
  function formatFinding(index, f) {
14661
14779
  const lines = [];
14662
- const headline = "`" + escapeForMarkdown(f.packageName) + "@" + escapeForMarkdown(f.installedVersion) + "` \u2014 " + f.severity;
14780
+ const headline = "`" + escapeForMarkdown(f.packageName) + "@" + escapeForMarkdown(f.installedVersion) + "` \u2014 " + (f.noticeKind ? "notice: " + f.noticeKind : f.severity);
14663
14781
  lines.push("### " + index + ". " + headline);
14664
14782
  lines.push("");
14665
14783
  lines.push("- **Ecosystem:** " + ecosystemLabel(f.ecosystem));
@@ -14736,8 +14854,16 @@ function wayOutLines(ecosystem, r, notRechecked) {
14736
14854
  for (const a of text.alternatives) lines.push(" - **Alternatives:** " + a);
14737
14855
  return lines;
14738
14856
  }
14857
+ function isNotice(f) {
14858
+ return Boolean(f.noticeKind);
14859
+ }
14860
+ function countNotices(findings) {
14861
+ return findings.filter(isNotice).length;
14862
+ }
14739
14863
  function sortForExport(findings) {
14740
14864
  return [...findings].sort(function bySeverityThenName(a, b) {
14865
+ const kind = Number(isNotice(a)) - Number(isNotice(b));
14866
+ if (kind !== 0) return kind;
14741
14867
  const sev = compareSeverity(a.severity, b.severity);
14742
14868
  if (sev !== 0) return sev;
14743
14869
  const nameCmp = a.packageName.localeCompare(b.packageName);
@@ -14745,13 +14871,14 @@ function sortForExport(findings) {
14745
14871
  return a.advisoryId.localeCompare(b.advisoryId);
14746
14872
  });
14747
14873
  }
14748
- function buildHeader(scope, generatedAt, count2, range) {
14874
+ function buildHeader(scope, generatedAt, count2, range, notices) {
14749
14875
  const title = "Sentinello advisory export \u2014 " + scopeTitle(scope);
14750
14876
  const subtitleParts = [];
14751
14877
  subtitleParts.push("Generated " + new Date(generatedAt).toISOString());
14752
14878
  {
14753
14879
  subtitleParts.push(count2 + " " + (count2 === 1 ? "finding" : "findings"));
14754
14880
  }
14881
+ if (notices > 0) subtitleParts.push(notices + " " + (notices === 1 ? "notice" : "notices") + ", not vulnerabilities");
14755
14882
  if (scope.kind === "project") {
14756
14883
  subtitleParts.push("project: `" + escapeForMarkdown(scope.projectPath) + "`");
14757
14884
  } else if (scope.kind === "library") {
@@ -14803,12 +14930,21 @@ function buildFindingsSection(findings, startIndex) {
14803
14930
  const out = [];
14804
14931
  out.push("## Findings");
14805
14932
  out.push("");
14806
- if (findings.length === 0) {
14933
+ if (!findings.some(function vulnerability(f) {
14934
+ return !isNotice(f);
14935
+ })) {
14807
14936
  out.push("_No current findings._");
14808
14937
  out.push("");
14809
- return out;
14810
14938
  }
14939
+ let noticesStarted = false;
14811
14940
  findings.forEach(function appendFinding(f, i) {
14941
+ if (isNotice(f) && !noticesStarted) {
14942
+ noticesStarted = true;
14943
+ out.push("## Notices");
14944
+ out.push("");
14945
+ out.push("Not vulnerabilities: the advisory says the package is unmaintained, unsound or worth knowing about, and there is no fix version to chase. Weigh them when you next touch the dependency.");
14946
+ out.push("");
14947
+ }
14812
14948
  out.push(formatFinding(startIndex + i + 1, f));
14813
14949
  out.push("");
14814
14950
  });
@@ -14817,7 +14953,8 @@ function buildFindingsSection(findings, startIndex) {
14817
14953
  function buildAdvisoryMarkdown(args) {
14818
14954
  const { scope, prompt, findings, generatedAt } = args;
14819
14955
  const sorted = sortForExport(findings);
14820
- const out = buildHeader(scope, generatedAt, sorted.length).concat(buildPromptSection(prompt)).concat(buildScanStateSection(args.scanStates ?? [])).concat(buildFindingsSection(sorted, 0));
14956
+ const notices = countNotices(sorted);
14957
+ const out = buildHeader(scope, generatedAt, sorted.length - notices, null, notices).concat(buildPromptSection(prompt)).concat(buildScanStateSection(args.scanStates ?? [])).concat(buildFindingsSection(sorted, 0));
14821
14958
  return out.join("\n");
14822
14959
  }
14823
14960
  function buildExportFilename(scope, generatedAt) {
@@ -34766,8 +34903,8 @@ function evaluableContains(ev, version2) {
34766
34903
 
34767
34904
  // ../../packages/scanners/src/npm-audit-parse.ts
34768
34905
  var NPM_AUDIT_SCANNER_NAME = "npm-audit";
34769
- var SEVERITY_VALUES = ["critical", "high", "moderate", "low", "info"];
34770
- var severitySchema = external_exports.enum(SEVERITY_VALUES).catch("moderate");
34906
+ var SEVERITY_VALUES = ["critical", "high", "moderate", "unrated", "low", "info"];
34907
+ var severitySchema = external_exports.enum(SEVERITY_VALUES).catch("unrated");
34771
34908
  var viaObjectSchema = external_exports.object({
34772
34909
  source: external_exports.number().int().optional(),
34773
34910
  name: external_exports.string().optional(),
@@ -34952,7 +35089,7 @@ function pickAdvisoryAliases(advisoryId, url2, githubAdvisoryId) {
34952
35089
  function pickSeverity(via, vuln) {
34953
35090
  if (via.severity) return via.severity;
34954
35091
  if (vuln.severity) return vuln.severity;
34955
- return "moderate";
35092
+ return "unrated";
34956
35093
  }
34957
35094
  function pickFixAvailability(fix) {
34958
35095
  if (fix === void 0 || fix === false) return { fixAvailable: false, fixVersion: null, fixName: null };
@@ -35074,7 +35211,7 @@ function normalizePnpmAuditOutput(parsed, classifier) {
35074
35211
  const adv = advisories[idKey];
35075
35212
  if (!adv) continue;
35076
35213
  const advisoryId = pickPnpmAdvisoryId(adv, idKey);
35077
- const severity = adv.severity || "moderate";
35214
+ const severity = adv.severity || "unrated";
35078
35215
  const patched = adv.patched_versions || null;
35079
35216
  const recommendation = adv.recommendation || null;
35080
35217
  const vulnRange = adv.vulnerable_versions || "";
@@ -35793,6 +35930,141 @@ function unauditable(details) {
35793
35930
  return { status: "unauditable", ecosystem: GO_ECOSYSTEM, reasonCode: "ambiguous_dependency_spec", details };
35794
35931
  }
35795
35932
  var NPM_ECOSYSTEM = "npm";
35933
+ async function parseBunLock(absolutePath, manifestPath) {
35934
+ let doc;
35935
+ try {
35936
+ doc = parseJsonc(await promises.readFile(absolutePath, "utf8"));
35937
+ } catch {
35938
+ return { status: "unauditable", ecosystem: NPM_ECOSYSTEM, reasonCode: "unsupported_lockfile", details: ["could not read " + manifestPath] };
35939
+ }
35940
+ const packages = recordOf(recordOf(doc).packages);
35941
+ const workspaces = recordOf(recordOf(doc).workspaces);
35942
+ const entries = /* @__PURE__ */ new Map();
35943
+ const cannotAudit = [];
35944
+ for (const key of Object.keys(packages)) {
35945
+ const entry = readEntry(key, packages[key]);
35946
+ if (entry === null) cannotAudit.push(key);
35947
+ else if (!entry.spec.startsWith("workspace:")) entries.set(key, entry);
35948
+ }
35949
+ const nodes = [];
35950
+ const edges = [];
35951
+ const auditable = /* @__PURE__ */ new Set();
35952
+ for (const entry of entries.values()) {
35953
+ nodes.push({ id: entry.key, name: entry.name, version: entry.spec });
35954
+ if (entry.spec.includes(":")) cannotAudit.push(entry.name + "@" + entry.spec);
35955
+ else auditable.add(entry.key);
35956
+ const chain = packageChain(entry.key);
35957
+ addEdges(entry.key, chain, entry.meta.dependencies, "prod", entries, edges);
35958
+ addEdges(entry.key, chain, entry.meta.optionalDependencies, "optional", entries, edges);
35959
+ addEdges(entry.key, chain, entry.meta.peerDependencies, "peer", entries, edges);
35960
+ }
35961
+ const roots = [];
35962
+ for (const path of Object.keys(workspaces)) {
35963
+ const workspace = recordOf(workspaces[path]);
35964
+ const importer = path === "" ? "." : path;
35965
+ const chain = typeof workspace.name === "string" ? [workspace.name] : [];
35966
+ addRoots(importer, chain, workspace.dependencies, "prod", entries, roots);
35967
+ addRoots(importer, chain, workspace.peerDependencies, "prod", entries, roots);
35968
+ addRoots(importer, chain, workspace.optionalDependencies, "optional", entries, roots);
35969
+ addRoots(importer, chain, workspace.devDependencies, "dev", entries, roots);
35970
+ }
35971
+ const graph = graphFromLock({
35972
+ ecosystem: NPM_ECOSYSTEM,
35973
+ manifestPath,
35974
+ nodes,
35975
+ edges,
35976
+ roots,
35977
+ auditable(nodeId) {
35978
+ return auditable.has(nodeId);
35979
+ }
35980
+ });
35981
+ if (cannotAudit.length === 0) return { status: "ok", ecosystem: NPM_ECOSYSTEM, graph };
35982
+ return {
35983
+ status: "partial",
35984
+ ecosystem: NPM_ECOSYSTEM,
35985
+ graph,
35986
+ reasonCode: "partial_dependency_graph",
35987
+ details: [cannotAudit.length + " packages from git, local path or URL sources cannot be audited: " + cannotAudit.sort().join(", ")]
35988
+ };
35989
+ }
35990
+ function readEntry(key, value) {
35991
+ if (!Array.isArray(value) || typeof value[0] !== "string") return null;
35992
+ const at = value[0].indexOf("@", 1);
35993
+ if (at < 0 || at === value[0].length - 1) return null;
35994
+ const meta3 = value.slice(1).find(function isMeta(part) {
35995
+ return part !== null && typeof part === "object" && !Array.isArray(part);
35996
+ });
35997
+ return { key, name: value[0].slice(0, at), spec: value[0].slice(at + 1), meta: meta3 ?? {} };
35998
+ }
35999
+ function packageChain(key) {
36000
+ const chain = [];
36001
+ const parts = key.split("/");
36002
+ for (let i = 0; i < parts.length; i++) {
36003
+ const part = parts[i];
36004
+ if (part.startsWith("@") && i + 1 < parts.length) {
36005
+ chain.push(part + "/" + parts[i + 1]);
36006
+ i += 1;
36007
+ } else {
36008
+ chain.push(part);
36009
+ }
36010
+ }
36011
+ return chain;
36012
+ }
36013
+ function resolveFrom(chain, child, entries) {
36014
+ for (let depth = chain.length; depth >= 0; depth--) {
36015
+ const key = [...chain.slice(0, depth), child].join("/");
36016
+ if (entries.has(key)) return key;
36017
+ }
36018
+ return null;
36019
+ }
36020
+ function addEdges(from, chain, deps, kind, entries, out) {
36021
+ for (const child of Object.keys(deps ?? {})) {
36022
+ const to = resolveFrom(chain, child, entries);
36023
+ if (to !== null) out.push({ from, to, kind });
36024
+ }
36025
+ }
36026
+ function addRoots(importer, chain, deps, kind, entries, out) {
36027
+ for (const child of Object.keys(deps ?? {})) {
36028
+ const nodeId = resolveFrom(chain, child, entries);
36029
+ if (nodeId !== null) out.push({ importer, nodeId, kind });
36030
+ }
36031
+ }
36032
+ function recordOf(value) {
36033
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
36034
+ }
36035
+ function parseJsonc(text) {
36036
+ let out = "";
36037
+ let i = 0;
36038
+ while (i < text.length) {
36039
+ const c = text[i];
36040
+ if (c === '"') {
36041
+ const end = stringEnd(text, i);
36042
+ out += text.slice(i, end);
36043
+ i = end;
36044
+ } else if (c === "/" && text[i + 1] === "/") {
36045
+ const newline = text.indexOf("\n", i);
36046
+ i = newline < 0 ? text.length : newline;
36047
+ } else if (c === "/" && text[i + 1] === "*") {
36048
+ const close = text.indexOf("*/", i + 2);
36049
+ i = close < 0 ? text.length : close + 2;
36050
+ } else {
36051
+ if (c === "}" || c === "]") out = out.replace(/,\s*$/, "");
36052
+ out += c;
36053
+ i += 1;
36054
+ }
36055
+ }
36056
+ return JSON.parse(out);
36057
+ }
36058
+ function stringEnd(text, start) {
36059
+ let i = start + 1;
36060
+ while (i < text.length) {
36061
+ if (text[i] === "\\") i += 2;
36062
+ else if (text[i] === '"') return i + 1;
36063
+ else i += 1;
36064
+ }
36065
+ return text.length;
36066
+ }
36067
+ var NPM_ECOSYSTEM2 = "npm";
35796
36068
  async function parseNpmLock(projectPath, absolutePath, manifestPath) {
35797
36069
  let text;
35798
36070
  try {
@@ -35808,6 +36080,7 @@ async function parseNpmLock(projectPath, absolutePath, manifestPath) {
35808
36080
  }
35809
36081
  if (!parsed || typeof parsed !== "object") return null;
35810
36082
  const doc = parsed;
36083
+ if (doc.lockfileVersion === 1) return null;
35811
36084
  const packages = doc.packages || {};
35812
36085
  const direct = await readDirectDeps(projectPath);
35813
36086
  const out = [];
@@ -35823,7 +36096,7 @@ async function parseNpmLock(projectPath, absolutePath, manifestPath) {
35823
36096
  if (direct.prod.has(name)) isProd = true;
35824
36097
  if (direct.dev.has(name)) isDev = true;
35825
36098
  out.push({
35826
- ecosystem: NPM_ECOSYSTEM,
36099
+ ecosystem: NPM_ECOSYSTEM2,
35827
36100
  name,
35828
36101
  version: entry.version,
35829
36102
  scope: { isProd, isDev, isOptional: entry.optional === true || entry.devOptional === true },
@@ -35833,6 +36106,13 @@ async function parseNpmLock(projectPath, absolutePath, manifestPath) {
35833
36106
  }
35834
36107
  return makeGraph(out, doc.packages ? buildNodeGraph(packages) : null);
35835
36108
  }
36109
+ async function isNpmLockV1(absolutePath) {
36110
+ try {
36111
+ return JSON.parse(await promises.readFile(absolutePath, "utf8"))?.lockfileVersion === 1;
36112
+ } catch {
36113
+ return false;
36114
+ }
36115
+ }
35836
36116
  function buildNodeGraph(packages) {
35837
36117
  const nodes = [];
35838
36118
  const edges = [];
@@ -35842,37 +36122,37 @@ function buildNodeGraph(packages) {
35842
36122
  if (!entry) continue;
35843
36123
  if (!isNodePath(path)) {
35844
36124
  const importer = path === "" ? "." : path;
35845
- addRoots(importer, path, entry.dependencies, "prod", packages, roots);
35846
- addRoots(importer, path, entry.peerDependencies, "prod", packages, roots);
35847
- addRoots(importer, path, entry.optionalDependencies, "optional", packages, roots);
35848
- addRoots(importer, path, entry.devDependencies, "dev", packages, roots);
36125
+ addRoots2(importer, path, entry.dependencies, "prod", packages, roots);
36126
+ addRoots2(importer, path, entry.peerDependencies, "prod", packages, roots);
36127
+ addRoots2(importer, path, entry.optionalDependencies, "optional", packages, roots);
36128
+ addRoots2(importer, path, entry.devDependencies, "dev", packages, roots);
35849
36129
  continue;
35850
36130
  }
35851
36131
  const name = entry.name || nameFromNodePath(path);
35852
36132
  if (entry.link === true || !entry.version || !name) continue;
35853
36133
  nodes.push({ id: path, name, version: entry.version });
35854
- addEdges(path, entry.dependencies, "prod", packages, edges);
35855
- addEdges(path, entry.optionalDependencies, "optional", packages, edges);
35856
- addEdges(path, entry.peerDependencies, "peer", packages, edges);
36134
+ addEdges2(path, entry.dependencies, "prod", packages, edges);
36135
+ addEdges2(path, entry.optionalDependencies, "optional", packages, edges);
36136
+ addEdges2(path, entry.peerDependencies, "peer", packages, edges);
35857
36137
  }
35858
36138
  return { nodes, edges, roots };
35859
36139
  }
35860
36140
  function isNodePath(path) {
35861
36141
  return path.startsWith("node_modules/") || path.includes("/node_modules/");
35862
36142
  }
35863
- function addRoots(importer, from, deps, kind, packages, out) {
36143
+ function addRoots2(importer, from, deps, kind, packages, out) {
35864
36144
  for (const child of Object.keys(deps || {})) {
35865
- const nodeId = resolveFrom(from, child, packages);
36145
+ const nodeId = resolveFrom2(from, child, packages);
35866
36146
  if (nodeId !== null) out.push({ importer, nodeId, kind });
35867
36147
  }
35868
36148
  }
35869
- function addEdges(from, deps, kind, packages, out) {
36149
+ function addEdges2(from, deps, kind, packages, out) {
35870
36150
  for (const child of Object.keys(deps || {})) {
35871
- const to = resolveFrom(from, child, packages);
36151
+ const to = resolveFrom2(from, child, packages);
35872
36152
  if (to !== null) out.push({ from, to, kind });
35873
36153
  }
35874
36154
  }
35875
- function resolveFrom(location, child, packages) {
36155
+ function resolveFrom2(location, child, packages) {
35876
36156
  let base = location;
35877
36157
  for (; ; ) {
35878
36158
  const candidate = (base === "" ? "" : base + "/") + "node_modules/" + child;
@@ -38990,7 +39270,7 @@ var {
38990
39270
  } = yaml;
38991
39271
 
38992
39272
  // ../../packages/scanners/src/resolver/pnpm.ts
38993
- var NPM_ECOSYSTEM2 = "npm";
39273
+ var NPM_ECOSYSTEM3 = "npm";
38994
39274
  async function parsePnpmLock(absolutePath, manifestPath) {
38995
39275
  let text;
38996
39276
  try {
@@ -39063,7 +39343,7 @@ function parsePnpmV9(root, manifestPath) {
39063
39343
  existing.depPaths.push(key);
39064
39344
  } else {
39065
39345
  byId.set(id, {
39066
- ecosystem: NPM_ECOSYSTEM2,
39346
+ ecosystem: NPM_ECOSYSTEM3,
39067
39347
  name: parsed.name,
39068
39348
  version: parsed.version,
39069
39349
  scope: { isProd, isDev, isOptional },
@@ -39094,7 +39374,7 @@ function parsePnpmLegacy(root, manifestPath) {
39094
39374
  const version2 = entry.version || parsed.version;
39095
39375
  const isDev = entry.dev === true;
39096
39376
  out.push({
39097
- ecosystem: NPM_ECOSYSTEM2,
39377
+ ecosystem: NPM_ECOSYSTEM3,
39098
39378
  name: parsed.name,
39099
39379
  version: version2,
39100
39380
  scope: { isProd: !isDev, isDev, isOptional: entry.optional === true },
@@ -39825,6 +40105,16 @@ function unauditable3(reasonCode, details) {
39825
40105
  var CRATES_ECOSYSTEM = "crates.io";
39826
40106
  var CRATES_IO_SOURCES = ["registry+https://github.com/rust-lang/crates.io-index", "sparse+https://index.crates.io/"];
39827
40107
  var MAX_MANIFESTS = 1e3;
40108
+ function ownCratesOfLock(text) {
40109
+ return parseArrayOfTables(text, "package").flatMap(function ownName(t) {
40110
+ const name = tomlString(t.name);
40111
+ const source = tomlString(t.source);
40112
+ return name !== null && (source === null || source.length === 0) ? [name] : [];
40113
+ });
40114
+ }
40115
+ function crateNameOfManifest(text) {
40116
+ return tomlString(tomlTable(parseTomlDocument(text).package)?.name);
40117
+ }
39828
40118
  async function parseCargoLock(projectPath, absolutePath, manifestPath) {
39829
40119
  let text;
39830
40120
  try {
@@ -40196,11 +40486,19 @@ async function resolveManifest(projectPath, manifest) {
40196
40486
  if (lockless !== null) return { status: "unauditable", ecosystem, reasonCode: "no_lockfile", details: [lockless] };
40197
40487
  if (ecosystem === "npm") {
40198
40488
  if (kind === "package-lock.json") {
40199
- return wrapNpm(ecosystem, await parseNpmLock(projectPath, absolutePath, manifestPath), kind);
40489
+ const graph = await parseNpmLock(projectPath, absolutePath, manifestPath);
40490
+ if (graph === null && await isNpmLockV1(absolutePath)) {
40491
+ return { status: "unauditable", ecosystem, reasonCode: "unsupported_lockfile", details: [manifestPath + " is lockfileVersion 1, which lists no packages to read: run npm install with npm 7 or later to upgrade it"] };
40492
+ }
40493
+ return wrapNpm(ecosystem, graph, kind);
40200
40494
  }
40201
40495
  if (kind === "pnpm-lock.yaml") {
40202
40496
  return wrapNpm(ecosystem, await parsePnpmLock(absolutePath, manifestPath), kind);
40203
40497
  }
40498
+ if (kind === "bun.lock") return parseBunLock(absolutePath, manifestPath);
40499
+ if (kind === "bun.lockb") {
40500
+ return { status: "unauditable", ecosystem, reasonCode: "unsupported_lockfile", details: [manifestPath + " is Bun's binary lockfile, which cannot be read: run bun install --save-text-lockfile to write bun.lock"] };
40501
+ }
40204
40502
  return { status: "unauditable", ecosystem, reasonCode: "unsupported_lockfile", details: [kind + " is not a supported JavaScript lockfile format"] };
40205
40503
  }
40206
40504
  if (ecosystem === "PyPI") return parsePythonLock(projectPath, kind, absolutePath, manifestPath);
@@ -40255,7 +40553,9 @@ var import_ignore = __toESM(require_ignore());
40255
40553
  var LOCKFILE_TO_PM = {
40256
40554
  "pnpm-lock.yaml": "pnpm",
40257
40555
  "package-lock.json": "npm",
40258
- "yarn.lock": "yarn"
40556
+ "yarn.lock": "yarn",
40557
+ "bun.lock": "bun",
40558
+ "bun.lockb": "bun"
40259
40559
  };
40260
40560
  var ALWAYS_SKIP = /* @__PURE__ */ new Set(["node_modules", ".git"]);
40261
40561
  var MANIFEST_SKIP = /* @__PURE__ */ new Set(["node_modules", "vendor", ".venv", "venv", "target", "Pods", "build", "dist"]);
@@ -40277,6 +40577,7 @@ function discoverProjectsInTree(options) {
40277
40577
  excludeMatcher,
40278
40578
  hasExcludes: Boolean(options.excludes && options.excludes.length > 0),
40279
40579
  layers,
40580
+ readIgnoreFiles: true,
40280
40581
  onSkip: options.onSkip,
40281
40582
  onError: options.onError,
40282
40583
  ecosystems,
@@ -40296,7 +40597,7 @@ function walk(state) {
40296
40597
  const manifestsOff = owner === state.owner && state.manifestsOff;
40297
40598
  if (owner?.npm && state.subEcosystems.length === 0) return;
40298
40599
  if (state.maxDepth !== null && state.depth >= state.maxDepth) return;
40299
- const localLayer = loadIgnoreLayer(state.currentDir);
40600
+ const localLayer = state.readIgnoreFiles ? loadIgnoreLayer(state.currentDir) : null;
40300
40601
  const layers = localLayer ? state.layers.concat([localLayer]) : state.layers;
40301
40602
  for (const entry of readEntries(state.currentDir, state.onError)) {
40302
40603
  if (!entry.isDirectory()) continue;
@@ -40360,6 +40661,7 @@ function addManifests(project, found) {
40360
40661
  }
40361
40662
  }
40362
40663
  function finishProject(project, ecosystems) {
40664
+ project.manifests = withoutLockedCrates(project);
40363
40665
  project.manifests.sort(function byDirectory(a, b) {
40364
40666
  return manifestDirOf(a.path).localeCompare(manifestDirOf(b.path));
40365
40667
  });
@@ -40371,6 +40673,30 @@ function finishProject(project, ecosystems) {
40371
40673
  return eco.id;
40372
40674
  });
40373
40675
  }
40676
+ function withoutLockedCrates(project) {
40677
+ const bare = project.manifests.filter(function isBare(m) {
40678
+ return m.kind === "Cargo.toml";
40679
+ });
40680
+ if (bare.length === 0) return project.manifests;
40681
+ const locked = /* @__PURE__ */ new Set();
40682
+ for (const m of project.manifests) {
40683
+ if (m.kind !== "Cargo.lock") continue;
40684
+ for (const name of ownCratesOfLock(readFileOrEmpty(path.join(project.absolutePath, m.path)))) locked.add(name);
40685
+ }
40686
+ if (locked.size === 0) return project.manifests;
40687
+ return project.manifests.filter(function uncovered(m) {
40688
+ if (m.kind !== "Cargo.toml") return true;
40689
+ const name = crateNameOfManifest(readFileOrEmpty(path.join(project.absolutePath, m.path)));
40690
+ return name === null || !locked.has(name);
40691
+ });
40692
+ }
40693
+ function readFileOrEmpty(path) {
40694
+ try {
40695
+ return fs.readFileSync(path, "utf8");
40696
+ } catch {
40697
+ return "";
40698
+ }
40699
+ }
40374
40700
  function isNpm(eco) {
40375
40701
  return eco.id === "npm";
40376
40702
  }
@@ -40628,7 +40954,8 @@ function buildFinding(pkg2, advisory, severity, fixVersion, vulnerableRange, aff
40628
40954
  depPath: pkg2.depPaths,
40629
40955
  isProd: pkg2.scope.isProd,
40630
40956
  isDev: pkg2.scope.isDev,
40631
- aliases: advisory.aliases
40957
+ aliases: advisory.aliases,
40958
+ noticeKind: advisory.noticeKind ?? null
40632
40959
  };
40633
40960
  }
40634
40961
  function rangesToDisplay(ranges, exactVersions) {
@@ -40638,14 +40965,14 @@ function rangesToDisplay(ranges, exactVersions) {
40638
40965
  return parts.join(" || ");
40639
40966
  }
40640
40967
  function mapSeverity(severity) {
40641
- if (!severity) return "moderate";
40968
+ if (!severity) return "unrated";
40642
40969
  const s = String(severity).trim().toLowerCase();
40643
40970
  if (s === "critical") return "critical";
40644
40971
  if (s === "high") return "high";
40645
40972
  if (s === "moderate" || s === "medium") return "moderate";
40646
40973
  if (s === "low") return "low";
40647
40974
  if (s === "info" || s === "none") return "info";
40648
- return "moderate";
40975
+ return "unrated";
40649
40976
  }
40650
40977
 
40651
40978
  // ../../packages/scanners/src/osv.ts
@@ -40680,7 +41007,13 @@ function createOsvScanner(deps) {
40680
41007
  durationMs: Date.now() - startedAt
40681
41008
  };
40682
41009
  }
40683
- return { name: OSV_SCANNER_NAME, scan };
41010
+ return {
41011
+ name: OSV_SCANNER_NAME,
41012
+ scan,
41013
+ aliasEvidence: function aliasEvidence(ecosystem, packageNames) {
41014
+ return deps.isSeeded(ecosystem) ? deps.lookup(ecosystem, packageNames) : null;
41015
+ }
41016
+ };
40684
41017
  }
40685
41018
  function matchPackages(packages, lookup, isSeeded2, isEnabled) {
40686
41019
  const findings = [];
@@ -40717,7 +41050,8 @@ function toCanonicalAdvisory(packageName, ecosystem, advisory) {
40717
41050
  severity: advisory.severity,
40718
41051
  summary: advisory.summary,
40719
41052
  url: advisory.url,
40720
- withdrawn: advisory.withdrawn
41053
+ withdrawn: advisory.withdrawn,
41054
+ noticeKind: advisory.noticeKind
40721
41055
  };
40722
41056
  }
40723
41057
  function groupByEcosystem(packages) {
@@ -40753,6 +41087,64 @@ function unauditable5(reasonCode, message, startedAt) {
40753
41087
  };
40754
41088
  }
40755
41089
 
41090
+ // ../../packages/scanners/src/withdrawn.ts
41091
+ function stampWithdrawn(advisories, links) {
41092
+ return advisories.map(function stamp(advisory) {
41093
+ const withdrawn = withdrawnAt(advisory, links);
41094
+ if (withdrawn !== null) return { ...advisory, withdrawn };
41095
+ const osvRecords = liveLinks(advisory, links);
41096
+ return osvRecords.length === 0 ? advisory : { ...advisory, osvRecords };
41097
+ });
41098
+ }
41099
+ function stampWithdrawnByPackage(byPackage, linksByPackage) {
41100
+ const out = /* @__PURE__ */ new Map();
41101
+ for (const [name, advisories] of byPackage.entries()) {
41102
+ out.set(name, stampWithdrawn(advisories, linksByPackage.get(name) ?? []));
41103
+ }
41104
+ return out;
41105
+ }
41106
+ function liveLinks(advisory, links) {
41107
+ const identity = /* @__PURE__ */ new Set([advisory.advisoryId, ...advisory.aliases]);
41108
+ return links.filter(function live(link2) {
41109
+ return link2.withdrawn === null && sharesIdentifier(identity, link2);
41110
+ });
41111
+ }
41112
+ function clearedByOsv(records, version2, comparator, acceptedRangeTypes) {
41113
+ if (records === void 0 || records.length === 0) return false;
41114
+ if (comparator.normalize(version2) === null) return false;
41115
+ return !records.some(function contains(record2) {
41116
+ if (record2.rangesDiscarded === true) return true;
41117
+ if (record2.ranges.length === 0 && record2.versions.length === 0) return true;
41118
+ if (record2.versions.includes(version2)) return true;
41119
+ if (record2.ranges.some(function unreadable(range) {
41120
+ return isRefused(range) || range.type === void 0 || !acceptedRangeTypes.includes(range.type);
41121
+ })) return true;
41122
+ const exact = /* @__PURE__ */ new Set();
41123
+ for (const raw of record2.versions) {
41124
+ const normalized = comparator.normalize(raw);
41125
+ if (normalized === null) return true;
41126
+ exact.add(normalized);
41127
+ }
41128
+ return versionInSet(version2, record2.ranges, exact, comparator, void 0);
41129
+ });
41130
+ }
41131
+ function withdrawnAt(advisory, links) {
41132
+ const identity = /* @__PURE__ */ new Set([advisory.advisoryId, ...advisory.aliases]);
41133
+ let latest = null;
41134
+ for (const link2 of links) {
41135
+ if (!sharesIdentifier(identity, link2)) continue;
41136
+ if (link2.withdrawn === null) return null;
41137
+ if (latest === null || link2.withdrawn > latest) latest = link2.withdrawn;
41138
+ }
41139
+ return latest;
41140
+ }
41141
+ function sharesIdentifier(identity, link2) {
41142
+ if (identity.has(link2.advisoryId)) return true;
41143
+ return link2.aliases.some(function inIdentity(alias) {
41144
+ return identity.has(alias);
41145
+ });
41146
+ }
41147
+
40756
41148
  // ../../packages/scanners/src/gemnasium.ts
40757
41149
  var GEMNASIUM_SCANNER_NAME = "gemnasium";
40758
41150
  function createGemnasiumScanner(deps) {
@@ -40799,7 +41191,13 @@ function createGemnasiumScanner(deps) {
40799
41191
  durationMs: Date.now() - startedAt
40800
41192
  };
40801
41193
  }
40802
- return { name: GEMNASIUM_SCANNER_NAME, scan };
41194
+ return {
41195
+ name: GEMNASIUM_SCANNER_NAME,
41196
+ scan,
41197
+ aliasEvidence: function aliasEvidence(ecosystem, packageNames) {
41198
+ return deps.isSeeded() ? deps.lookup(ecosystem, packageNames) : null;
41199
+ }
41200
+ };
40803
41201
  }
40804
41202
  function matchPackages2(packages, lookup, isEnabled) {
40805
41203
  const findings = [];
@@ -40815,7 +41213,13 @@ function matchPackages2(packages, lookup, isEnabled) {
40815
41213
  return toCanonicalAdvisory2(name, ecosystem, advisory);
40816
41214
  }));
40817
41215
  }
40818
- for (const finding of matchAdvisories(pkgs, byPackage, comparator)) findings.push(finding);
41216
+ const acceptedRangeTypes = acceptedRangeTypesForEcosystem(ecosystem);
41217
+ for (const finding of matchAdvisories(pkgs, byPackage, comparator)) {
41218
+ const advisory = byPackageRaw.get(finding.packageName)?.find(function same(a) {
41219
+ return a.advisoryId === finding.advisoryId;
41220
+ });
41221
+ if (!clearedByOsv(advisory?.osvRecords, finding.installedVersion, comparator, acceptedRangeTypes)) findings.push(finding);
41222
+ }
40819
41223
  }
40820
41224
  return findings;
40821
41225
  }
@@ -40870,37 +41274,6 @@ function unauditable6(reasonCode, message, startedAt) {
40870
41274
  };
40871
41275
  }
40872
41276
 
40873
- // ../../packages/scanners/src/withdrawn.ts
40874
- function stampWithdrawn(advisories, links) {
40875
- return advisories.map(function stamp(advisory) {
40876
- const withdrawn = withdrawnAt(advisory, links);
40877
- return withdrawn === null ? advisory : { ...advisory, withdrawn };
40878
- });
40879
- }
40880
- function stampWithdrawnByPackage(byPackage, linksByPackage) {
40881
- const out = /* @__PURE__ */ new Map();
40882
- for (const [name, advisories] of byPackage.entries()) {
40883
- out.set(name, stampWithdrawn(advisories, linksByPackage.get(name) ?? []));
40884
- }
40885
- return out;
40886
- }
40887
- function withdrawnAt(advisory, links) {
40888
- const identity = /* @__PURE__ */ new Set([advisory.advisoryId, ...advisory.aliases]);
40889
- let latest = null;
40890
- for (const link2 of links) {
40891
- if (!sharesIdentifier(identity, link2)) continue;
40892
- if (link2.withdrawn === null) return null;
40893
- if (latest === null || link2.withdrawn > latest) latest = link2.withdrawn;
40894
- }
40895
- return latest;
40896
- }
40897
- function sharesIdentifier(identity, link2) {
40898
- if (identity.has(link2.advisoryId)) return true;
40899
- return link2.aliases.some(function inIdentity(alias) {
40900
- return identity.has(alias);
40901
- });
40902
- }
40903
-
40904
41277
  // ../../packages/scanners/src/engine/reconcile.ts
40905
41278
  function findingIdentityKeys(finding) {
40906
41279
  const keys = [finding.advisoryId.toLowerCase()];
@@ -40922,6 +41295,9 @@ function reconcileAgainstReported(findings, reportedByPackage, source) {
40922
41295
  const target = firstReported(existing, keys);
40923
41296
  if (target && target.source === source) {
40924
41297
  foldInstallation(target.finding, finding);
41298
+ target.severity = maxSeverity([target.severity, finding.severity]);
41299
+ target.finding.severity = escalatedSeverity(target.severity, target.finding.corroborations ?? []);
41300
+ clearNoticeWhenReal(target.finding, finding);
40925
41301
  target.evidence.push(finding.fixInputs);
40926
41302
  continue;
40927
41303
  }
@@ -40934,6 +41310,7 @@ function reconcileAgainstReported(findings, reportedByPackage, source) {
40934
41310
  })) attached.push(by);
40935
41311
  target.finding.corroborations = attached;
40936
41312
  target.finding.severity = escalatedSeverity(target.severity, attached);
41313
+ clearNoticeWhenReal(target.finding, finding);
40937
41314
  target.evidence.push(finding.fixInputs);
40938
41315
  continue;
40939
41316
  }
@@ -40973,6 +41350,9 @@ function foldInstallation(survivor, copy) {
40973
41350
  function installationsOf(finding) {
40974
41351
  return finding.installations ? finding.installations.slice() : [];
40975
41352
  }
41353
+ function clearNoticeWhenReal(survivor, other) {
41354
+ if (!other.noticeKind) survivor.noticeKind = null;
41355
+ }
40976
41356
  function firstReported(existing, keys) {
40977
41357
  for (const key of keys) {
40978
41358
  const found = existing.get(key);
@@ -41169,6 +41549,98 @@ async function openDownloadStream(url2, onProgress, options) {
41169
41549
  return { stream, contentLength, lastModified: response.headers["last-modified"] ?? null };
41170
41550
  }
41171
41551
 
41552
+ // ../../packages/feeds/src/gemnasium/cvss.ts
41553
+ var V3_AV = { N: 0.85, A: 0.62, L: 0.55, P: 0.2 };
41554
+ var V3_AC = { L: 0.77, H: 0.44 };
41555
+ var V3_UI = { N: 0.85, R: 0.62 };
41556
+ var V3_CIA = { H: 0.56, L: 0.22, N: 0 };
41557
+ var V3_PR_UNCHANGED = { N: 0.85, L: 0.62, H: 0.27 };
41558
+ var V3_PR_CHANGED = { N: 0.85, L: 0.68, H: 0.5 };
41559
+ var V2_AV = { L: 0.395, A: 0.646, N: 1 };
41560
+ var V2_AC = { H: 0.35, M: 0.61, L: 0.71 };
41561
+ var V2_AU = { M: 0.45, S: 0.56, N: 0.704 };
41562
+ var V2_CIA = { N: 0, P: 0.275, C: 0.66 };
41563
+ function severityFromCvss(cvssV3, cvssV2) {
41564
+ const v3 = parseVector(cvssV3);
41565
+ if (v3) {
41566
+ const score = baseScoreV3(v3);
41567
+ if (score !== null) return bucketV3(score);
41568
+ }
41569
+ const v2 = parseVector(cvssV2);
41570
+ if (v2) {
41571
+ const score = baseScoreV2(v2);
41572
+ if (score !== null) return bucketV2(score);
41573
+ }
41574
+ return null;
41575
+ }
41576
+ function parseVector(vector) {
41577
+ if (typeof vector !== "string" || vector.trim().length === 0) return null;
41578
+ const out = {};
41579
+ for (const part of vector.trim().split("/")) {
41580
+ const colon = part.indexOf(":");
41581
+ if (colon <= 0) continue;
41582
+ const key = part.slice(0, colon).trim();
41583
+ const value = part.slice(colon + 1).trim().toUpperCase();
41584
+ if (key === "CVSS") continue;
41585
+ out[key] = value;
41586
+ }
41587
+ return Object.keys(out).length > 0 ? out : null;
41588
+ }
41589
+ function weight(table, key) {
41590
+ if (key === void 0) return void 0;
41591
+ return table[key];
41592
+ }
41593
+ function baseScoreV3(m) {
41594
+ const av = weight(V3_AV, m.AV);
41595
+ const ac = weight(V3_AC, m.AC);
41596
+ const ui = weight(V3_UI, m.UI);
41597
+ const c = weight(V3_CIA, m.C);
41598
+ const i = weight(V3_CIA, m.I);
41599
+ const a = weight(V3_CIA, m.A);
41600
+ const changed = m.S === "C";
41601
+ const pr = weight(changed ? V3_PR_CHANGED : V3_PR_UNCHANGED, m.PR);
41602
+ if (av === void 0 || ac === void 0 || ui === void 0 || pr === void 0) return null;
41603
+ if (c === void 0 || i === void 0 || a === void 0) return null;
41604
+ const iss = 1 - (1 - c) * (1 - i) * (1 - a);
41605
+ const impact = changed ? 7.52 * (iss - 0.029) - 3.25 * Math.pow(iss - 0.02, 15) : 6.42 * iss;
41606
+ const exploitability = 8.22 * av * ac * pr * ui;
41607
+ if (impact <= 0) return 0;
41608
+ const raw = changed ? 1.08 * (impact + exploitability) : impact + exploitability;
41609
+ return roundUpV3(Math.min(raw, 10));
41610
+ }
41611
+ function roundUpV3(value) {
41612
+ const intInput = Math.round(value * 1e5);
41613
+ if (intInput % 1e4 === 0) return intInput / 1e5;
41614
+ return (Math.floor(intInput / 1e4) + 1) / 10;
41615
+ }
41616
+ function bucketV3(score) {
41617
+ if (score === 0) return "info";
41618
+ if (score < 4) return "low";
41619
+ if (score < 7) return "moderate";
41620
+ if (score < 9) return "high";
41621
+ return "critical";
41622
+ }
41623
+ function baseScoreV2(m) {
41624
+ const av = weight(V2_AV, m.AV);
41625
+ const ac = weight(V2_AC, m.AC);
41626
+ const au = weight(V2_AU, m.Au) ?? weight(V2_AU, m.AU);
41627
+ const c = weight(V2_CIA, m.C);
41628
+ const i = weight(V2_CIA, m.I);
41629
+ const a = weight(V2_CIA, m.A);
41630
+ if (av === void 0 || ac === void 0 || au === void 0) return null;
41631
+ if (c === void 0 || i === void 0 || a === void 0) return null;
41632
+ const impact = 10.41 * (1 - (1 - c) * (1 - i) * (1 - a));
41633
+ const exploitability = 20 * av * ac * au;
41634
+ const f = impact === 0 ? 0 : 1.176;
41635
+ const base = (0.6 * impact + 0.4 * exploitability - 1.5) * f;
41636
+ return Math.round(base * 10) / 10;
41637
+ }
41638
+ function bucketV2(score) {
41639
+ if (score < 4) return "low";
41640
+ if (score < 7) return "moderate";
41641
+ return "high";
41642
+ }
41643
+
41172
41644
  // ../../packages/feeds/src/osv/normalize.ts
41173
41645
  function normalizeOsvRecord(record2, ecosystem) {
41174
41646
  if (!record2 || typeof record2 !== "object") return [];
@@ -41193,10 +41665,14 @@ function normalizeOsvRecord(record2, ecosystem) {
41193
41665
  if (!packageName) continue;
41194
41666
  const ranges = extractRanges(affected.ranges, affected.database_specific?.last_known_affected_version_range, comparator);
41195
41667
  const versions = extractVersions(affected.versions);
41668
+ const noticeKind = noticeKindOf(r.database_specific?.informational) ?? noticeKindOf(affected.database_specific?.informational);
41669
+ const rangesDiscarded = Array.isArray(affected.ranges) && !affected.ranges.every(isReadableRange);
41196
41670
  const existing = byPackage.get(packageName);
41197
41671
  if (existing) {
41198
41672
  for (const range of ranges) existing.ranges.push(range);
41199
41673
  for (const version2 of versions) existing.versions.push(version2);
41674
+ existing.noticeKind ??= noticeKind;
41675
+ if (rangesDiscarded) existing.rangesDiscarded = true;
41200
41676
  continue;
41201
41677
  }
41202
41678
  byPackage.set(packageName, {
@@ -41210,7 +41686,9 @@ function normalizeOsvRecord(record2, ecosystem) {
41210
41686
  summary,
41211
41687
  url: url2,
41212
41688
  malicious,
41213
- withdrawn
41689
+ withdrawn,
41690
+ noticeKind,
41691
+ ...rangesDiscarded ? { rangesDiscarded } : {}
41214
41692
  });
41215
41693
  }
41216
41694
  for (const row of byPackage.values()) {
@@ -41230,14 +41708,17 @@ function extractVersions(versions) {
41230
41708
  }
41231
41709
  return out;
41232
41710
  }
41711
+ function isReadableRange(range) {
41712
+ const type2 = typeof range.type === "string" ? range.type : "SEMVER";
41713
+ return (type2 === "SEMVER" || type2 === "ECOSYSTEM") && Array.isArray(range.events);
41714
+ }
41233
41715
  function extractRanges(ranges, lastKnownAffected, comparator) {
41234
41716
  if (!Array.isArray(ranges)) return [];
41235
41717
  const out = [];
41236
41718
  const refused = [];
41237
41719
  for (const range of ranges) {
41720
+ if (!isReadableRange(range)) continue;
41238
41721
  const type2 = typeof range.type === "string" ? range.type : "SEMVER";
41239
- if (type2 !== "SEMVER" && type2 !== "ECOSYSTEM") continue;
41240
- if (!Array.isArray(range.events)) continue;
41241
41722
  let introduced = null;
41242
41723
  let lastAffected = null;
41243
41724
  for (const event of range.events) {
@@ -41295,7 +41776,17 @@ function boundOpenEndedRange(ranges, lastKnownAffected, comparator) {
41295
41776
  function pickSeverity2(r) {
41296
41777
  const ds = r.database_specific && r.database_specific.severity;
41297
41778
  if (typeof ds === "string" && ds.length > 0) return ds;
41298
- return null;
41779
+ if (!Array.isArray(r.severity)) return null;
41780
+ return severityFromCvss(vectorOfType(r.severity, "CVSS_V3"), vectorOfType(r.severity, "CVSS_V2"));
41781
+ }
41782
+ function vectorOfType(severity, type2) {
41783
+ const entry = severity.find(function ofType(s) {
41784
+ return s.type === type2 && typeof s.score === "string";
41785
+ });
41786
+ return entry?.score ?? null;
41787
+ }
41788
+ function noticeKindOf(value) {
41789
+ return isNonEmptyString(value) ? value : null;
41299
41790
  }
41300
41791
  function pickUrl(r, advisoryId) {
41301
41792
  if (Array.isArray(r.references)) {
@@ -41425,98 +41916,6 @@ function parseSeedEntry(content, ecosystem) {
41425
41916
  // ../../packages/feeds/src/gemnasium/feed.ts
41426
41917
  var import_unzipper2 = __toESM(require_unzip2());
41427
41918
 
41428
- // ../../packages/feeds/src/gemnasium/cvss.ts
41429
- var V3_AV = { N: 0.85, A: 0.62, L: 0.55, P: 0.2 };
41430
- var V3_AC = { L: 0.77, H: 0.44 };
41431
- var V3_UI = { N: 0.85, R: 0.62 };
41432
- var V3_CIA = { H: 0.56, L: 0.22, N: 0 };
41433
- var V3_PR_UNCHANGED = { N: 0.85, L: 0.62, H: 0.27 };
41434
- var V3_PR_CHANGED = { N: 0.85, L: 0.68, H: 0.5 };
41435
- var V2_AV = { L: 0.395, A: 0.646, N: 1 };
41436
- var V2_AC = { H: 0.35, M: 0.61, L: 0.71 };
41437
- var V2_AU = { M: 0.45, S: 0.56, N: 0.704 };
41438
- var V2_CIA = { N: 0, P: 0.275, C: 0.66 };
41439
- function severityFromCvss(cvssV3, cvssV2) {
41440
- const v3 = parseVector(cvssV3);
41441
- if (v3) {
41442
- const score = baseScoreV3(v3);
41443
- if (score !== null) return bucketV3(score);
41444
- }
41445
- const v2 = parseVector(cvssV2);
41446
- if (v2) {
41447
- const score = baseScoreV2(v2);
41448
- if (score !== null) return bucketV2(score);
41449
- }
41450
- return null;
41451
- }
41452
- function parseVector(vector) {
41453
- if (typeof vector !== "string" || vector.trim().length === 0) return null;
41454
- const out = {};
41455
- for (const part of vector.trim().split("/")) {
41456
- const colon = part.indexOf(":");
41457
- if (colon <= 0) continue;
41458
- const key = part.slice(0, colon).trim();
41459
- const value = part.slice(colon + 1).trim().toUpperCase();
41460
- if (key === "CVSS") continue;
41461
- out[key] = value;
41462
- }
41463
- return Object.keys(out).length > 0 ? out : null;
41464
- }
41465
- function weight(table, key) {
41466
- if (key === void 0) return void 0;
41467
- return table[key];
41468
- }
41469
- function baseScoreV3(m) {
41470
- const av = weight(V3_AV, m.AV);
41471
- const ac = weight(V3_AC, m.AC);
41472
- const ui = weight(V3_UI, m.UI);
41473
- const c = weight(V3_CIA, m.C);
41474
- const i = weight(V3_CIA, m.I);
41475
- const a = weight(V3_CIA, m.A);
41476
- const changed = m.S === "C";
41477
- const pr = weight(changed ? V3_PR_CHANGED : V3_PR_UNCHANGED, m.PR);
41478
- if (av === void 0 || ac === void 0 || ui === void 0 || pr === void 0) return null;
41479
- if (c === void 0 || i === void 0 || a === void 0) return null;
41480
- const iss = 1 - (1 - c) * (1 - i) * (1 - a);
41481
- const impact = changed ? 7.52 * (iss - 0.029) - 3.25 * Math.pow(iss - 0.02, 15) : 6.42 * iss;
41482
- const exploitability = 8.22 * av * ac * pr * ui;
41483
- if (impact <= 0) return 0;
41484
- const raw = changed ? 1.08 * (impact + exploitability) : impact + exploitability;
41485
- return roundUpV3(Math.min(raw, 10));
41486
- }
41487
- function roundUpV3(value) {
41488
- const intInput = Math.round(value * 1e5);
41489
- if (intInput % 1e4 === 0) return intInput / 1e5;
41490
- return (Math.floor(intInput / 1e4) + 1) / 10;
41491
- }
41492
- function bucketV3(score) {
41493
- if (score === 0) return "info";
41494
- if (score < 4) return "low";
41495
- if (score < 7) return "moderate";
41496
- if (score < 9) return "high";
41497
- return "critical";
41498
- }
41499
- function baseScoreV2(m) {
41500
- const av = weight(V2_AV, m.AV);
41501
- const ac = weight(V2_AC, m.AC);
41502
- const au = weight(V2_AU, m.Au) ?? weight(V2_AU, m.AU);
41503
- const c = weight(V2_CIA, m.C);
41504
- const i = weight(V2_CIA, m.I);
41505
- const a = weight(V2_CIA, m.A);
41506
- if (av === void 0 || ac === void 0 || au === void 0) return null;
41507
- if (c === void 0 || i === void 0 || a === void 0) return null;
41508
- const impact = 10.41 * (1 - (1 - c) * (1 - i) * (1 - a));
41509
- const exploitability = 20 * av * ac * au;
41510
- const f = impact === 0 ? 0 : 1.176;
41511
- const base = (0.6 * impact + 0.4 * exploitability - 1.5) * f;
41512
- return Math.round(base * 10) / 10;
41513
- }
41514
- function bucketV2(score) {
41515
- if (score < 4) return "low";
41516
- if (score < 7) return "moderate";
41517
- return "high";
41518
- }
41519
-
41520
41919
  // ../../packages/feeds/src/gemnasium/normalize.ts
41521
41920
  function normalizeGemnasiumRecord(record2, ecosystem, slugPrefix) {
41522
41921
  if (!record2 || typeof record2 !== "object") return [];
@@ -55734,8 +56133,13 @@ function pickReleasedFix(args) {
55734
56133
  patched.push(range);
55735
56134
  }
55736
56135
  const stated = statedFixVersions(args.evidence, comparator);
55737
- let lowest = null;
55738
- let lowestCurrent = null;
56136
+ function lowest(current, candidate) {
56137
+ return current === null || comparator.lt(candidate.version, current.version) ? candidate : current;
56138
+ }
56139
+ let tagged = null;
56140
+ let taggedCurrent = null;
56141
+ let pseudo = null;
56142
+ let pseudoCurrent = null;
55739
56143
  for (const p of args.published) {
55740
56144
  const v = comparator.normalize(p.version);
55741
56145
  if (v === null) continue;
@@ -55749,10 +56153,15 @@ function pickReleasedFix(args) {
55749
56153
  return evaluableContains(ev, v);
55750
56154
  })) continue;
55751
56155
  const candidate = { version: v, spelled: p.version };
55752
- if (lowest === null || comparator.lt(v, lowest.version)) lowest = candidate;
55753
- if (!p.deprecated && (lowestCurrent === null || comparator.lt(v, lowestCurrent.version))) lowestCurrent = candidate;
56156
+ if (kind === "pseudo") {
56157
+ pseudo = lowest(pseudo, candidate);
56158
+ if (!p.deprecated) pseudoCurrent = lowest(pseudoCurrent, candidate);
56159
+ } else {
56160
+ tagged = lowest(tagged, candidate);
56161
+ if (!p.deprecated) taggedCurrent = lowest(taggedCurrent, candidate);
56162
+ }
55754
56163
  }
55755
- const chosen = lowestCurrent ?? lowest;
56164
+ const chosen = taggedCurrent ?? tagged ?? pseudoCurrent ?? pseudo;
55756
56165
  if (chosen === null) return { kind: "none" };
55757
56166
  return { kind: "released", version: chosen.spelled };
55758
56167
  }
@@ -56215,7 +56624,8 @@ function toOsvAdvisory(row) {
56215
56624
  summary: row.summary,
56216
56625
  url: row.url,
56217
56626
  malicious: row.malicious,
56218
- withdrawn: row.withdrawn
56627
+ withdrawn: row.withdrawn,
56628
+ noticeKind: row.noticeKind ?? null
56219
56629
  };
56220
56630
  }
56221
56631
  function toGemnasiumAdvisory(row) {
@@ -56995,7 +57405,7 @@ function explicitFlagNames(argv) {
56995
57405
  return out;
56996
57406
  }
56997
57407
  function emptyCounts() {
56998
- return { critical: 0, high: 0, moderate: 0, low: 0, info: 0 };
57408
+ return { critical: 0, high: 0, moderate: 0, unrated: 0, low: 0, info: 0 };
56999
57409
  }
57000
57410
  function matchesDepType(finding, depType) {
57001
57411
  if (depType === "all") return true;
@@ -57005,6 +57415,7 @@ function matchesDepType(finding, depType) {
57005
57415
  function summarize(results, options) {
57006
57416
  const projects = [];
57007
57417
  const findings = [];
57418
+ const notices = [];
57008
57419
  const total = emptyCounts();
57009
57420
  let totalFindings = 0;
57010
57421
  for (const result of results) {
@@ -57012,26 +57423,30 @@ function summarize(results, options) {
57012
57423
  let projectFindings = 0;
57013
57424
  for (const finding of result.findings) {
57014
57425
  if (!matchesDepType(finding, options.depType)) continue;
57015
- if (!meetsSeverityFloor(finding.severity, options.minSeverity)) continue;
57016
- counts[finding.severity]++;
57017
- total[finding.severity]++;
57018
- projectFindings++;
57019
- totalFindings++;
57426
+ if (!finding.noticeKind && !meetsSeverityFloor(finding.severity, options.minSeverity)) continue;
57427
+ if (!finding.noticeKind) {
57428
+ counts[finding.severity]++;
57429
+ total[finding.severity]++;
57430
+ projectFindings++;
57431
+ totalFindings++;
57432
+ }
57020
57433
  const fix = result.fixes.get(finding);
57021
- findings.push({
57434
+ const list = finding.noticeKind ? notices : findings;
57435
+ list.push({
57022
57436
  // npm-audit builds its findings without an ecosystem; it only ever reports npm packages.
57023
57437
  ecosystem: finding.ecosystem ?? DEFAULT_ECOSYSTEM,
57024
57438
  packageName: finding.packageName,
57025
57439
  installedVersion: finding.installedVersion,
57026
57440
  // scanProject records the installations of every finding it keeps.
57027
57441
  installations: result.installations.get(finding),
57028
- fixAvailable: fix.fixAvailable,
57029
- fixVersion: fix.fixVersion,
57030
- fixStatus: fix.fixStatus,
57031
- fixCheck: fix.fixCheck,
57442
+ fixAvailable: fix?.fixAvailable ?? false,
57443
+ fixVersion: fix?.fixVersion ?? null,
57444
+ fixStatus: fix?.fixStatus ?? "unverified",
57445
+ fixCheck: fix?.fixCheck ?? null,
57032
57446
  // Only a finding settled 'none_released' has one.
57033
57447
  remediation: result.remediations.get(finding) ?? null,
57034
57448
  severity: finding.severity,
57449
+ noticeKind: finding.noticeKind ?? null,
57035
57450
  advisoryId: finding.advisoryId,
57036
57451
  advisoryTitle: finding.advisoryTitle,
57037
57452
  advisoryUrl: finding.advisoryUrl,
@@ -57057,7 +57472,7 @@ function summarize(results, options) {
57057
57472
  scanState: result.scanState
57058
57473
  });
57059
57474
  }
57060
- return { projects, totalFindings, counts: total, findings };
57475
+ return { projects, totalFindings, counts: total, findings, notices };
57061
57476
  }
57062
57477
  async function resolvePrompt(options) {
57063
57478
  if (!options.includePrompt) return "";
@@ -57079,7 +57494,7 @@ function renderMarkdown(summary, options, prompt, generatedAt) {
57079
57494
  return buildAdvisoryMarkdown({
57080
57495
  scope: buildScope(options, summary.projects.length),
57081
57496
  prompt,
57082
- findings: summary.findings,
57497
+ findings: [...summary.findings, ...summary.notices],
57083
57498
  generatedAt,
57084
57499
  // Only the projects that could not be (fully) scanned are rendered, in their own section.
57085
57500
  scanStates: summary.projects.map(function state(p) {
@@ -57109,7 +57524,8 @@ function renderJson(summary, options, generatedAt) {
57109
57524
  scanState: labelScanState(p.scanState)
57110
57525
  };
57111
57526
  }),
57112
- findings: summary.findings
57527
+ findings: summary.findings,
57528
+ notices: summary.notices
57113
57529
  }, null, 2) + "\n";
57114
57530
  }
57115
57531
  function hasUnavailableSource(summary) {
@@ -57266,7 +57682,7 @@ async function scanProject(setup, resolved2, scanners) {
57266
57682
  for (const scanner of scanners) {
57267
57683
  for (const ecosystem of ecosystems) {
57268
57684
  if (setup.abortSignal && setup.abortSignal.aborted) break;
57269
- if (!cellRuns(setup, scanner.name, ecosystem)) continue;
57685
+ if (!cellRuns(setup, scanner.name, ecosystem) || !sourceAppliesToPackageManager(scanner.name, resolved2.project.packageManager)) continue;
57270
57686
  const isNpmAudit = scanner.name === NPM_AUDIT_SCANNER_NAME2;
57271
57687
  const cell = resolved2.manifests.filter(function of(m) {
57272
57688
  return m.result.ecosystem === ecosystem;
@@ -57319,7 +57735,10 @@ async function scanProject(setup, resolved2, scanners) {
57319
57735
  }
57320
57736
  }
57321
57737
  const settled = await settleProject({
57322
- findings: [...survivors.values()],
57738
+ // A notice has no fix to chase, so it is not settled.
57739
+ findings: [...survivors.values()].filter(function vulnerability(reported) {
57740
+ return !reported.finding.noticeKind;
57741
+ }),
57323
57742
  evidence,
57324
57743
  graph: resolved2.npmGraph,
57325
57744
  registry: setup.registry,
@@ -57330,7 +57749,8 @@ async function scanProject(setup, resolved2, scanners) {
57330
57749
  const installations = /* @__PURE__ */ new Map();
57331
57750
  for (const [finding, reported] of survivors) {
57332
57751
  const key = fixEvidenceKey(reported);
57333
- fixes.set(finding, settled.settlements.get(key));
57752
+ const settlement = settled.settlements.get(key);
57753
+ if (settlement) fixes.set(finding, settlement);
57334
57754
  const remediation = settled.remediations.get(key);
57335
57755
  if (remediation) remediations.set(finding, remediation);
57336
57756
  installations.set(finding, installationsFor(finding, resolved2.npmGraph));
@@ -57365,7 +57785,7 @@ function cliScanState(setup, resolved2, scanners, outcomes) {
57365
57785
  const expectedCells = [];
57366
57786
  for (const scanner of scanners) {
57367
57787
  for (const ecosystem of ecosystems) {
57368
- if (cellRuns(setup, scanner.name, ecosystem)) expectedCells.push({ source: scanner.name, ecosystem });
57788
+ if (cellRuns(setup, scanner.name, ecosystem) && sourceAppliesToPackageManager(scanner.name, resolved2.project.packageManager)) expectedCells.push({ source: scanner.name, ecosystem });
57369
57789
  }
57370
57790
  }
57371
57791
  return projectScanState({
@@ -57409,7 +57829,7 @@ var PLAIN = {
57409
57829
  green: "",
57410
57830
  cyan: ""
57411
57831
  };
57412
- var SEVERITY_ORDER = ["critical", "high", "moderate", "low", "info"];
57832
+ var SEVERITY_ORDER = ["critical", "high", "moderate", "unrated", "low", "info"];
57413
57833
  function formatBytes(bytes, estimated = false) {
57414
57834
  if (bytes === null) return "unknown size";
57415
57835
  const prefix = estimated ? "~" : "";
@@ -57445,7 +57865,7 @@ function createUi(options) {
57445
57865
  function severityColor(severity) {
57446
57866
  if (severity === "critical") return c.red;
57447
57867
  if (severity === "high") return c.magenta;
57448
- if (severity === "moderate") return c.yellow;
57868
+ if (severity === "moderate" || severity === "unrated") return c.yellow;
57449
57869
  if (severity === "low") return c.blue;
57450
57870
  return c.dim;
57451
57871
  }
@@ -57712,6 +58132,9 @@ function createUi(options) {
57712
58132
  write(" " + project.relPath.padEnd(38).slice(0, 38) + " " + breakdown);
57713
58133
  }
57714
58134
  }
58135
+ if (runSummary.notices.length > 0) {
58136
+ write(" " + c.dim + runSummary.notices.length + " notice" + (runSummary.notices.length === 1 ? "" : "s") + " (unmaintained, unsound), not vulnerabilities: listed in the report, in no count above." + c.reset);
58137
+ }
57715
58138
  if (unscanned.length > 0) {
57716
58139
  const cannot = runSummary.projects.filter(function cannotScan(p) {
57717
58140
  return p.scanState.state === "cannot_scan";
@@ -57773,8 +58196,8 @@ function createUi(options) {
57773
58196
 
57774
58197
  // src/help.ts
57775
58198
  var CLI_VERSION = (function resolveVersion() {
57776
- if ("3.8.0".length > 0) {
57777
- return "3.8.0";
58199
+ if ("3.8.2".length > 0) {
58200
+ return "3.8.2";
57778
58201
  }
57779
58202
  const fromEnv = process.env.SENTINELLO_VERSION;
57780
58203
  if (fromEnv && fromEnv.trim().length > 0) return fromEnv.trim();