@wrongstack/plugins 0.286.0 → 0.289.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/README.md +20 -11
- package/dist/accessibility-auditor/index.d.ts.map +1 -1
- package/dist/accessibility-auditor.js +67 -55
- package/dist/api-compatibility-gate.js +1 -1
- package/dist/auto-doc.js +1 -1
- package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
- package/dist/auto-i18n-extractor.js +20 -12
- package/dist/changelog-writer.js +1 -1
- package/dist/code-metrics/index.d.ts.map +1 -1
- package/dist/code-metrics.js +63 -50
- package/dist/commit-validator.js +1 -1
- package/dist/config-validator.js +1 -1
- package/dist/cost-tracker/index.d.ts.map +1 -1
- package/dist/cost-tracker.js +4 -2
- package/dist/cron/index.d.ts.map +1 -1
- package/dist/cron.js +29 -0
- package/dist/dead-code-detector/index.d.ts.map +1 -1
- package/dist/dead-code-detector.js +28 -19
- package/dist/dep-guard.js +1 -1
- package/dist/diff-summary/index.d.ts.map +1 -1
- package/dist/diff-summary.js +19 -11
- package/dist/doc-sync-guard/index.d.ts.map +1 -1
- package/dist/doc-sync-guard.js +25 -16
- package/dist/duplicate-code-detector/index.d.ts.map +1 -1
- package/dist/duplicate-code-detector.js +70 -57
- package/dist/error-lens.js +1 -1
- package/dist/feature-flag-tracker/index.d.ts.map +1 -1
- package/dist/feature-flag-tracker.js +69 -56
- package/dist/file-watcher/index.d.ts.map +1 -1
- package/dist/file-watcher.js +21 -4
- package/dist/format-on-save/index.d.ts.map +1 -1
- package/dist/format-on-save.js +19 -11
- package/dist/git-autocommit.js +1 -1
- package/dist/import-organizer/index.d.ts.map +1 -1
- package/dist/import-organizer.js +23 -14
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1167 -1048
- package/dist/interface-contract-guard/index.d.ts.map +1 -1
- package/dist/interface-contract-guard.js +64 -51
- package/dist/lint-gate/index.d.ts.map +1 -1
- package/dist/lint-gate.js +61 -30
- package/dist/migration-planner/index.d.ts +12 -2
- package/dist/migration-planner/index.d.ts.map +1 -1
- package/dist/migration-planner.js +210 -28
- package/dist/pr-drafter.js +1 -1
- package/dist/prompt-firewall/index.d.ts +14 -6
- package/dist/prompt-firewall/index.d.ts.map +1 -1
- package/dist/prompt-firewall.js +7 -6
- package/dist/refactor-suggester/index.d.ts.map +1 -1
- package/dist/refactor-suggester.js +69 -56
- package/dist/release-notes-generator/index.d.ts +3 -1
- package/dist/release-notes-generator/index.d.ts.map +1 -1
- package/dist/release-notes-generator.js +152 -12
- package/dist/runtime/index.d.ts +36 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/llm.d.ts +33 -0
- package/dist/runtime/llm.d.ts.map +1 -0
- package/dist/runtime.js +119 -25
- package/dist/schema-evolution-guard/index.d.ts.map +1 -1
- package/dist/schema-evolution-guard.js +22 -13
- package/dist/secret-scanner/index.d.ts.map +1 -1
- package/dist/secret-scanner.js +17 -6
- package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
- package/dist/security-hotspot-scanner.js +24 -15
- package/dist/session-recap.js +1 -1
- package/dist/spec-linker.js +1167 -1048
- package/dist/test-generator/index.d.ts +5 -3
- package/dist/test-generator/index.d.ts.map +1 -1
- package/dist/test-generator.js +169 -26
- package/dist/test-runner-gate/index.d.ts.map +1 -1
- package/dist/test-runner-gate.js +65 -43
- package/dist/type-gate/index.d.ts.map +1 -1
- package/dist/type-gate.js +23 -35
- package/package.json +3 -3
package/dist/secret-scanner.js
CHANGED
|
@@ -55,6 +55,8 @@ var BASE_PATTERNS = [
|
|
|
55
55
|
];
|
|
56
56
|
var PATTERNS = [...BASE_PATTERNS];
|
|
57
57
|
var COMBINED_REGEX = buildCombinedRegex(PATTERNS);
|
|
58
|
+
var RE_DOS_MAX_SCAN_LENGTH = 1e5;
|
|
59
|
+
var RE_DOS_TIMEOUT_MS = 100;
|
|
58
60
|
function buildCombinedRegex(patterns) {
|
|
59
61
|
return new RegExp(patterns.map((p) => `(${p.regex.source})`).join("|"), "g");
|
|
60
62
|
}
|
|
@@ -75,10 +77,17 @@ var state = {
|
|
|
75
77
|
};
|
|
76
78
|
function findMatches(text) {
|
|
77
79
|
if (!text) return [];
|
|
80
|
+
if (text.length > RE_DOS_MAX_SCAN_LENGTH) return [];
|
|
78
81
|
const found = /* @__PURE__ */ new Set();
|
|
79
82
|
COMBINED_REGEX.lastIndex = 0;
|
|
80
83
|
let m;
|
|
84
|
+
const startTime = performance.now();
|
|
81
85
|
while ((m = COMBINED_REGEX.exec(text)) !== null) {
|
|
86
|
+
if (performance.now() - startTime > RE_DOS_TIMEOUT_MS) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`secret-scanner: ReDoS timeout \u2014 regex scan exceeded ${RE_DOS_TIMEOUT_MS}ms on ${text.length}-char input`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
82
91
|
for (let i = 0; i < PATTERNS.length; i++) {
|
|
83
92
|
if (m[i + 1] !== void 0) {
|
|
84
93
|
found.add(PATTERNS[i].type);
|
|
@@ -91,30 +100,32 @@ function findMatches(text) {
|
|
|
91
100
|
}
|
|
92
101
|
return Array.from(found);
|
|
93
102
|
}
|
|
94
|
-
function scanInput(input) {
|
|
103
|
+
function scanInput(input, depth = 0) {
|
|
95
104
|
if (input === null || input === void 0) return null;
|
|
105
|
+
if (depth > 50) return null;
|
|
96
106
|
if (typeof input === "string") {
|
|
97
107
|
const found = findMatches(input);
|
|
98
108
|
return found.length > 0 ? found : null;
|
|
99
109
|
}
|
|
100
110
|
if (Array.isArray(input)) {
|
|
101
111
|
for (const item of input) {
|
|
102
|
-
const found = scanInput(item);
|
|
112
|
+
const found = scanInput(item, depth + 1);
|
|
103
113
|
if (found) return found;
|
|
104
114
|
}
|
|
105
115
|
return null;
|
|
106
116
|
}
|
|
107
117
|
if (typeof input === "object") {
|
|
108
118
|
for (const value of Object.values(input)) {
|
|
109
|
-
const found = scanInput(value);
|
|
119
|
+
const found = scanInput(value, depth + 1);
|
|
110
120
|
if (found) return found;
|
|
111
121
|
}
|
|
112
122
|
return null;
|
|
113
123
|
}
|
|
114
124
|
return null;
|
|
115
125
|
}
|
|
116
|
-
function redactInput(input) {
|
|
126
|
+
function redactInput(input, depth = 0) {
|
|
117
127
|
if (input === null || input === void 0) return input;
|
|
128
|
+
if (depth > 50) return input;
|
|
118
129
|
if (typeof input === "string") {
|
|
119
130
|
return input.replace(COMBINED_REGEX, (_match, ...groups) => {
|
|
120
131
|
for (let i = 0; i < PATTERNS.length; i++) {
|
|
@@ -126,12 +137,12 @@ function redactInput(input) {
|
|
|
126
137
|
});
|
|
127
138
|
}
|
|
128
139
|
if (Array.isArray(input)) {
|
|
129
|
-
return input.map((item) => redactInput(item));
|
|
140
|
+
return input.map((item) => redactInput(item, depth + 1));
|
|
130
141
|
}
|
|
131
142
|
if (typeof input === "object") {
|
|
132
143
|
const out = {};
|
|
133
144
|
for (const [k, v] of Object.entries(input)) {
|
|
134
|
-
out[k] = redactInput(v);
|
|
145
|
+
out[k] = redactInput(v, depth + 1);
|
|
135
146
|
}
|
|
136
147
|
return out;
|
|
137
148
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security-hotspot-scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security-hotspot-scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAgQ/C,QAAA,MAAM,MAAM,EAAE,MAiQb,CAAC;eAEa,MAAM"}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
// src/security-hotspot-scanner/index.ts
|
|
2
2
|
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
|
-
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
|
|
4
|
+
|
|
5
|
+
// src/runtime/index.ts
|
|
6
|
+
import { basename, extname, isAbsolute, relative, resolve } from "node:path";
|
|
7
|
+
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
8
|
+
function hasLeadingDash(arg) {
|
|
9
|
+
return arg.length > 0 && arg.startsWith("-");
|
|
10
|
+
}
|
|
11
|
+
function withinProjectPath(projectRoot, candidate) {
|
|
12
|
+
if (candidate.length === 0 || candidate.length > 4096) return false;
|
|
13
|
+
if (hasLeadingDash(candidate)) return false;
|
|
14
|
+
const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
|
|
15
|
+
const rel = relative(projectRoot, resolved);
|
|
16
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
17
|
+
}
|
|
18
|
+
function withinProject(p) {
|
|
19
|
+
return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/security-hotspot-scanner/index.ts
|
|
4
23
|
var API_VERSION = "^0.1.10";
|
|
5
24
|
var state = {
|
|
6
25
|
scanCount: 0,
|
|
@@ -82,20 +101,10 @@ function isSourceFile(filePath, extensions) {
|
|
|
82
101
|
const lower = filePath.toLowerCase();
|
|
83
102
|
return extensions.some((ext) => lower.endsWith(ext));
|
|
84
103
|
}
|
|
85
|
-
function withinProject(p) {
|
|
86
|
-
if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
|
|
87
|
-
const root = process.cwd();
|
|
88
|
-
const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
|
|
89
|
-
const rel = relative(root, resolved);
|
|
90
|
-
if (rel === "" || rel === ".") return true;
|
|
91
|
-
if (rel.startsWith("..")) return false;
|
|
92
|
-
if (isAbsolute(rel)) return false;
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
104
|
function scanPath(inputPath, cfg) {
|
|
96
105
|
const start = Date.now();
|
|
97
106
|
const root = process.cwd();
|
|
98
|
-
const resolved =
|
|
107
|
+
const resolved = isAbsolute2(inputPath) ? resolve2(inputPath) : resolve2(root, inputPath);
|
|
99
108
|
if (!withinProject(inputPath)) {
|
|
100
109
|
return {
|
|
101
110
|
path: inputPath,
|
|
@@ -116,7 +125,7 @@ function scanPath(inputPath, cfg) {
|
|
|
116
125
|
filesScanned += 1;
|
|
117
126
|
const findings = scanSource(content, maxPerFile);
|
|
118
127
|
for (const f of findings) {
|
|
119
|
-
allFindings.push({ ...f, snippet: `${
|
|
128
|
+
allFindings.push({ ...f, snippet: `${relative2(root, filePath)}:${f.line}: ${f.snippet}` });
|
|
120
129
|
if (allFindings.length >= cfg.maxFindings) return;
|
|
121
130
|
}
|
|
122
131
|
} catch {
|
|
@@ -131,7 +140,7 @@ function scanPath(inputPath, cfg) {
|
|
|
131
140
|
}
|
|
132
141
|
for (const entry of entries) {
|
|
133
142
|
if (allFindings.length >= cfg.maxFindings) return;
|
|
134
|
-
const full =
|
|
143
|
+
const full = resolve2(dir, entry);
|
|
135
144
|
try {
|
|
136
145
|
const st = statSync(full);
|
|
137
146
|
if (st.isDirectory()) {
|
|
@@ -279,7 +288,7 @@ Review or remove the risky pattern(s).`;
|
|
|
279
288
|
}
|
|
280
289
|
return { additionalContext: message };
|
|
281
290
|
};
|
|
282
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
291
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
283
292
|
api.tools.register({
|
|
284
293
|
name: "security_hotspot_scan",
|
|
285
294
|
description: "Scan a file or directory for security anti-patterns (eval, Function constructor, innerHTML, SQL concatenation, http URLs, credential logging, variable exec commands).",
|
package/dist/session-recap.js
CHANGED
|
@@ -106,7 +106,7 @@ var plugin = {
|
|
|
106
106
|
version: "0.1.0",
|
|
107
107
|
description: "Stop hook that posts a one-page session summary (tokens, tools, commits, last activity) to the project mailbox",
|
|
108
108
|
apiVersion: "^0.1.10",
|
|
109
|
-
capabilities: { tools: true, hooks: true },
|
|
109
|
+
capabilities: { tools: true, hooks: true, llm: true },
|
|
110
110
|
defaultConfig: { ...DEFAULTS },
|
|
111
111
|
configSchema: {
|
|
112
112
|
type: "object",
|