@kevinrabun/judges 3.56.0 → 3.58.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/CHANGELOG.md +24 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/assertion-density.d.ts +5 -0
- package/dist/commands/assertion-density.d.ts.map +1 -0
- package/dist/commands/assertion-density.js +264 -0
- package/dist/commands/assertion-density.js.map +1 -0
- package/dist/commands/async-safety.d.ts +5 -0
- package/dist/commands/async-safety.d.ts.map +1 -0
- package/dist/commands/async-safety.js +267 -0
- package/dist/commands/async-safety.js.map +1 -0
- package/dist/commands/cache-audit.d.ts +5 -0
- package/dist/commands/cache-audit.d.ts.map +1 -0
- package/dist/commands/cache-audit.js +220 -0
- package/dist/commands/cache-audit.js.map +1 -0
- package/dist/commands/clone-detect.d.ts +5 -0
- package/dist/commands/clone-detect.d.ts.map +1 -0
- package/dist/commands/clone-detect.js +233 -0
- package/dist/commands/clone-detect.js.map +1 -0
- package/dist/commands/comment-drift.d.ts +5 -0
- package/dist/commands/comment-drift.d.ts.map +1 -0
- package/dist/commands/comment-drift.js +229 -0
- package/dist/commands/comment-drift.js.map +1 -0
- package/dist/commands/contract-verify.d.ts +5 -0
- package/dist/commands/contract-verify.d.ts.map +1 -0
- package/dist/commands/contract-verify.js +317 -0
- package/dist/commands/contract-verify.js.map +1 -0
- package/dist/commands/dead-code-detect.d.ts +5 -0
- package/dist/commands/dead-code-detect.d.ts.map +1 -0
- package/dist/commands/dead-code-detect.js +256 -0
- package/dist/commands/dead-code-detect.js.map +1 -0
- package/dist/commands/encoding-safety.d.ts +5 -0
- package/dist/commands/encoding-safety.d.ts.map +1 -0
- package/dist/commands/encoding-safety.js +276 -0
- package/dist/commands/encoding-safety.js.map +1 -0
- package/dist/commands/error-ux.d.ts +5 -0
- package/dist/commands/error-ux.d.ts.map +1 -0
- package/dist/commands/error-ux.js +253 -0
- package/dist/commands/error-ux.js.map +1 -0
- package/dist/commands/event-leak.d.ts +5 -0
- package/dist/commands/event-leak.d.ts.map +1 -0
- package/dist/commands/event-leak.js +263 -0
- package/dist/commands/event-leak.js.map +1 -0
- package/dist/commands/idempotency-audit.d.ts +5 -0
- package/dist/commands/idempotency-audit.d.ts.map +1 -0
- package/dist/commands/idempotency-audit.js +223 -0
- package/dist/commands/idempotency-audit.js.map +1 -0
- package/dist/commands/input-guard.d.ts +5 -0
- package/dist/commands/input-guard.d.ts.map +1 -0
- package/dist/commands/input-guard.js +256 -0
- package/dist/commands/input-guard.js.map +1 -0
- package/dist/commands/privilege-path.d.ts +5 -0
- package/dist/commands/privilege-path.d.ts.map +1 -0
- package/dist/commands/privilege-path.js +234 -0
- package/dist/commands/privilege-path.js.map +1 -0
- package/dist/commands/state-integrity.d.ts +5 -0
- package/dist/commands/state-integrity.d.ts.map +1 -0
- package/dist/commands/state-integrity.js +284 -0
- package/dist/commands/state-integrity.js.map +1 -0
- package/dist/commands/timeout-audit.d.ts +5 -0
- package/dist/commands/timeout-audit.d.ts.map +1 -0
- package/dist/commands/timeout-audit.js +211 -0
- package/dist/commands/timeout-audit.js.map +1 -0
- package/dist/commands/type-boundary.d.ts +5 -0
- package/dist/commands/type-boundary.d.ts.map +1 -0
- package/dist/commands/type-boundary.js +236 -0
- package/dist/commands/type-boundary.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privilege path — model authorization flows to find privilege-escalation paths.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, extname } from "path";
|
|
6
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
7
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs"]);
|
|
8
|
+
function collectFiles(dir, max = 300) {
|
|
9
|
+
const files = [];
|
|
10
|
+
function walk(d) {
|
|
11
|
+
if (files.length >= max)
|
|
12
|
+
return;
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(d);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const e of entries) {
|
|
21
|
+
if (files.length >= max)
|
|
22
|
+
return;
|
|
23
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
24
|
+
continue;
|
|
25
|
+
const full = join(d, e);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(full).isDirectory())
|
|
28
|
+
walk(full);
|
|
29
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
30
|
+
files.push(full);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* skip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
walk(dir);
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
41
|
+
function analyzeFile(filepath) {
|
|
42
|
+
const issues = [];
|
|
43
|
+
let content;
|
|
44
|
+
try {
|
|
45
|
+
content = readFileSync(filepath, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return issues;
|
|
49
|
+
}
|
|
50
|
+
const lines = content.split("\n");
|
|
51
|
+
const fullText = content;
|
|
52
|
+
// Detect route/endpoint definitions
|
|
53
|
+
const isRouteFile = /(?:router|app)\.\s*(?:get|post|put|delete|patch|all)\s*\(|@(?:GET|POST|PUT|DELETE|PATCH|Controller|RequestMapping)/i.test(fullText);
|
|
54
|
+
for (let i = 0; i < lines.length; i++) {
|
|
55
|
+
const line = lines[i];
|
|
56
|
+
// Route without auth middleware
|
|
57
|
+
if (/(?:router|app)\.\s*(?:get|post|put|delete|patch)\s*\(\s*['"]([^'"]+)['"]/.test(line)) {
|
|
58
|
+
const routeMatch = line.match(/(?:router|app)\.\s*(?:get|post|put|delete|patch)\s*\(\s*['"]([^'"]+)['"]/);
|
|
59
|
+
if (routeMatch) {
|
|
60
|
+
const route = routeMatch[1];
|
|
61
|
+
const block = lines.slice(i, Math.min(i + 3, lines.length)).join("\n");
|
|
62
|
+
// Skip public routes
|
|
63
|
+
if (!/(?:health|status|ping|public|login|register|signup|webhook|callback)/i.test(route)) {
|
|
64
|
+
if (!/auth|authenticate|authorize|requireAuth|isAuthenticated|passport|guard|protect|jwt|token|session/i.test(block)) {
|
|
65
|
+
issues.push({
|
|
66
|
+
file: filepath,
|
|
67
|
+
line: i + 1,
|
|
68
|
+
issue: "Route without authentication middleware",
|
|
69
|
+
severity: "high",
|
|
70
|
+
detail: `${route} — no auth middleware detected; endpoint may be publicly accessible`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// IDOR: user ID from request used directly in query
|
|
77
|
+
if (/(?:req\.params|req\.query|req\.body|request\.\w+)\.\s*(?:id|userId|user_id)/i.test(line)) {
|
|
78
|
+
const block = lines.slice(i, Math.min(i + 8, lines.length)).join("\n");
|
|
79
|
+
if (/(?:findById|findOne|where|SELECT|DELETE|UPDATE)\s*\(/i.test(block)) {
|
|
80
|
+
if (!/req\.user|currentUser|session\.user|token\.sub|auth\.user/i.test(block)) {
|
|
81
|
+
issues.push({
|
|
82
|
+
file: filepath,
|
|
83
|
+
line: i + 1,
|
|
84
|
+
issue: "Potential IDOR — user ID from request without ownership check",
|
|
85
|
+
severity: "high",
|
|
86
|
+
detail: "User-supplied ID used in query without verifying ownership — attacker can access other users' data",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Role check using string comparison (fragile)
|
|
92
|
+
if (/role\s*===?\s*['"]admin['"]|role\s*===?\s*['"]superadmin['"]/i.test(line)) {
|
|
93
|
+
if (!/enum|const\s+ROLES|Role\./i.test(fullText)) {
|
|
94
|
+
issues.push({
|
|
95
|
+
file: filepath,
|
|
96
|
+
line: i + 1,
|
|
97
|
+
issue: "Role check with magic string",
|
|
98
|
+
severity: "medium",
|
|
99
|
+
detail: "Role comparison uses magic string — use enum/constant to prevent typo-based bypass",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Privilege escalation: self-assign role
|
|
104
|
+
if (/role|isAdmin|is_admin|permissions/i.test(line) && /req\.body|request\.body/i.test(line)) {
|
|
105
|
+
issues.push({
|
|
106
|
+
file: filepath,
|
|
107
|
+
line: i + 1,
|
|
108
|
+
issue: "Role/permission from user input",
|
|
109
|
+
severity: "high",
|
|
110
|
+
detail: "Role or permission value taken from request body — user can self-escalate privileges",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// Missing authorization on destructive operations
|
|
114
|
+
if (/\.(?:delete|destroy|remove|drop|truncate)\s*\(/i.test(line) && isRouteFile) {
|
|
115
|
+
const contextBlock = lines.slice(Math.max(0, i - 10), i + 1).join("\n");
|
|
116
|
+
if (!/authorize|permission|role|isAdmin|canDelete|allowed/i.test(contextBlock)) {
|
|
117
|
+
issues.push({
|
|
118
|
+
file: filepath,
|
|
119
|
+
line: i + 1,
|
|
120
|
+
issue: "Destructive operation without authorization check",
|
|
121
|
+
severity: "high",
|
|
122
|
+
detail: "Delete/destroy called without prior authorization — any authenticated user may execute it",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// JWT token without signature verification
|
|
127
|
+
if (/jwt\.decode\s*\(/.test(line)) {
|
|
128
|
+
if (!/jwt\.verify|jsonwebtoken.*verify/i.test(fullText)) {
|
|
129
|
+
issues.push({
|
|
130
|
+
file: filepath,
|
|
131
|
+
line: i + 1,
|
|
132
|
+
issue: "JWT decoded without verification",
|
|
133
|
+
severity: "high",
|
|
134
|
+
detail: "jwt.decode() does NOT verify signature — use jwt.verify() to prevent token forgery",
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Hardcoded secrets/tokens in auth logic
|
|
139
|
+
if (/(?:secret|password|token|apiKey|api_key)\s*[:=]\s*['"][^'"]{8,}['"]/i.test(line)) {
|
|
140
|
+
if (!/test|spec|mock|fixture|example|sample/i.test(filepath)) {
|
|
141
|
+
issues.push({
|
|
142
|
+
file: filepath,
|
|
143
|
+
line: i + 1,
|
|
144
|
+
issue: "Hardcoded credential in auth logic",
|
|
145
|
+
severity: "high",
|
|
146
|
+
detail: "Secret/token hardcoded in source — extract to environment variable or secret manager",
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Session fixation: session ID not regenerated after login
|
|
151
|
+
if (/login|authenticate|signIn/i.test(line) && /function|=>|async/.test(line)) {
|
|
152
|
+
const funcBlock = lines.slice(i, Math.min(i + 30, lines.length)).join("\n");
|
|
153
|
+
if (/session/i.test(funcBlock) && !/regenerate|destroy.*session|req\.session\s*=\s*null/i.test(funcBlock)) {
|
|
154
|
+
issues.push({
|
|
155
|
+
file: filepath,
|
|
156
|
+
line: i + 1,
|
|
157
|
+
issue: "Session not regenerated after login",
|
|
158
|
+
severity: "medium",
|
|
159
|
+
detail: "Session ID persists across auth boundary — regenerate to prevent session fixation",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// CORS: wildcard origin with credentials
|
|
164
|
+
if (/origin\s*:\s*['"]\*['"]|origin\s*:\s*true/.test(line)) {
|
|
165
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
166
|
+
if (/credentials\s*:\s*true/i.test(block)) {
|
|
167
|
+
issues.push({
|
|
168
|
+
file: filepath,
|
|
169
|
+
line: i + 1,
|
|
170
|
+
issue: "CORS wildcard with credentials",
|
|
171
|
+
severity: "high",
|
|
172
|
+
detail: "Wildcard origin with credentials allows any site to make authenticated requests",
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return issues;
|
|
178
|
+
}
|
|
179
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
180
|
+
export function runPrivilegePath(argv) {
|
|
181
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
182
|
+
console.log(`
|
|
183
|
+
judges privilege-path — Model authorization flows to find escalation paths
|
|
184
|
+
|
|
185
|
+
Usage:
|
|
186
|
+
judges privilege-path [dir]
|
|
187
|
+
judges privilege-path src/ --format json
|
|
188
|
+
|
|
189
|
+
Options:
|
|
190
|
+
[dir] Directory to scan (default: .)
|
|
191
|
+
--format json JSON output
|
|
192
|
+
--help, -h Show this help
|
|
193
|
+
|
|
194
|
+
Checks: routes without auth, IDOR patterns, magic-string role checks, self-assigned roles,
|
|
195
|
+
unprotected destructive ops, JWT decode without verify, hardcoded secrets, session fixation, CORS.
|
|
196
|
+
`);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
200
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
201
|
+
const files = collectFiles(dir);
|
|
202
|
+
const allIssues = [];
|
|
203
|
+
for (const f of files)
|
|
204
|
+
allIssues.push(...analyzeFile(f));
|
|
205
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
206
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
207
|
+
const score = Math.max(0, 100 - highCount * 10 - medCount * 4);
|
|
208
|
+
if (format === "json") {
|
|
209
|
+
console.log(JSON.stringify({
|
|
210
|
+
issues: allIssues,
|
|
211
|
+
score,
|
|
212
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
213
|
+
timestamp: new Date().toISOString(),
|
|
214
|
+
}, null, 2));
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
const badge = score >= 80 ? "✅ SECURE" : score >= 50 ? "⚠️ GAPS" : "❌ EXPOSED";
|
|
218
|
+
console.log(`\n Privilege Safety: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
219
|
+
if (allIssues.length === 0) {
|
|
220
|
+
console.log(" No privilege escalation paths detected.\n");
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
224
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
225
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
226
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
227
|
+
console.log(` ${issue.detail}`);
|
|
228
|
+
}
|
|
229
|
+
if (allIssues.length > 25)
|
|
230
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
231
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=privilege-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"privilege-path.js","sourceRoot":"","sources":["../../src/commands/privilege-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-integrity.d.ts","sourceRoot":"","sources":["../../src/commands/state-integrity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuPH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+DtD"}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State integrity — validate state machine correctness, unreachable states, and missing transitions.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, extname } from "path";
|
|
6
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
7
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx"]);
|
|
8
|
+
function collectFiles(dir, max = 300) {
|
|
9
|
+
const files = [];
|
|
10
|
+
function walk(d) {
|
|
11
|
+
if (files.length >= max)
|
|
12
|
+
return;
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(d);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const e of entries) {
|
|
21
|
+
if (files.length >= max)
|
|
22
|
+
return;
|
|
23
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
24
|
+
continue;
|
|
25
|
+
const full = join(d, e);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(full).isDirectory())
|
|
28
|
+
walk(full);
|
|
29
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
30
|
+
files.push(full);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* skip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
walk(dir);
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
41
|
+
function analyzeFile(filepath) {
|
|
42
|
+
const issues = [];
|
|
43
|
+
let content;
|
|
44
|
+
try {
|
|
45
|
+
content = readFileSync(filepath, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return issues;
|
|
49
|
+
}
|
|
50
|
+
const lines = content.split("\n");
|
|
51
|
+
const fullText = content;
|
|
52
|
+
// Detect enum/union type definitions for states
|
|
53
|
+
const stateEnums = new Map();
|
|
54
|
+
for (let i = 0; i < lines.length; i++) {
|
|
55
|
+
const line = lines[i];
|
|
56
|
+
const enumMatch = line.match(/enum\s+(\w*(?:State|Status|Phase|Stage|Mode)\w*)\s*\{/i);
|
|
57
|
+
if (enumMatch) {
|
|
58
|
+
const enumName = enumMatch[1];
|
|
59
|
+
let depth = 0;
|
|
60
|
+
let enumEnd = i;
|
|
61
|
+
for (let j = i; j < Math.min(i + 30, lines.length); j++) {
|
|
62
|
+
for (const ch of lines[j]) {
|
|
63
|
+
if (ch === "{")
|
|
64
|
+
depth++;
|
|
65
|
+
if (ch === "}")
|
|
66
|
+
depth--;
|
|
67
|
+
}
|
|
68
|
+
if (depth <= 0 && j > i) {
|
|
69
|
+
enumEnd = j;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const enumBody = lines.slice(i + 1, enumEnd).join("\n");
|
|
74
|
+
const values = [...enumBody.matchAll(/(\w+)\s*[=,]/g)].map((m) => m[1]);
|
|
75
|
+
if (values.length > 0)
|
|
76
|
+
stateEnums.set(enumName, { values, line: i + 1 });
|
|
77
|
+
}
|
|
78
|
+
// Also detect string union types for state
|
|
79
|
+
const unionMatch = line.match(/type\s+(\w*(?:State|Status|Phase|Stage|Mode)\w*)\s*=\s*(.+)/i);
|
|
80
|
+
if (unionMatch) {
|
|
81
|
+
const typeName = unionMatch[1];
|
|
82
|
+
const rest = unionMatch[2] + (lines[i + 1] || "");
|
|
83
|
+
const values = [...rest.matchAll(/['"](\w+)['"]/g)].map((m) => m[1]);
|
|
84
|
+
if (values.length > 1)
|
|
85
|
+
stateEnums.set(typeName, { values, line: i + 1 });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Check if all enum values are handled in switch statements
|
|
89
|
+
for (const [enumName, { values }] of stateEnums) {
|
|
90
|
+
for (let i = 0; i < lines.length; i++) {
|
|
91
|
+
const line = lines[i];
|
|
92
|
+
if (/switch\s*\(/.test(line) &&
|
|
93
|
+
new RegExp(enumName, "i").test(lines.slice(Math.max(0, i - 3), i + 1).join("\n"))) {
|
|
94
|
+
let depth = 0;
|
|
95
|
+
let switchEnd = i;
|
|
96
|
+
let started = false;
|
|
97
|
+
for (let j = i; j < Math.min(i + 60, lines.length); j++) {
|
|
98
|
+
for (const ch of lines[j]) {
|
|
99
|
+
if (ch === "{") {
|
|
100
|
+
depth++;
|
|
101
|
+
started = true;
|
|
102
|
+
}
|
|
103
|
+
if (ch === "}")
|
|
104
|
+
depth--;
|
|
105
|
+
}
|
|
106
|
+
if (started && depth <= 0) {
|
|
107
|
+
switchEnd = j;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const switchBody = lines.slice(i, switchEnd + 1).join("\n");
|
|
112
|
+
const unhandled = values.filter((v) => !switchBody.includes(v));
|
|
113
|
+
if (unhandled.length > 0 && !/default\s*:/.test(switchBody)) {
|
|
114
|
+
issues.push({
|
|
115
|
+
file: filepath,
|
|
116
|
+
line: i + 1,
|
|
117
|
+
issue: "Incomplete state handling",
|
|
118
|
+
severity: "high",
|
|
119
|
+
detail: `Switch on ${enumName} missing: ${unhandled.join(", ")} — and no default case`,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
for (let i = 0; i < lines.length; i++) {
|
|
126
|
+
const line = lines[i];
|
|
127
|
+
// Impossible state combinations (boolean flags)
|
|
128
|
+
if (/(?:loading|isLoading)\s*[:=]\s*true/.test(line)) {
|
|
129
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
130
|
+
if (/(?:error|isError|hasError)\s*[:=]\s*true/.test(block)) {
|
|
131
|
+
issues.push({
|
|
132
|
+
file: filepath,
|
|
133
|
+
line: i + 1,
|
|
134
|
+
issue: "Impossible state: loading + error simultaneously",
|
|
135
|
+
severity: "medium",
|
|
136
|
+
detail: "Setting loading and error to true at the same time — use state machine to prevent impossible combinations",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Direct state mutation without transition validation
|
|
141
|
+
if (/\.(?:state|status|phase)\s*=\s*['"](\w+)['"]/.test(line)) {
|
|
142
|
+
const newState = line.match(/\.(?:state|status|phase)\s*=\s*['"](\w+)['"]/)?.[1];
|
|
143
|
+
const block = lines.slice(Math.max(0, i - 5), i + 1).join("\n");
|
|
144
|
+
if (!/if\s*\(|switch\s*\(|transition|canTransition|validate|guard|allowed/i.test(block)) {
|
|
145
|
+
issues.push({
|
|
146
|
+
file: filepath,
|
|
147
|
+
line: i + 1,
|
|
148
|
+
issue: "State mutation without transition guard",
|
|
149
|
+
severity: "medium",
|
|
150
|
+
detail: `Setting state to '${newState}' without validating transition — any state can be set from any other`,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// useState with multiple related booleans (React)
|
|
155
|
+
if (/useState\s*<?\s*boolean\s*>?\s*\(\s*(?:true|false)\s*\)/.test(line)) {
|
|
156
|
+
const block = lines.slice(i, Math.min(i + 8, lines.length)).join("\n");
|
|
157
|
+
const boolStateCount = (block.match(/useState\s*<?\s*boolean/g) || []).length;
|
|
158
|
+
if (boolStateCount >= 3) {
|
|
159
|
+
issues.push({
|
|
160
|
+
file: filepath,
|
|
161
|
+
line: i + 1,
|
|
162
|
+
issue: "Too many boolean state variables",
|
|
163
|
+
severity: "medium",
|
|
164
|
+
detail: `${boolStateCount} boolean useState calls in proximity — use discriminated union or state machine to prevent impossible states`,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Redux/Vuex: reducer with incomplete action handling
|
|
169
|
+
if (/(?:createSlice|createReducer|reducer)\s*[(:]/.test(line)) {
|
|
170
|
+
const block = lines.slice(i, Math.min(i + 40, lines.length)).join("\n");
|
|
171
|
+
if (!/default\s*:|exhaustive|never/i.test(block)) {
|
|
172
|
+
const caseCount = (block.match(/case\s+['"]?\w+['"]?\s*:|(\w+)\s*(?::\s*\(|:\s*\{)/g) || []).length;
|
|
173
|
+
if (caseCount > 0 && caseCount < 3) {
|
|
174
|
+
issues.push({
|
|
175
|
+
file: filepath,
|
|
176
|
+
line: i + 1,
|
|
177
|
+
issue: "Reducer with few cases and no default",
|
|
178
|
+
severity: "low",
|
|
179
|
+
detail: "Reducer handles few actions — ensure all action types are covered",
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// State variable set to invalid value (magic string)
|
|
185
|
+
if (/(?:state|status|phase|stage|mode)\s*[:=]\s*['"](\w+)['"]/.test(line)) {
|
|
186
|
+
const value = line.match(/(?:state|status|phase|stage|mode)\s*[:=]\s*['"](\w+)['"]/)?.[1];
|
|
187
|
+
if (value) {
|
|
188
|
+
// Check if this value is defined in any state enum or type
|
|
189
|
+
let isDefined = false;
|
|
190
|
+
for (const [_name, { values }] of stateEnums) {
|
|
191
|
+
if (values.includes(value)) {
|
|
192
|
+
isDefined = true;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Check if value is used as a type somewhere
|
|
197
|
+
if (!isDefined && fullText.includes(`'${value}'`) && !/test|spec|fixture/i.test(filepath)) {
|
|
198
|
+
const occurrences = (fullText.match(new RegExp(`['"]${value}['"]`, "g")) || []).length;
|
|
199
|
+
if (occurrences === 1) {
|
|
200
|
+
issues.push({
|
|
201
|
+
file: filepath,
|
|
202
|
+
line: i + 1,
|
|
203
|
+
issue: "State value used only once",
|
|
204
|
+
severity: "low",
|
|
205
|
+
detail: `State '${value}' appears only once — may be an orphaned or transitional state`,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Missing error state in async flow
|
|
212
|
+
if (/async\s+(?:function|=>)/.test(line) && /state|status|phase/i.test(fullText)) {
|
|
213
|
+
const block = lines.slice(i, Math.min(i + 30, lines.length)).join("\n");
|
|
214
|
+
if (/loading|pending|fetching/i.test(block)) {
|
|
215
|
+
if (!/error|failed|rejected|catch/i.test(block)) {
|
|
216
|
+
issues.push({
|
|
217
|
+
file: filepath,
|
|
218
|
+
line: i + 1,
|
|
219
|
+
issue: "Async flow missing error state",
|
|
220
|
+
severity: "medium",
|
|
221
|
+
detail: "Async operation sets loading state but has no error state — failures leave UI in loading",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return issues;
|
|
228
|
+
}
|
|
229
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
230
|
+
export function runStateIntegrity(argv) {
|
|
231
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
232
|
+
console.log(`
|
|
233
|
+
judges state-integrity — Validate state machine correctness and impossible states
|
|
234
|
+
|
|
235
|
+
Usage:
|
|
236
|
+
judges state-integrity [dir]
|
|
237
|
+
judges state-integrity src/ --format json
|
|
238
|
+
|
|
239
|
+
Options:
|
|
240
|
+
[dir] Directory to scan (default: .)
|
|
241
|
+
--format json JSON output
|
|
242
|
+
--help, -h Show this help
|
|
243
|
+
|
|
244
|
+
Checks: incomplete enum handling, impossible boolean combinations, state mutation without guards,
|
|
245
|
+
excessive boolean state, missing error states in async flows, orphaned state values.
|
|
246
|
+
`);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
250
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
251
|
+
const files = collectFiles(dir);
|
|
252
|
+
const allIssues = [];
|
|
253
|
+
for (const f of files)
|
|
254
|
+
allIssues.push(...analyzeFile(f));
|
|
255
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
256
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
257
|
+
const score = Math.max(0, 100 - highCount * 10 - medCount * 4);
|
|
258
|
+
if (format === "json") {
|
|
259
|
+
console.log(JSON.stringify({
|
|
260
|
+
issues: allIssues,
|
|
261
|
+
score,
|
|
262
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
263
|
+
timestamp: new Date().toISOString(),
|
|
264
|
+
}, null, 2));
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
const badge = score >= 80 ? "✅ SOUND" : score >= 50 ? "⚠️ FRAGILE" : "❌ BROKEN";
|
|
268
|
+
console.log(`\n State Integrity: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
269
|
+
if (allIssues.length === 0) {
|
|
270
|
+
console.log(" No state integrity issues detected.\n");
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
274
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
275
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
276
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
277
|
+
console.log(` ${issue.detail}`);
|
|
278
|
+
}
|
|
279
|
+
if (allIssues.length > 25)
|
|
280
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
281
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=state-integrity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-integrity.js","sourceRoot":"","sources":["../../src/commands/state-integrity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout-audit.d.ts","sourceRoot":"","sources":["../../src/commands/timeout-audit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgLH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+DpD"}
|