@wrongstack/plugins 0.309.0 → 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.
- package/dist/dependency-vulnerability-gate.js +31 -3
- package/dist/index.js +34 -12
- package/dist/path-guard.js +3 -9
- package/package.json +5 -5
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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]
|
|
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] ?? "")) {
|
package/dist/path-guard.js
CHANGED
|
@@ -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]
|
|
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.309.
|
|
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.
|
|
303
|
+
"vitest": "^4.1.11"
|
|
304
304
|
},
|
|
305
305
|
"dependencies": {
|
|
306
|
-
"@wrongstack/plugin-sdk": "0.309.
|
|
307
|
-
"@wrongstack/core": "0.309.
|
|
308
|
-
"@wrongstack/tools": "0.309.
|
|
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",
|