@wrongstack/plugins 0.308.7 → 0.309.1

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.
@@ -402,6 +402,7 @@ var state2 = {
402
402
  auditsRun: 0,
403
403
  blocks: 0,
404
404
  warns: 0,
405
+ belowThresholdWarns: 0,
405
406
  errors: 0,
406
407
  lastResult: null,
407
408
  hookUnregister: null
@@ -449,9 +450,11 @@ function parseAuditJson(jsonString) {
449
450
  return null;
450
451
  }
451
452
  const out = { maxSeverity: null, counts: {}, total: 0 };
452
- if (parsed && typeof parsed === "object") {
453
+ let recognizedShape = false;
454
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
453
455
  const vulnerabilities = parsed["vulnerabilities"];
454
456
  if (vulnerabilities && typeof vulnerabilities === "object" && !Array.isArray(vulnerabilities)) {
457
+ recognizedShape = true;
455
458
  for (const entry of Object.values(vulnerabilities)) {
456
459
  if (entry && typeof entry === "object") {
457
460
  const severity = entry["severity"];
@@ -464,7 +467,8 @@ function parseAuditJson(jsonString) {
464
467
  if (out.total === 0) {
465
468
  const metadata = parsed["metadata"];
466
469
  const metaVulns = metadata && typeof metadata === "object" ? metadata["vulnerabilities"] : void 0;
467
- if (metaVulns && typeof metaVulns === "object") {
470
+ if (metaVulns && typeof metaVulns === "object" && !Array.isArray(metaVulns)) {
471
+ recognizedShape = true;
468
472
  for (const [key, value] of Object.entries(metaVulns)) {
469
473
  const count = typeof value === "number" ? value : 0;
470
474
  if (count > 0 && SEVERITY_RANK[key] != null) {
@@ -480,6 +484,7 @@ function parseAuditJson(jsonString) {
480
484
  }
481
485
  }
482
486
  if (Array.isArray(parsed)) {
487
+ recognizedShape = true;
483
488
  for (const entry of parsed) {
484
489
  if (entry && typeof entry === "object") {
485
490
  const severity = entry["severity"];
@@ -489,6 +494,7 @@ function parseAuditJson(jsonString) {
489
494
  }
490
495
  }
491
496
  }
497
+ if (!recognizedShape) return null;
492
498
  return out;
493
499
  }
494
500
  function exceedsThreshold(report, threshold) {
@@ -598,6 +604,7 @@ var plugin2 = {
598
604
  state2.auditsRun = 0;
599
605
  state2.blocks = 0;
600
606
  state2.warns = 0;
607
+ state2.belowThresholdWarns = 0;
601
608
  state2.errors = 0;
602
609
  state2.lastResult = null;
603
610
  if (state2.hookUnregister) {
@@ -618,7 +625,13 @@ var plugin2 = {
618
625
  const result = await runAudit(cfg);
619
626
  if (!result) {
620
627
  state2.errors += 1;
621
- return;
628
+ api.metrics.counter("audit_errors");
629
+ api.log.warn("dependency-vulnerability-gate: audit did not complete; install not vetted", {
630
+ managerHint: "see dependency_audit_status for counters"
631
+ });
632
+ return {
633
+ additionalContext: "\n\u26A0\uFE0F dependency-vulnerability-gate: the package audit could not be completed (timeout or unreadable output), so these dependencies were NOT checked for known vulnerabilities."
634
+ };
622
635
  }
623
636
  state2.auditsRun += 1;
624
637
  state2.lastResult = {
@@ -630,6 +643,17 @@ var plugin2 = {
630
643
  when: (/* @__PURE__ */ new Date()).toISOString()
631
644
  };
632
645
  if (!exceedsThreshold(result.report, cfg.severityThreshold)) {
646
+ if (result.report.total > 0) {
647
+ state2.belowThresholdWarns += 1;
648
+ api.metrics.counter("below_threshold_warns");
649
+ const belowCounts = Object.entries(result.report.counts).filter(([, count]) => count > 0).map(([sev, count]) => `${sev}: ${count}`).join(", ");
650
+ return {
651
+ additionalContext: `
652
+ \u2139\uFE0F dependency-vulnerability-gate: ${result.manager} audit found vulnerabilities BELOW the configured threshold (${cfg.severityThreshold}); not blocking.
653
+ Max severity: ${result.report.maxSeverity}
654
+ Counts: ${belowCounts || "unknown"}`
655
+ };
656
+ }
633
657
  return;
634
658
  }
635
659
  const countsText = Object.entries(result.report.counts).filter(([, count]) => count > 0).map(([sev, count]) => `${sev}: ${count}`).join(", ");
@@ -671,6 +695,7 @@ Review the audit output or adjust the dependency choice.`;
671
695
  auditsRun: state2.auditsRun,
672
696
  blocks: state2.blocks,
673
697
  warns: state2.warns,
698
+ belowThresholdWarns: state2.belowThresholdWarns,
674
699
  errors: state2.errors
675
700
  },
676
701
  lastResult: state2.lastResult
@@ -697,6 +722,7 @@ Review the audit output or adjust the dependency choice.`;
697
722
  auditsRun: state2.auditsRun,
698
723
  blocks: state2.blocks,
699
724
  warns: state2.warns,
725
+ belowThresholdWarns: state2.belowThresholdWarns,
700
726
  errors: state2.errors
701
727
  };
702
728
  state2.invocations = 0;
@@ -704,6 +730,7 @@ Review the audit output or adjust the dependency choice.`;
704
730
  state2.auditsRun = 0;
705
731
  state2.blocks = 0;
706
732
  state2.warns = 0;
733
+ state2.belowThresholdWarns = 0;
707
734
  state2.errors = 0;
708
735
  state2.lastResult = null;
709
736
  api.log.info("dependency-vulnerability-gate: teardown complete", { final });
@@ -718,6 +745,7 @@ Review the audit output or adjust the dependency choice.`;
718
745
  auditsRun: state2.auditsRun,
719
746
  blocks: state2.blocks,
720
747
  warns: state2.warns,
748
+ belowThresholdWarns: state2.belowThresholdWarns,
721
749
  errors: state2.errors
722
750
  },
723
751
  lastResult: state2.lastResult
package/dist/index.js CHANGED
@@ -5713,6 +5713,7 @@ var state17 = {
5713
5713
  auditsRun: 0,
5714
5714
  blocks: 0,
5715
5715
  warns: 0,
5716
+ belowThresholdWarns: 0,
5716
5717
  errors: 0,
5717
5718
  lastResult: null,
5718
5719
  hookUnregister: null
@@ -5760,9 +5761,11 @@ function parseAuditJson(jsonString) {
5760
5761
  return null;
5761
5762
  }
5762
5763
  const out = { maxSeverity: null, counts: {}, total: 0 };
5763
- if (parsed && typeof parsed === "object") {
5764
+ let recognizedShape = false;
5765
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
5764
5766
  const vulnerabilities = parsed["vulnerabilities"];
5765
5767
  if (vulnerabilities && typeof vulnerabilities === "object" && !Array.isArray(vulnerabilities)) {
5768
+ recognizedShape = true;
5766
5769
  for (const entry of Object.values(vulnerabilities)) {
5767
5770
  if (entry && typeof entry === "object") {
5768
5771
  const severity = entry["severity"];
@@ -5775,7 +5778,8 @@ function parseAuditJson(jsonString) {
5775
5778
  if (out.total === 0) {
5776
5779
  const metadata = parsed["metadata"];
5777
5780
  const metaVulns = metadata && typeof metadata === "object" ? metadata["vulnerabilities"] : void 0;
5778
- if (metaVulns && typeof metaVulns === "object") {
5781
+ if (metaVulns && typeof metaVulns === "object" && !Array.isArray(metaVulns)) {
5782
+ recognizedShape = true;
5779
5783
  for (const [key, value] of Object.entries(metaVulns)) {
5780
5784
  const count = typeof value === "number" ? value : 0;
5781
5785
  if (count > 0 && SEVERITY_RANK[key] != null) {
@@ -5791,6 +5795,7 @@ function parseAuditJson(jsonString) {
5791
5795
  }
5792
5796
  }
5793
5797
  if (Array.isArray(parsed)) {
5798
+ recognizedShape = true;
5794
5799
  for (const entry of parsed) {
5795
5800
  if (entry && typeof entry === "object") {
5796
5801
  const severity = entry["severity"];
@@ -5800,6 +5805,7 @@ function parseAuditJson(jsonString) {
5800
5805
  }
5801
5806
  }
5802
5807
  }
5808
+ if (!recognizedShape) return null;
5803
5809
  return out;
5804
5810
  }
5805
5811
  function exceedsThreshold(report, threshold) {
@@ -5909,6 +5915,7 @@ var plugin18 = {
5909
5915
  state17.auditsRun = 0;
5910
5916
  state17.blocks = 0;
5911
5917
  state17.warns = 0;
5918
+ state17.belowThresholdWarns = 0;
5912
5919
  state17.errors = 0;
5913
5920
  state17.lastResult = null;
5914
5921
  if (state17.hookUnregister) {
@@ -5929,7 +5936,13 @@ var plugin18 = {
5929
5936
  const result = await runAudit(cfg);
5930
5937
  if (!result) {
5931
5938
  state17.errors += 1;
5932
- return;
5939
+ api.metrics.counter("audit_errors");
5940
+ api.log.warn("dependency-vulnerability-gate: audit did not complete; install not vetted", {
5941
+ managerHint: "see dependency_audit_status for counters"
5942
+ });
5943
+ return {
5944
+ additionalContext: "\n\u26A0\uFE0F dependency-vulnerability-gate: the package audit could not be completed (timeout or unreadable output), so these dependencies were NOT checked for known vulnerabilities."
5945
+ };
5933
5946
  }
5934
5947
  state17.auditsRun += 1;
5935
5948
  state17.lastResult = {
@@ -5941,6 +5954,17 @@ var plugin18 = {
5941
5954
  when: (/* @__PURE__ */ new Date()).toISOString()
5942
5955
  };
5943
5956
  if (!exceedsThreshold(result.report, cfg.severityThreshold)) {
5957
+ if (result.report.total > 0) {
5958
+ state17.belowThresholdWarns += 1;
5959
+ api.metrics.counter("below_threshold_warns");
5960
+ const belowCounts = Object.entries(result.report.counts).filter(([, count]) => count > 0).map(([sev, count]) => `${sev}: ${count}`).join(", ");
5961
+ return {
5962
+ additionalContext: `
5963
+ \u2139\uFE0F dependency-vulnerability-gate: ${result.manager} audit found vulnerabilities BELOW the configured threshold (${cfg.severityThreshold}); not blocking.
5964
+ Max severity: ${result.report.maxSeverity}
5965
+ Counts: ${belowCounts || "unknown"}`
5966
+ };
5967
+ }
5944
5968
  return;
5945
5969
  }
5946
5970
  const countsText = Object.entries(result.report.counts).filter(([, count]) => count > 0).map(([sev, count]) => `${sev}: ${count}`).join(", ");
@@ -5982,6 +6006,7 @@ Review the audit output or adjust the dependency choice.`;
5982
6006
  auditsRun: state17.auditsRun,
5983
6007
  blocks: state17.blocks,
5984
6008
  warns: state17.warns,
6009
+ belowThresholdWarns: state17.belowThresholdWarns,
5985
6010
  errors: state17.errors
5986
6011
  },
5987
6012
  lastResult: state17.lastResult
@@ -6008,6 +6033,7 @@ Review the audit output or adjust the dependency choice.`;
6008
6033
  auditsRun: state17.auditsRun,
6009
6034
  blocks: state17.blocks,
6010
6035
  warns: state17.warns,
6036
+ belowThresholdWarns: state17.belowThresholdWarns,
6011
6037
  errors: state17.errors
6012
6038
  };
6013
6039
  state17.invocations = 0;
@@ -6015,6 +6041,7 @@ Review the audit output or adjust the dependency choice.`;
6015
6041
  state17.auditsRun = 0;
6016
6042
  state17.blocks = 0;
6017
6043
  state17.warns = 0;
6044
+ state17.belowThresholdWarns = 0;
6018
6045
  state17.errors = 0;
6019
6046
  state17.lastResult = null;
6020
6047
  api.log.info("dependency-vulnerability-gate: teardown complete", { final });
@@ -6029,6 +6056,7 @@ Review the audit output or adjust the dependency choice.`;
6029
6056
  auditsRun: state17.auditsRun,
6030
6057
  blocks: state17.blocks,
6031
6058
  warns: state17.warns,
6059
+ belowThresholdWarns: state17.belowThresholdWarns,
6032
6060
  errors: state17.errors
6033
6061
  },
6034
6062
  lastResult: state17.lastResult
@@ -13612,7 +13640,7 @@ function stripLauncherAtBoundary(command, launcher, valueTaking) {
13612
13640
  }
13613
13641
  return `${command.slice(0, match.index)}${boundary}${after.slice(consumed).replace(/^\s+/, "")}`;
13614
13642
  }
13615
- var XARGS_OPTIONS = String.raw`(?:\s+(?:(?:-[InLsPjeE]|--(?:arg-file|replace|max-args|max-lines|max-chars|max-procs))\s+[^\s]+|-[^\s]+))*`;
13643
+ var XARGS_OPTIONS = String.raw`(?:\s+(?:(?:-[InLsPjeE]|--(?:arg-file|replace|max-args|max-lines|max-chars|max-procs))\s+[^\s-][^\s]*|-[^\s]+))*`;
13616
13644
  var COMMAND_BOUNDARY = String.raw`(?:^|[;&|\r\n]\s*|\{\s*|(?<![$(])\(\s*|\bxargs${XARGS_OPTIONS}\s+)`;
13617
13645
  function commandRecursivelyDeletes(command) {
13618
13646
  const stripped = stripTransparentLaunchers(maskNonExecutingHeredocBodies(command));
@@ -13944,19 +13972,13 @@ function destructiveTargetsAtDepth(command, depth) {
13944
13972
  if (destination) targets.push(destination);
13945
13973
  c = copy.exec(normalizedCommand);
13946
13974
  }
13947
- const tee = new RegExp(
13948
- String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(tee)\s+([^;&|\r\n]+)`,
13949
- "gi"
13950
- );
13975
+ const tee = new RegExp(String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(tee)\s+([^;&|\r\n]+)`, "gi");
13951
13976
  let t = tee.exec(normalizedCommand);
13952
13977
  while (t !== null) {
13953
13978
  if (!tokenIsQuoted(t, t[1] ?? "")) targets.push(...shellArgs(t[2] ?? ""));
13954
13979
  t = tee.exec(normalizedCommand);
13955
13980
  }
13956
- const dd = new RegExp(
13957
- String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(dd)\s+([^;&|\r\n]+)`,
13958
- "gi"
13959
- );
13981
+ const dd = new RegExp(String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(dd)\s+([^;&|\r\n]+)`, "gi");
13960
13982
  let d = dd.exec(normalizedCommand);
13961
13983
  while (d !== null) {
13962
13984
  if (!tokenIsQuoted(d, d[1] ?? "")) {
@@ -505,7 +505,7 @@ function stripLauncherAtBoundary(command, launcher, valueTaking) {
505
505
  }
506
506
  return `${command.slice(0, match.index)}${boundary}${after.slice(consumed).replace(/^\s+/, "")}`;
507
507
  }
508
- var XARGS_OPTIONS = String.raw`(?:\s+(?:(?:-[InLsPjeE]|--(?:arg-file|replace|max-args|max-lines|max-chars|max-procs))\s+[^\s]+|-[^\s]+))*`;
508
+ var XARGS_OPTIONS = String.raw`(?:\s+(?:(?:-[InLsPjeE]|--(?:arg-file|replace|max-args|max-lines|max-chars|max-procs))\s+[^\s-][^\s]*|-[^\s]+))*`;
509
509
  var COMMAND_BOUNDARY = String.raw`(?:^|[;&|\r\n]\s*|\{\s*|(?<![$(])\(\s*|\bxargs${XARGS_OPTIONS}\s+)`;
510
510
  function commandRecursivelyDeletes(command) {
511
511
  const stripped = stripTransparentLaunchers(maskNonExecutingHeredocBodies(command));
@@ -837,19 +837,13 @@ function destructiveTargetsAtDepth(command, depth) {
837
837
  if (destination) targets.push(destination);
838
838
  c = copy.exec(normalizedCommand);
839
839
  }
840
- const tee = new RegExp(
841
- String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(tee)\s+([^;&|\r\n]+)`,
842
- "gi"
843
- );
840
+ const tee = new RegExp(String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(tee)\s+([^;&|\r\n]+)`, "gi");
844
841
  let t = tee.exec(normalizedCommand);
845
842
  while (t !== null) {
846
843
  if (!tokenIsQuoted(t, t[1] ?? "")) targets.push(...shellArgs(t[2] ?? ""));
847
844
  t = tee.exec(normalizedCommand);
848
845
  }
849
- const dd = new RegExp(
850
- String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(dd)\s+([^;&|\r\n]+)`,
851
- "gi"
852
- );
846
+ const dd = new RegExp(String.raw`${COMMAND_BOUNDARY}(?:sudo\s+)?(dd)\s+([^;&|\r\n]+)`, "gi");
853
847
  let d = dd.exec(normalizedCommand);
854
848
  while (d !== null) {
855
849
  if (!tokenIsQuoted(d, d[1] ?? "")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/plugins",
3
- "version": "0.308.7",
3
+ "version": "0.309.1",
4
4
  "description": "Official WrongStack collection of focused plugins for code quality, security, observability, planning, and agent coordination",
5
5
  "license": "MIT",
6
6
  "author": "ECOSTACK TECHNOLOGY OÜ",
@@ -300,12 +300,12 @@
300
300
  "devDependencies": {
301
301
  "@types/node": "^26.2.0",
302
302
  "typescript": "^7.0.2",
303
- "vitest": "^4.1.10"
303
+ "vitest": "^4.1.11"
304
304
  },
305
305
  "dependencies": {
306
- "@wrongstack/core": "0.308.7",
307
- "@wrongstack/tools": "0.308.7",
308
- "@wrongstack/plugin-sdk": "0.308.7"
306
+ "@wrongstack/plugin-sdk": "0.309.1",
307
+ "@wrongstack/core": "0.309.1",
308
+ "@wrongstack/tools": "0.309.1"
309
309
  },
310
310
  "scripts": {
311
311
  "build": "node ../../scripts/build-package.mjs",