@kevinrabun/judges 3.55.0 → 3.57.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/api-versioning-audit.d.ts +6 -0
- package/dist/commands/api-versioning-audit.d.ts.map +1 -0
- package/dist/commands/api-versioning-audit.js +234 -0
- package/dist/commands/api-versioning-audit.js.map +1 -0
- package/dist/commands/boundary-enforce.d.ts +6 -0
- package/dist/commands/boundary-enforce.d.ts.map +1 -0
- package/dist/commands/boundary-enforce.js +256 -0
- package/dist/commands/boundary-enforce.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/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/error-taxonomy.d.ts +6 -0
- package/dist/commands/error-taxonomy.d.ts.map +1 -0
- package/dist/commands/error-taxonomy.js +227 -0
- package/dist/commands/error-taxonomy.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/log-quality.d.ts +6 -0
- package/dist/commands/log-quality.d.ts.map +1 -0
- package/dist/commands/log-quality.js +212 -0
- package/dist/commands/log-quality.js.map +1 -0
- package/dist/commands/null-safety-audit.d.ts +6 -0
- package/dist/commands/null-safety-audit.d.ts.map +1 -0
- package/dist/commands/null-safety-audit.js +222 -0
- package/dist/commands/null-safety-audit.js.map +1 -0
- package/dist/commands/ownership-map.d.ts +6 -0
- package/dist/commands/ownership-map.d.ts.map +1 -0
- package/dist/commands/ownership-map.js +229 -0
- package/dist/commands/ownership-map.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/retry-pattern-audit.d.ts +6 -0
- package/dist/commands/retry-pattern-audit.d.ts.map +1 -0
- package/dist/commands/retry-pattern-audit.js +216 -0
- package/dist/commands/retry-pattern-audit.js.map +1 -0
- package/dist/commands/test-isolation.d.ts +6 -0
- package/dist/commands/test-isolation.d.ts.map +1 -0
- package/dist/commands/test-isolation.js +235 -0
- package/dist/commands/test-isolation.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,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeout audit — trace timeout and deadline settings through call chains.
|
|
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
|
+
for (let i = 0; i < lines.length; i++) {
|
|
52
|
+
const line = lines[i];
|
|
53
|
+
// Hardcoded timeout values
|
|
54
|
+
const hardcodedMatch = line.match(/timeout\s*[:=]\s*(\d+)/i);
|
|
55
|
+
if (hardcodedMatch) {
|
|
56
|
+
const val = parseInt(hardcodedMatch[1], 10);
|
|
57
|
+
if (val > 0 && !line.includes("config") && !line.includes("option") && !line.includes("env")) {
|
|
58
|
+
issues.push({
|
|
59
|
+
file: filepath,
|
|
60
|
+
line: i + 1,
|
|
61
|
+
issue: "Hardcoded timeout value",
|
|
62
|
+
severity: "medium",
|
|
63
|
+
detail: `Timeout = ${val}${val >= 1000 ? "ms" : ""} — extract to configuration for tunability`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Missing timeout on fetch/axios/http calls
|
|
68
|
+
if (/(?:fetch|axios|http\.(?:get|post|put|delete|request)|got|superagent)\s*\(/.test(line)) {
|
|
69
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
70
|
+
if (!/timeout|signal|AbortController|deadline/i.test(block)) {
|
|
71
|
+
issues.push({
|
|
72
|
+
file: filepath,
|
|
73
|
+
line: i + 1,
|
|
74
|
+
issue: "HTTP call without timeout",
|
|
75
|
+
severity: "high",
|
|
76
|
+
detail: "Network call has no timeout — can hang indefinitely under failure conditions",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Missing timeout on database queries
|
|
81
|
+
if (/\.(?:query|execute|find|findOne|aggregate|raw)\s*\(/.test(line)) {
|
|
82
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
83
|
+
if (/(?:db|pool|connection|prisma|knex|sequelize|mongo)/i.test(block) &&
|
|
84
|
+
!/timeout|maxTimeMS|statement_timeout/i.test(block)) {
|
|
85
|
+
issues.push({
|
|
86
|
+
file: filepath,
|
|
87
|
+
line: i + 1,
|
|
88
|
+
issue: "Database query without timeout",
|
|
89
|
+
severity: "medium",
|
|
90
|
+
detail: "DB query has no timeout — long-running queries can exhaust connection pool",
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// setTimeout with very large values
|
|
95
|
+
const setTimeoutMatch = line.match(/setTimeout\s*\([^,]+,\s*(\d+)\)/);
|
|
96
|
+
if (setTimeoutMatch) {
|
|
97
|
+
const val = parseInt(setTimeoutMatch[1], 10);
|
|
98
|
+
if (val > 300000) {
|
|
99
|
+
issues.push({
|
|
100
|
+
file: filepath,
|
|
101
|
+
line: i + 1,
|
|
102
|
+
issue: "Excessive setTimeout delay",
|
|
103
|
+
severity: "low",
|
|
104
|
+
detail: `setTimeout delay = ${Math.round(val / 1000)}s — consider persistent scheduling instead`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Promise.race without timeout
|
|
109
|
+
if (/Promise\.all\s*\(/.test(line)) {
|
|
110
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
111
|
+
if (!/timeout|Promise\.race|AbortController/i.test(block)) {
|
|
112
|
+
issues.push({
|
|
113
|
+
file: filepath,
|
|
114
|
+
line: i + 1,
|
|
115
|
+
issue: "Promise.all without timeout guard",
|
|
116
|
+
severity: "medium",
|
|
117
|
+
detail: "Promise.all can hang if any promise never resolves — wrap with Promise.race timeout",
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Upstream vs downstream timeout mismatch (heuristic)
|
|
122
|
+
if (/server.*timeout|listen.*timeout|request.*timeout/i.test(line)) {
|
|
123
|
+
const downstreamBlock = lines.slice(i, Math.min(i + 30, lines.length)).join("\n");
|
|
124
|
+
const serverTimeout = line.match(/timeout\s*[:=]\s*(\d+)/i);
|
|
125
|
+
const clientTimeout = downstreamBlock.match(/(?:fetch|axios|http).*timeout\s*[:=]\s*(\d+)/i);
|
|
126
|
+
if (serverTimeout && clientTimeout) {
|
|
127
|
+
const server = parseInt(serverTimeout[1], 10);
|
|
128
|
+
const client = parseInt(clientTimeout[1], 10);
|
|
129
|
+
if (client > server) {
|
|
130
|
+
issues.push({
|
|
131
|
+
file: filepath,
|
|
132
|
+
line: i + 1,
|
|
133
|
+
issue: "Downstream timeout exceeds upstream",
|
|
134
|
+
severity: "high",
|
|
135
|
+
detail: `Client timeout (${client}) > server timeout (${server}) — response may be dropped after server times out`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// gRPC / streaming without deadline
|
|
141
|
+
if (/grpc|\.stream\s*\(|createReadStream|createWriteStream/i.test(line)) {
|
|
142
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
143
|
+
if (!/deadline|timeout|destroy|abort/i.test(block)) {
|
|
144
|
+
issues.push({
|
|
145
|
+
file: filepath,
|
|
146
|
+
line: i + 1,
|
|
147
|
+
issue: "Stream/gRPC call without deadline",
|
|
148
|
+
severity: "medium",
|
|
149
|
+
detail: "Streaming call has no deadline — can leak resources if peer becomes unresponsive",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return issues;
|
|
155
|
+
}
|
|
156
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
157
|
+
export function runTimeoutAudit(argv) {
|
|
158
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
159
|
+
console.log(`
|
|
160
|
+
judges timeout-audit — Trace timeout and deadline propagation gaps
|
|
161
|
+
|
|
162
|
+
Usage:
|
|
163
|
+
judges timeout-audit [dir]
|
|
164
|
+
judges timeout-audit src/ --format json
|
|
165
|
+
|
|
166
|
+
Options:
|
|
167
|
+
[dir] Directory to scan (default: .)
|
|
168
|
+
--format json JSON output
|
|
169
|
+
--help, -h Show this help
|
|
170
|
+
|
|
171
|
+
Checks: missing HTTP timeouts, hardcoded values, DB query timeouts,
|
|
172
|
+
excessive setTimeout, Promise.all without guards, downstream > upstream mismatch.
|
|
173
|
+
`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
177
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
178
|
+
const files = collectFiles(dir);
|
|
179
|
+
const allIssues = [];
|
|
180
|
+
for (const f of files)
|
|
181
|
+
allIssues.push(...analyzeFile(f));
|
|
182
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
183
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
184
|
+
const score = Math.max(0, 100 - highCount * 10 - medCount * 4);
|
|
185
|
+
if (format === "json") {
|
|
186
|
+
console.log(JSON.stringify({
|
|
187
|
+
issues: allIssues,
|
|
188
|
+
score,
|
|
189
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
190
|
+
timestamp: new Date().toISOString(),
|
|
191
|
+
}, null, 2));
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
const badge = score >= 80 ? "✅ ROBUST" : score >= 50 ? "⚠️ GAPS" : "❌ FRAGILE";
|
|
195
|
+
console.log(`\n Timeout Safety: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
196
|
+
if (allIssues.length === 0) {
|
|
197
|
+
console.log(" No timeout issues detected.\n");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
201
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
202
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
203
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
204
|
+
console.log(` ${issue.detail}`);
|
|
205
|
+
}
|
|
206
|
+
if (allIssues.length > 25)
|
|
207
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
208
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=timeout-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout-audit.js","sourceRoot":"","sources":["../../src/commands/timeout-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-boundary.d.ts","sourceRoot":"","sources":["../../src/commands/type-boundary.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyMH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAgEpD"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type boundary — check type safety at serialization boundaries.
|
|
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
|
+
for (let i = 0; i < lines.length; i++) {
|
|
52
|
+
const line = lines[i];
|
|
53
|
+
// JSON.parse without validation
|
|
54
|
+
if (/JSON\.parse\s*\(/.test(line)) {
|
|
55
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
56
|
+
// Check for type assertion without validation
|
|
57
|
+
if (/as\s+\w+/.test(line) || /as\s+\w+/.test(lines[i + 1] || "")) {
|
|
58
|
+
if (!/zod|joi|yup|ajv|validate|schema|assert|guard|is\w+\(/i.test(block)) {
|
|
59
|
+
issues.push({
|
|
60
|
+
file: filepath,
|
|
61
|
+
line: i + 1,
|
|
62
|
+
issue: "JSON.parse with unchecked type assertion",
|
|
63
|
+
severity: "high",
|
|
64
|
+
detail: "Type assertion on parsed JSON without runtime validation — external data shape is unverified",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// JSON.parse returning any without narrowing
|
|
69
|
+
if (!/:\s*\w+\s*=|as\s+\w+|validate|parse|schema/i.test(line) && !/validate|schema|guard/i.test(block)) {
|
|
70
|
+
issues.push({
|
|
71
|
+
file: filepath,
|
|
72
|
+
line: i + 1,
|
|
73
|
+
issue: "JSON.parse result used without validation",
|
|
74
|
+
severity: "medium",
|
|
75
|
+
detail: "Parsed JSON used directly — add runtime type checking for external data",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Unchecked 'as' cast on external data sources
|
|
80
|
+
if (/\bas\s+(?!const\b)\w+/.test(line)) {
|
|
81
|
+
if (/(?:response|body|data|result|payload|params|query|req\.|res\.)/.test(line)) {
|
|
82
|
+
const block = lines.slice(Math.max(0, i - 3), Math.min(i + 3, lines.length)).join("\n");
|
|
83
|
+
if (!/validate|schema|guard|assert|instanceof|typeof|zod|joi|ajv/i.test(block)) {
|
|
84
|
+
issues.push({
|
|
85
|
+
file: filepath,
|
|
86
|
+
line: i + 1,
|
|
87
|
+
issue: "Type assertion on external data",
|
|
88
|
+
severity: "high",
|
|
89
|
+
detail: "Casting external data with 'as' bypasses type safety — validate at boundary",
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// @ts-ignore or @ts-expect-error suppressing boundary checks
|
|
95
|
+
if (/@ts-ignore|@ts-expect-error/.test(line)) {
|
|
96
|
+
const nextLine = lines[i + 1] || "";
|
|
97
|
+
if (/parse|response|body|fetch|axios|request|query/i.test(nextLine)) {
|
|
98
|
+
issues.push({
|
|
99
|
+
file: filepath,
|
|
100
|
+
line: i + 1,
|
|
101
|
+
issue: "Type suppression at data boundary",
|
|
102
|
+
severity: "high",
|
|
103
|
+
detail: "ts-ignore/ts-expect-error hides type errors at external boundary — fix the types instead",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// any type at API boundary
|
|
108
|
+
if (/:\s*any\b/.test(line)) {
|
|
109
|
+
if (/(?:request|response|handler|controller|route|api|endpoint|middleware)/i.test(line) ||
|
|
110
|
+
/(?:req|res|ctx|context|body|params|query)/i.test(line)) {
|
|
111
|
+
issues.push({
|
|
112
|
+
file: filepath,
|
|
113
|
+
line: i + 1,
|
|
114
|
+
issue: "'any' type at API boundary",
|
|
115
|
+
severity: "medium",
|
|
116
|
+
detail: "Using 'any' at API boundary loses type safety — define explicit request/response types",
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// SQL query results used without type checking
|
|
121
|
+
if (/\.query\s*\(|\.raw\s*\(|\.execute\s*\(/.test(line)) {
|
|
122
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
123
|
+
if (/as\s+\w+/.test(block) && !/validate|schema|guard|rows\.\w+/i.test(block)) {
|
|
124
|
+
issues.push({
|
|
125
|
+
file: filepath,
|
|
126
|
+
line: i + 1,
|
|
127
|
+
issue: "SQL result with unchecked type assertion",
|
|
128
|
+
severity: "medium",
|
|
129
|
+
detail: "Query result cast without validation — column types may differ from TypeScript types",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// process.env without validation
|
|
134
|
+
if (/process\.env\.\w+/.test(line)) {
|
|
135
|
+
if (!/!\s*$|as\s+string|\?\?|[|][|]|if\s*\(|assert|env.*schema|zod|joi/i.test(line)) {
|
|
136
|
+
// Only flag if used directly without null check
|
|
137
|
+
const block = lines.slice(Math.max(0, i - 2), Math.min(i + 2, lines.length)).join("\n");
|
|
138
|
+
if (!/if\s*\(|[?][?]|\|\||assert|throw|env.*config/i.test(block)) {
|
|
139
|
+
issues.push({
|
|
140
|
+
file: filepath,
|
|
141
|
+
line: i + 1,
|
|
142
|
+
issue: "process.env used without validation",
|
|
143
|
+
severity: "low",
|
|
144
|
+
detail: "Environment variable used without null check — may be undefined at runtime",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// FormData/URLSearchParams parsed without validation
|
|
150
|
+
if (/FormData|URLSearchParams|formData|searchParams/i.test(line) && /\.get\s*\(/.test(line)) {
|
|
151
|
+
const block = lines.slice(i, Math.min(i + 3, lines.length)).join("\n");
|
|
152
|
+
if (!/validate|schema|typeof|instanceof|zod|joi/i.test(block)) {
|
|
153
|
+
if (/as\s+\w+/.test(block)) {
|
|
154
|
+
issues.push({
|
|
155
|
+
file: filepath,
|
|
156
|
+
line: i + 1,
|
|
157
|
+
issue: "Form data cast without validation",
|
|
158
|
+
severity: "medium",
|
|
159
|
+
detail: "Form/URL params cast without validation — user input shape is unverified",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Protobuf/gRPC decode without validation
|
|
165
|
+
if (/\.decode\s*\(|\.deserialize|\.fromBinary|\.fromJSON/i.test(line)) {
|
|
166
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
167
|
+
if (!/validate|verify|check|schema/i.test(block)) {
|
|
168
|
+
issues.push({
|
|
169
|
+
file: filepath,
|
|
170
|
+
line: i + 1,
|
|
171
|
+
issue: "Deserialization without validation",
|
|
172
|
+
severity: "medium",
|
|
173
|
+
detail: "Decoded protobuf/binary data not validated — may contain unexpected fields or types",
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return issues;
|
|
179
|
+
}
|
|
180
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
181
|
+
export function runTypeBoundary(argv) {
|
|
182
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
183
|
+
console.log(`
|
|
184
|
+
judges type-boundary — Check type safety at serialization boundaries
|
|
185
|
+
|
|
186
|
+
Usage:
|
|
187
|
+
judges type-boundary [dir]
|
|
188
|
+
judges type-boundary src/ --format json
|
|
189
|
+
|
|
190
|
+
Options:
|
|
191
|
+
[dir] Directory to scan (default: .)
|
|
192
|
+
--format json JSON output
|
|
193
|
+
--help, -h Show this help
|
|
194
|
+
|
|
195
|
+
Checks: JSON.parse without validation, unchecked 'as' casts on external data,
|
|
196
|
+
ts-ignore at boundaries, 'any' at API boundaries, SQL result casting,
|
|
197
|
+
unvalidated env vars, form data casting, protobuf decode.
|
|
198
|
+
`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
202
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
203
|
+
const files = collectFiles(dir);
|
|
204
|
+
const allIssues = [];
|
|
205
|
+
for (const f of files)
|
|
206
|
+
allIssues.push(...analyzeFile(f));
|
|
207
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
208
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
209
|
+
const score = Math.max(0, 100 - highCount * 8 - medCount * 3);
|
|
210
|
+
if (format === "json") {
|
|
211
|
+
console.log(JSON.stringify({
|
|
212
|
+
issues: allIssues,
|
|
213
|
+
score,
|
|
214
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
215
|
+
timestamp: new Date().toISOString(),
|
|
216
|
+
}, null, 2));
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
const badge = score >= 80 ? "✅ SAFE" : score >= 50 ? "⚠️ LEAKY" : "❌ UNSAFE";
|
|
220
|
+
console.log(`\n Type Boundaries: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
221
|
+
if (allIssues.length === 0) {
|
|
222
|
+
console.log(" No type boundary issues detected.\n");
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
226
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
227
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
228
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
229
|
+
console.log(` ${issue.detail}`);
|
|
230
|
+
}
|
|
231
|
+
if (allIssues.length > 25)
|
|
232
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
233
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=type-boundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-boundary.js","sourceRoot":"","sources":["../../src/commands/type-boundary.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/kevinrabun/judges",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "3.
|
|
10
|
+
"version": "3.57.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@kevinrabun/judges",
|
|
15
|
-
"version": "3.
|
|
15
|
+
"version": "3.57.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|