@wrongstack/plugins 0.302.2 → 0.305.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1220 -1201
- package/dist/path-guard.js +15 -14
- package/dist/secret-scanner.js +70 -52
- package/package.json +3 -3
package/dist/path-guard.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
// src/path-guard/index.ts
|
|
2
|
-
|
|
3
|
-
invocations: 0,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
hookUnregister: null
|
|
8
|
-
};
|
|
2
|
+
function createState() {
|
|
3
|
+
return { invocations: 0, blocks: 0, warns: 0, lastBlock: null, hookUnregister: null };
|
|
4
|
+
}
|
|
5
|
+
var states = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
var latestState = createState();
|
|
9
7
|
var DEFAULT_PROTECT = [
|
|
10
8
|
"pnpm-lock.yaml",
|
|
11
9
|
"package-lock.json",
|
|
@@ -1273,17 +1271,16 @@ var plugin = {
|
|
|
1273
1271
|
}
|
|
1274
1272
|
},
|
|
1275
1273
|
setup(api) {
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
state.warns = 0;
|
|
1279
|
-
state.lastBlock = null;
|
|
1280
|
-
if (state.hookUnregister) {
|
|
1274
|
+
const previous = states.get(api);
|
|
1275
|
+
if (previous?.hookUnregister) {
|
|
1281
1276
|
try {
|
|
1282
|
-
|
|
1277
|
+
previous.hookUnregister();
|
|
1283
1278
|
} catch {
|
|
1284
1279
|
}
|
|
1285
|
-
state.hookUnregister = null;
|
|
1286
1280
|
}
|
|
1281
|
+
const state = createState();
|
|
1282
|
+
states.set(api, state);
|
|
1283
|
+
latestState = state;
|
|
1287
1284
|
const cfg = readConfig(api.config.extensions?.["path-guard"]);
|
|
1288
1285
|
const protectRes = cfg.protect.map(compilePathGlob);
|
|
1289
1286
|
const allowRes = cfg.allow.map(compilePathGlob);
|
|
@@ -1397,6 +1394,8 @@ var plugin = {
|
|
|
1397
1394
|
});
|
|
1398
1395
|
},
|
|
1399
1396
|
teardown(api) {
|
|
1397
|
+
const state = states.get(api);
|
|
1398
|
+
if (!state) return;
|
|
1400
1399
|
if (state.hookUnregister) {
|
|
1401
1400
|
try {
|
|
1402
1401
|
state.hookUnregister();
|
|
@@ -1409,9 +1408,11 @@ var plugin = {
|
|
|
1409
1408
|
state.blocks = 0;
|
|
1410
1409
|
state.warns = 0;
|
|
1411
1410
|
state.lastBlock = null;
|
|
1411
|
+
states.delete(api);
|
|
1412
1412
|
api.log.info("path-guard: teardown complete", { final });
|
|
1413
1413
|
},
|
|
1414
1414
|
async health() {
|
|
1415
|
+
const state = latestState;
|
|
1415
1416
|
return {
|
|
1416
1417
|
ok: true,
|
|
1417
1418
|
message: state.lastBlock === null ? `path-guard: ${state.invocations} invocation(s), ${state.blocks} block(s), ${state.warns} warn(s)` : `path-guard: last block on "${state.lastBlock.path}" (${state.lastBlock.tool}) at ${state.lastBlock.when}`,
|
package/dist/secret-scanner.js
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
// src/runtime/local-bin.ts
|
|
2
|
-
import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
|
|
3
|
-
|
|
4
|
-
// src/runtime/handles.ts
|
|
5
|
-
function releaseHandle(off) {
|
|
6
|
-
if (off) {
|
|
7
|
-
try {
|
|
8
|
-
off();
|
|
9
|
-
} catch {
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// src/runtime/index.ts
|
|
16
|
-
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
17
|
-
|
|
18
1
|
// src/runtime/credential-patterns.ts
|
|
19
2
|
var CREDENTIAL_PATTERNS = [
|
|
20
3
|
// LLM provider keys
|
|
@@ -125,10 +108,26 @@ function cloneCredentialPatterns() {
|
|
|
125
108
|
}));
|
|
126
109
|
}
|
|
127
110
|
|
|
111
|
+
// src/runtime/local-bin.ts
|
|
112
|
+
import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
|
|
113
|
+
|
|
114
|
+
// src/runtime/handles.ts
|
|
115
|
+
function releaseHandle(off) {
|
|
116
|
+
if (off) {
|
|
117
|
+
try {
|
|
118
|
+
off();
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/runtime/index.ts
|
|
126
|
+
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
127
|
+
|
|
128
128
|
// src/secret-scanner/index.ts
|
|
129
129
|
var BASE_PATTERNS = cloneCredentialPatterns();
|
|
130
130
|
var PATTERNS = [...BASE_PATTERNS];
|
|
131
|
-
var patternCacheKey = "";
|
|
132
131
|
var GROUP_INDEX_OF_PATTERN = [];
|
|
133
132
|
var COMBINED_REGEX = buildCombinedRegex(PATTERNS);
|
|
134
133
|
var SCAN_WINDOW_LENGTH = 1e5;
|
|
@@ -151,11 +150,6 @@ function patternTypeForGroups(groups) {
|
|
|
151
150
|
return void 0;
|
|
152
151
|
}
|
|
153
152
|
function buildCombinedRegex(patterns) {
|
|
154
|
-
const newCacheKey = JSON.stringify(patterns.map((p) => [p.type, p.regex.source]));
|
|
155
|
-
if (newCacheKey === patternCacheKey && COMBINED_REGEX) {
|
|
156
|
-
return COMBINED_REGEX;
|
|
157
|
-
}
|
|
158
|
-
patternCacheKey = newCacheKey;
|
|
159
153
|
const offsets = [];
|
|
160
154
|
let cursor = 0;
|
|
161
155
|
for (const p of patterns) {
|
|
@@ -165,21 +159,30 @@ function buildCombinedRegex(patterns) {
|
|
|
165
159
|
GROUP_INDEX_OF_PATTERN = offsets;
|
|
166
160
|
return new RegExp(patterns.map((p) => `(${p.regex.source})`).join("|"), "g");
|
|
167
161
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
162
|
+
function createState() {
|
|
163
|
+
return {
|
|
164
|
+
blockCount: 0,
|
|
165
|
+
redactCount: 0,
|
|
166
|
+
allowCount: 0,
|
|
167
|
+
/** PostToolUse: secrets detected in tool output. */
|
|
168
|
+
leakCount: 0,
|
|
169
|
+
/** Most recent PreToolUse block — surfaced by `secret_scanner_status`. */
|
|
170
|
+
lastBlock: null,
|
|
171
|
+
/** Most recent PostToolUse leak — surfaced by `secret_scanner_status`. */
|
|
172
|
+
lastLeak: null,
|
|
173
|
+
/** PreToolUse hook handle so teardown can unregister. */
|
|
174
|
+
hookUnregister: null,
|
|
175
|
+
/** PostToolUse hook handle so teardown can unregister. */
|
|
176
|
+
postHookUnregister: null
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
var runtimes = /* @__PURE__ */ new WeakMap();
|
|
180
|
+
var latestRuntime;
|
|
181
|
+
function activateRuntime(runtime) {
|
|
182
|
+
PATTERNS = runtime.patterns;
|
|
183
|
+
COMBINED_REGEX = runtime.combinedRegex;
|
|
184
|
+
GROUP_INDEX_OF_PATTERN = runtime.groupIndexes;
|
|
185
|
+
}
|
|
183
186
|
function scanWindow(window, found, startTime) {
|
|
184
187
|
COMBINED_REGEX.lastIndex = 0;
|
|
185
188
|
let m;
|
|
@@ -325,8 +328,10 @@ function readConfig(raw) {
|
|
|
325
328
|
customPatterns
|
|
326
329
|
};
|
|
327
330
|
}
|
|
328
|
-
function buildHook(cfg, log) {
|
|
331
|
+
function buildHook(cfg, log, runtime) {
|
|
329
332
|
return (input) => {
|
|
333
|
+
activateRuntime(runtime);
|
|
334
|
+
const { state } = runtime;
|
|
330
335
|
if (!cfg.enabled) return;
|
|
331
336
|
const toolName = input.toolName ?? "unknown";
|
|
332
337
|
const matched = scanInput(input.toolInput);
|
|
@@ -368,8 +373,10 @@ function buildHook(cfg, log) {
|
|
|
368
373
|
return void 0;
|
|
369
374
|
};
|
|
370
375
|
}
|
|
371
|
-
function buildPostHook(cfg, log) {
|
|
376
|
+
function buildPostHook(cfg, log, runtime) {
|
|
372
377
|
return (input) => {
|
|
378
|
+
activateRuntime(runtime);
|
|
379
|
+
const { state } = runtime;
|
|
373
380
|
if (!cfg.enabled) return;
|
|
374
381
|
const result = input.toolResult;
|
|
375
382
|
if (!result || typeof result.content !== "string") return;
|
|
@@ -446,14 +453,11 @@ var plugin = {
|
|
|
446
453
|
}
|
|
447
454
|
},
|
|
448
455
|
setup(api) {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
state.lastLeak = null;
|
|
455
|
-
state.hookUnregister = releaseHandle(state.hookUnregister);
|
|
456
|
-
state.postHookUnregister = releaseHandle(state.postHookUnregister);
|
|
456
|
+
const previous = runtimes.get(api);
|
|
457
|
+
if (previous) {
|
|
458
|
+
previous.state.hookUnregister = releaseHandle(previous.state.hookUnregister);
|
|
459
|
+
previous.state.postHookUnregister = releaseHandle(previous.state.postHookUnregister);
|
|
460
|
+
}
|
|
457
461
|
const cfg = readConfig(api.config.extensions?.["secret-scanner"]);
|
|
458
462
|
PATTERNS = [...BASE_PATTERNS];
|
|
459
463
|
for (const cp of cfg.customPatterns) {
|
|
@@ -463,11 +467,20 @@ var plugin = {
|
|
|
463
467
|
}
|
|
464
468
|
}
|
|
465
469
|
COMBINED_REGEX = buildCombinedRegex(PATTERNS);
|
|
470
|
+
const runtime = {
|
|
471
|
+
state: createState(),
|
|
472
|
+
patterns: PATTERNS,
|
|
473
|
+
combinedRegex: COMBINED_REGEX,
|
|
474
|
+
groupIndexes: [...GROUP_INDEX_OF_PATTERN]
|
|
475
|
+
};
|
|
476
|
+
runtimes.set(api, runtime);
|
|
477
|
+
latestRuntime = runtime;
|
|
478
|
+
const { state } = runtime;
|
|
466
479
|
const log = {
|
|
467
480
|
warn: (msg, ...rest) => api.log.warn(msg, ...rest),
|
|
468
481
|
info: (msg, ...rest) => api.log.info(msg, ...rest)
|
|
469
482
|
};
|
|
470
|
-
const hook = buildHook(cfg, log);
|
|
483
|
+
const hook = buildHook(cfg, log, runtime);
|
|
471
484
|
state.hookUnregister = api.registerHook("PreToolUse", cfg.matcher, hook, {
|
|
472
485
|
name: "secret-scanner",
|
|
473
486
|
// Redaction rewrites arguments; block/allow modes must inspect the final
|
|
@@ -477,7 +490,7 @@ var plugin = {
|
|
|
477
490
|
failurePolicy: "closed",
|
|
478
491
|
policy: true
|
|
479
492
|
});
|
|
480
|
-
const postHook = buildPostHook(cfg, log);
|
|
493
|
+
const postHook = buildPostHook(cfg, log, runtime);
|
|
481
494
|
state.postHookUnregister = api.registerHook("PostToolUse", cfg.postToolUseMatcher, postHook);
|
|
482
495
|
api.tools.register({
|
|
483
496
|
name: "secret_scanner_status",
|
|
@@ -486,6 +499,7 @@ var plugin = {
|
|
|
486
499
|
permission: "auto",
|
|
487
500
|
mutating: false,
|
|
488
501
|
async execute() {
|
|
502
|
+
activateRuntime(runtime);
|
|
489
503
|
return {
|
|
490
504
|
ok: true,
|
|
491
505
|
enabled: cfg.enabled,
|
|
@@ -518,6 +532,7 @@ var plugin = {
|
|
|
518
532
|
permission: "auto",
|
|
519
533
|
mutating: false,
|
|
520
534
|
async execute(input) {
|
|
535
|
+
activateRuntime(runtime);
|
|
521
536
|
const text = typeof input["text"] === "string" ? input["text"] : "";
|
|
522
537
|
const matched = findMatches(text);
|
|
523
538
|
return {
|
|
@@ -535,6 +550,9 @@ var plugin = {
|
|
|
535
550
|
});
|
|
536
551
|
},
|
|
537
552
|
teardown(api) {
|
|
553
|
+
const runtime = runtimes.get(api);
|
|
554
|
+
if (!runtime) return;
|
|
555
|
+
const { state } = runtime;
|
|
538
556
|
if (state.hookUnregister) {
|
|
539
557
|
try {
|
|
540
558
|
state.hookUnregister();
|
|
@@ -561,11 +579,11 @@ var plugin = {
|
|
|
561
579
|
state.leakCount = 0;
|
|
562
580
|
state.lastBlock = null;
|
|
563
581
|
state.lastLeak = null;
|
|
564
|
-
|
|
565
|
-
COMBINED_REGEX = buildCombinedRegex(PATTERNS);
|
|
582
|
+
runtimes.delete(api);
|
|
566
583
|
api.log.info("secret-scanner: teardown complete", { counters: finalCounters });
|
|
567
584
|
},
|
|
568
585
|
async health() {
|
|
586
|
+
const state = latestRuntime?.state ?? createState();
|
|
569
587
|
return {
|
|
570
588
|
ok: true,
|
|
571
589
|
message: state.lastLeak !== null ? `secret-scanner: last leak at ${state.lastLeak.when} on ${state.lastLeak.toolName} (${state.lastLeak.matchedTypes.join(", ")})` : state.lastBlock !== null ? `secret-scanner: last block at ${state.lastBlock.when} on ${state.lastBlock.toolName} (${state.lastBlock.matchedTypes.join(", ")})` : `secret-scanner: ${state.blockCount + state.redactCount + state.allowCount + state.leakCount} invocations, no blocks or leaks`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.305.0",
|
|
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Ü",
|
|
@@ -299,8 +299,8 @@
|
|
|
299
299
|
"vitest": "^4.1.10"
|
|
300
300
|
},
|
|
301
301
|
"dependencies": {
|
|
302
|
-
"@wrongstack/
|
|
303
|
-
"@wrongstack/
|
|
302
|
+
"@wrongstack/tools": "0.305.0",
|
|
303
|
+
"@wrongstack/core": "0.305.0"
|
|
304
304
|
},
|
|
305
305
|
"scripts": {
|
|
306
306
|
"build": "node ../../scripts/build-package.mjs",
|