@kevinrabun/judges 1.2.0 → 1.3.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 +49 -13
- package/dist/evaluators/authentication.d.ts +3 -0
- package/dist/evaluators/authentication.d.ts.map +1 -0
- package/dist/evaluators/authentication.js +103 -0
- package/dist/evaluators/authentication.js.map +1 -0
- package/dist/evaluators/backwards-compatibility.d.ts +3 -0
- package/dist/evaluators/backwards-compatibility.d.ts.map +1 -0
- package/dist/evaluators/backwards-compatibility.js +76 -0
- package/dist/evaluators/backwards-compatibility.js.map +1 -0
- package/dist/evaluators/caching.d.ts +3 -0
- package/dist/evaluators/caching.d.ts.map +1 -0
- package/dist/evaluators/caching.js +78 -0
- package/dist/evaluators/caching.js.map +1 -0
- package/dist/evaluators/ci-cd.d.ts +3 -0
- package/dist/evaluators/ci-cd.d.ts.map +1 -0
- package/dist/evaluators/ci-cd.js +89 -0
- package/dist/evaluators/ci-cd.js.map +1 -0
- package/dist/evaluators/configuration-management.d.ts +3 -0
- package/dist/evaluators/configuration-management.d.ts.map +1 -0
- package/dist/evaluators/configuration-management.js +76 -0
- package/dist/evaluators/configuration-management.js.map +1 -0
- package/dist/evaluators/database.d.ts +3 -0
- package/dist/evaluators/database.d.ts.map +1 -0
- package/dist/evaluators/database.js +125 -0
- package/dist/evaluators/database.js.map +1 -0
- package/dist/evaluators/error-handling.d.ts +3 -0
- package/dist/evaluators/error-handling.d.ts.map +1 -0
- package/dist/evaluators/error-handling.js +123 -0
- package/dist/evaluators/error-handling.js.map +1 -0
- package/dist/evaluators/index.d.ts.map +1 -1
- package/dist/evaluators/index.js +48 -0
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/logging-privacy.d.ts +3 -0
- package/dist/evaluators/logging-privacy.d.ts.map +1 -0
- package/dist/evaluators/logging-privacy.js +105 -0
- package/dist/evaluators/logging-privacy.js.map +1 -0
- package/dist/evaluators/maintainability.d.ts +3 -0
- package/dist/evaluators/maintainability.d.ts.map +1 -0
- package/dist/evaluators/maintainability.js +141 -0
- package/dist/evaluators/maintainability.js.map +1 -0
- package/dist/evaluators/portability.d.ts +3 -0
- package/dist/evaluators/portability.d.ts.map +1 -0
- package/dist/evaluators/portability.js +108 -0
- package/dist/evaluators/portability.js.map +1 -0
- package/dist/evaluators/rate-limiting.d.ts +3 -0
- package/dist/evaluators/rate-limiting.d.ts.map +1 -0
- package/dist/evaluators/rate-limiting.js +88 -0
- package/dist/evaluators/rate-limiting.js.map +1 -0
- package/dist/evaluators/ux.d.ts +3 -0
- package/dist/evaluators/ux.d.ts.map +1 -0
- package/dist/evaluators/ux.js +106 -0
- package/dist/evaluators/ux.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/judges/authentication.d.ts +3 -0
- package/dist/judges/authentication.d.ts.map +1 -0
- package/dist/judges/authentication.js +34 -0
- package/dist/judges/authentication.js.map +1 -0
- package/dist/judges/backwards-compatibility.d.ts +3 -0
- package/dist/judges/backwards-compatibility.d.ts.map +1 -0
- package/dist/judges/backwards-compatibility.js +34 -0
- package/dist/judges/backwards-compatibility.js.map +1 -0
- package/dist/judges/caching.d.ts +3 -0
- package/dist/judges/caching.d.ts.map +1 -0
- package/dist/judges/caching.js +34 -0
- package/dist/judges/caching.js.map +1 -0
- package/dist/judges/ci-cd.d.ts +3 -0
- package/dist/judges/ci-cd.d.ts.map +1 -0
- package/dist/judges/ci-cd.js +34 -0
- package/dist/judges/ci-cd.js.map +1 -0
- package/dist/judges/configuration-management.d.ts +3 -0
- package/dist/judges/configuration-management.d.ts.map +1 -0
- package/dist/judges/configuration-management.js +34 -0
- package/dist/judges/configuration-management.js.map +1 -0
- package/dist/judges/database.d.ts +3 -0
- package/dist/judges/database.d.ts.map +1 -0
- package/dist/judges/database.js +34 -0
- package/dist/judges/database.js.map +1 -0
- package/dist/judges/error-handling.d.ts +3 -0
- package/dist/judges/error-handling.d.ts.map +1 -0
- package/dist/judges/error-handling.js +34 -0
- package/dist/judges/error-handling.js.map +1 -0
- package/dist/judges/index.d.ts.map +1 -1
- package/dist/judges/index.js +24 -0
- package/dist/judges/index.js.map +1 -1
- package/dist/judges/logging-privacy.d.ts +3 -0
- package/dist/judges/logging-privacy.d.ts.map +1 -0
- package/dist/judges/logging-privacy.js +34 -0
- package/dist/judges/logging-privacy.js.map +1 -0
- package/dist/judges/maintainability.d.ts +3 -0
- package/dist/judges/maintainability.d.ts.map +1 -0
- package/dist/judges/maintainability.js +34 -0
- package/dist/judges/maintainability.js.map +1 -0
- package/dist/judges/portability.d.ts +3 -0
- package/dist/judges/portability.d.ts.map +1 -0
- package/dist/judges/portability.js +34 -0
- package/dist/judges/portability.js.map +1 -0
- package/dist/judges/rate-limiting.d.ts +3 -0
- package/dist/judges/rate-limiting.d.ts.map +1 -0
- package/dist/judges/rate-limiting.js +34 -0
- package/dist/judges/rate-limiting.js.map +1 -0
- package/dist/judges/ux.d.ts +3 -0
- package/dist/judges/ux.d.ts.map +1 -0
- package/dist/judges/ux.js +34 -0
- package/dist/judges/ux.js.map +1 -0
- package/package.json +2 -2
- package/server.json +3 -3
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { getLineNumbers } from "./shared.js";
|
|
2
|
+
export function analyzeConfigurationManagement(code, language) {
|
|
3
|
+
const findings = [];
|
|
4
|
+
let ruleNum = 1;
|
|
5
|
+
const prefix = "CFG";
|
|
6
|
+
// Hardcoded secrets / credentials
|
|
7
|
+
const secretPattern = /(?:password|passwd|secret|api_?key|token|private_?key)\s*[:=]\s*["'`][^"'`]{3,}/gi;
|
|
8
|
+
const secretLines = getLineNumbers(code, secretPattern);
|
|
9
|
+
if (secretLines.length > 0) {
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
12
|
+
severity: "critical",
|
|
13
|
+
title: "Secrets hardcoded in source code",
|
|
14
|
+
description: `Found ${secretLines.length} instance(s) of hardcoded secrets. Secrets in code are exposed in version control, CI logs, and error traces. They cannot be rotated without redeployment.`,
|
|
15
|
+
lineNumbers: secretLines,
|
|
16
|
+
recommendation: "Store secrets in a secrets manager (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault). Inject via environment variables at runtime. Never commit secrets.",
|
|
17
|
+
reference: "OWASP: Secrets Management / 12-Factor App: Config",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// Hardcoded configuration values
|
|
21
|
+
const hardcodedConfigPattern = /(?:const|let|var)\s+(?:PORT|HOST|DATABASE|REDIS|MONGO|API_URL|BASE_URL|TIMEOUT|INTERVAL)\s*=\s*(?:["'`]\w|[0-9])/gi;
|
|
22
|
+
const hardcodedConfigLines = getLineNumbers(code, hardcodedConfigPattern);
|
|
23
|
+
if (hardcodedConfigLines.length > 0) {
|
|
24
|
+
findings.push({
|
|
25
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
26
|
+
severity: "medium",
|
|
27
|
+
title: "Configuration values hardcoded instead of externalized",
|
|
28
|
+
description: `Found ${hardcodedConfigLines.length} hardcoded configuration value(s). These values need to change between environments (dev, staging, prod) and should be externalized.`,
|
|
29
|
+
lineNumbers: hardcodedConfigLines,
|
|
30
|
+
recommendation: "Read configuration from environment variables (process.env.PORT). Use a config library (convict, dotenv, django-environ) to validate and provide defaults.",
|
|
31
|
+
reference: "12-Factor App: Config (Factor III)",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// No environment variable usage
|
|
35
|
+
const hasEnvVars = /process\.env|os\.environ|os\.Getenv|Environment\.GetEnvironmentVariable|System\.getenv|ENV\[/gi.test(code);
|
|
36
|
+
const hasConfig = /(?:port|host|database|url|key|secret|token)\s*[:=]\s*["'`0-9]/gi.test(code);
|
|
37
|
+
if (!hasEnvVars && hasConfig && code.split("\n").length > 30) {
|
|
38
|
+
findings.push({
|
|
39
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
40
|
+
severity: "medium",
|
|
41
|
+
title: "No environment variable usage detected",
|
|
42
|
+
description: "Configuration values are present but no environment variable reads are visible. The application cannot be configured differently per environment without code changes.",
|
|
43
|
+
recommendation: "Read all configuration from environment variables. Provide sensible defaults for development. Validate required config at startup and fail fast if missing.",
|
|
44
|
+
reference: "12-Factor App: Config (Factor III)",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Config validation at startup
|
|
48
|
+
const hasConfigValidation = /(?:assert|require|throw|exit|fatal|Error)\s*.*(?:missing|required|not set|undefined|config)/gi.test(code);
|
|
49
|
+
if (hasConfig && !hasConfigValidation && code.split("\n").length > 30) {
|
|
50
|
+
findings.push({
|
|
51
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
52
|
+
severity: "low",
|
|
53
|
+
title: "No configuration validation at startup",
|
|
54
|
+
description: "Configuration values are used but never validated at startup. Missing or invalid configuration will cause runtime failures instead of clear startup errors.",
|
|
55
|
+
recommendation: "Validate all required configuration at application startup. Fail fast with a clear error message listing which config is missing or invalid.",
|
|
56
|
+
reference: "Fail-Fast Principle / 12-Factor App",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// .env file committed (detected by its presence in code)
|
|
60
|
+
const dotenvCommitPattern = /\.env\b(?!\.example|\.sample|\.template|\.schema)/gi;
|
|
61
|
+
const hasGitignore = /\.gitignore/gi.test(code);
|
|
62
|
+
const hasEnvFile = /dotenv|\.env\b/gi.test(code);
|
|
63
|
+
// This is a heuristic — can't truly check .gitignore from code alone
|
|
64
|
+
if (hasEnvFile && code.split("\n").length > 10) {
|
|
65
|
+
findings.push({
|
|
66
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
67
|
+
severity: "info",
|
|
68
|
+
title: ".env usage detected — ensure it is not committed",
|
|
69
|
+
description: ".env files are useful for development but must not be committed to version control. Ensure .env is listed in .gitignore and provide a .env.example template instead.",
|
|
70
|
+
recommendation: "Add .env to .gitignore. Create a .env.example with placeholder values documenting required environment variables. Use CI/CD variables for deployment.",
|
|
71
|
+
reference: "12-Factor App: Config / dotenv Best Practices",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return findings;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=configuration-management.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configuration-management.js","sourceRoot":"","sources":["../../src/evaluators/configuration-management.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/evaluators/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAkIzE"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { getLineNumbers } from "./shared.js";
|
|
2
|
+
export function analyzeDatabase(code, language) {
|
|
3
|
+
const findings = [];
|
|
4
|
+
let ruleNum = 1;
|
|
5
|
+
const prefix = "DB";
|
|
6
|
+
// SQL injection via string concatenation
|
|
7
|
+
const sqlInjectionPattern = /(?:execute|query|raw|prepare)\s*\(\s*(?:`[^`]*\$\{|['"][^'"]*['"]\s*\+|['"][^'"]*['"]\s*\.\s*concat)/gi;
|
|
8
|
+
const sqlInjectionLines = getLineNumbers(code, sqlInjectionPattern);
|
|
9
|
+
if (sqlInjectionLines.length > 0) {
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
12
|
+
severity: "critical",
|
|
13
|
+
title: "SQL injection via string concatenation",
|
|
14
|
+
description: `Found ${sqlInjectionLines.length} instance(s) of SQL queries built with string concatenation or template literals containing user input. This is the most common and dangerous database vulnerability.`,
|
|
15
|
+
lineNumbers: sqlInjectionLines,
|
|
16
|
+
recommendation: "Use parameterized queries (placeholders) or prepared statements. ORMs handle this automatically. Never concatenate user input into SQL strings.",
|
|
17
|
+
reference: "OWASP SQL Injection Prevention Cheat Sheet / CWE-89",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// SELECT * usage
|
|
21
|
+
const selectStarPattern = /SELECT\s+\*/gi;
|
|
22
|
+
const selectStarLines = getLineNumbers(code, selectStarPattern);
|
|
23
|
+
if (selectStarLines.length > 0) {
|
|
24
|
+
findings.push({
|
|
25
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
26
|
+
severity: "medium",
|
|
27
|
+
title: "SELECT * retrieves unnecessary columns",
|
|
28
|
+
description: `Found ${selectStarLines.length} SELECT * query/queries. Selecting all columns transfers unnecessary data, breaks when schema changes, and prevents index-only scans.`,
|
|
29
|
+
lineNumbers: selectStarLines,
|
|
30
|
+
recommendation: "Select only the columns you need: SELECT id, name, email FROM users. This reduces network transfer, memory usage, and improves query plan optimization.",
|
|
31
|
+
reference: "SQL Performance Best Practices",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// N+1 query pattern (query in a loop)
|
|
35
|
+
const lines = code.split("\n");
|
|
36
|
+
const n1Lines = [];
|
|
37
|
+
let inLoop = false;
|
|
38
|
+
let loopDepth = 0;
|
|
39
|
+
for (let i = 0; i < lines.length; i++) {
|
|
40
|
+
const line = lines[i];
|
|
41
|
+
if (/\b(?:for|while|forEach|\.map|\.each)\b/.test(line)) {
|
|
42
|
+
inLoop = true;
|
|
43
|
+
loopDepth++;
|
|
44
|
+
}
|
|
45
|
+
if (inLoop && /(?:await\s+)?(?:db\.|query|find|findOne|findMany|execute|select|fetch)\s*\(/.test(line)) {
|
|
46
|
+
n1Lines.push(i + 1);
|
|
47
|
+
}
|
|
48
|
+
if (inLoop) {
|
|
49
|
+
const opens = (line.match(/\{/g) || []).length;
|
|
50
|
+
const closes = (line.match(/\}/g) || []).length;
|
|
51
|
+
loopDepth += opens - closes;
|
|
52
|
+
if (loopDepth <= 0) {
|
|
53
|
+
inLoop = false;
|
|
54
|
+
loopDepth = 0;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (n1Lines.length > 0) {
|
|
59
|
+
findings.push({
|
|
60
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
61
|
+
severity: "high",
|
|
62
|
+
title: "N+1 query pattern detected",
|
|
63
|
+
description: `Found ${n1Lines.length} database query/queries inside loops. This creates N+1 queries: 1 for the list + N for each item. Performance degrades linearly with data volume.`,
|
|
64
|
+
lineNumbers: n1Lines,
|
|
65
|
+
recommendation: "Use batch queries (WHERE id IN (...)), JOINs, or ORM eager loading (include/populate) to fetch related data in a single query.",
|
|
66
|
+
reference: "N+1 Query Problem / ORM Performance Patterns",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// No connection pooling
|
|
70
|
+
const hasDbConnection = /createConnection|new\s+Client|new\s+Pool|mongoose\.connect|createPool|DataSource|DriverManager|SqlConnection/gi.test(code);
|
|
71
|
+
const hasPooling = /pool|Pool|connectionPool|poolSize|max_connections|maxPoolSize|connectionLimit/gi.test(code);
|
|
72
|
+
if (hasDbConnection && !hasPooling) {
|
|
73
|
+
findings.push({
|
|
74
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
75
|
+
severity: "medium",
|
|
76
|
+
title: "Database connection without pooling",
|
|
77
|
+
description: "Database connection created without visible connection pooling. Creating a new connection per request is expensive and unsustainable under load.",
|
|
78
|
+
recommendation: "Use connection pooling (e.g., pg.Pool, mysql2.createPool, mongoose connection pooling). Configure pool size based on expected concurrent connections.",
|
|
79
|
+
reference: "Database Connection Pooling Best Practices",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// Raw SQL queries (no ORM/query builder)
|
|
83
|
+
const rawSqlPattern = /(?:execute|query)\s*\(\s*["'`]\s*(?:SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\b/gi;
|
|
84
|
+
const rawSqlLines = getLineNumbers(code, rawSqlPattern);
|
|
85
|
+
if (rawSqlLines.length > 2) {
|
|
86
|
+
findings.push({
|
|
87
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
88
|
+
severity: "low",
|
|
89
|
+
title: "Extensive raw SQL without query builder or ORM",
|
|
90
|
+
description: `Found ${rawSqlLines.length} raw SQL statements. Extensive raw SQL increases injection risk, reduces portability, and lacks type safety.`,
|
|
91
|
+
lineNumbers: rawSqlLines.slice(0, 5),
|
|
92
|
+
recommendation: "Consider using a query builder (Knex, Prisma, Drizzle, SQLAlchemy) or ORM for type safety, parameterization, and database portability.",
|
|
93
|
+
reference: "ORM vs Raw SQL Best Practices",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// No transaction handling
|
|
97
|
+
const hasMutations = /INSERT|UPDATE|DELETE|db\.(?:create|update|delete|save|remove)/gi.test(code);
|
|
98
|
+
const hasTransactions = /transaction|BEGIN|COMMIT|ROLLBACK|startTransaction|withTransaction/gi.test(code);
|
|
99
|
+
if (hasMutations && !hasTransactions && code.split("\n").length > 30) {
|
|
100
|
+
findings.push({
|
|
101
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
102
|
+
severity: "medium",
|
|
103
|
+
title: "Data mutations without transaction handling",
|
|
104
|
+
description: "Data is modified (INSERT/UPDATE/DELETE) without transaction wrappers. If an error occurs mid-operation, data could be left in an inconsistent state.",
|
|
105
|
+
recommendation: "Wrap multi-step data mutations in transactions. Use BEGIN/COMMIT/ROLLBACK or ORM transaction APIs to ensure atomicity.",
|
|
106
|
+
reference: "ACID Properties / Database Transaction Best Practices",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Hardcoded connection strings
|
|
110
|
+
const connStringPattern = /(?:postgres|mysql|mongodb|redis|mssql):\/\/[^"'`\s]{10,}/gi;
|
|
111
|
+
const connStringLines = getLineNumbers(code, connStringPattern);
|
|
112
|
+
if (connStringLines.length > 0) {
|
|
113
|
+
findings.push({
|
|
114
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
115
|
+
severity: "critical",
|
|
116
|
+
title: "Hardcoded database connection string",
|
|
117
|
+
description: "Database connection string is hardcoded in source code, exposing credentials and making it impossible to use different databases per environment.",
|
|
118
|
+
lineNumbers: connStringLines,
|
|
119
|
+
recommendation: "Use environment variables for connection strings. Store credentials in a secrets manager. Use different connection strings per environment.",
|
|
120
|
+
reference: "12-Factor App: Config / OWASP Secrets Management",
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return findings;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/evaluators/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handling.d.ts","sourceRoot":"","sources":["../../src/evaluators/error-handling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAiI9E"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { getLineNumbers } from "./shared.js";
|
|
2
|
+
export function analyzeErrorHandling(code, language) {
|
|
3
|
+
const findings = [];
|
|
4
|
+
let ruleNum = 1;
|
|
5
|
+
const prefix = "ERR";
|
|
6
|
+
// Empty catch blocks
|
|
7
|
+
const emptyCatchPattern = /catch\s*\([^)]*\)\s*\{\s*\}/g;
|
|
8
|
+
const emptyCatchLines = getLineNumbers(code, emptyCatchPattern);
|
|
9
|
+
if (emptyCatchLines.length > 0) {
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
12
|
+
severity: "high",
|
|
13
|
+
title: "Empty catch block swallows errors",
|
|
14
|
+
description: `Found ${emptyCatchLines.length} empty catch block(s). Silently swallowing errors hides bugs, makes debugging impossible, and can leave the application in an inconsistent state.`,
|
|
15
|
+
lineNumbers: emptyCatchLines,
|
|
16
|
+
recommendation: "Log the error with context, re-throw it, or handle it meaningfully. If intentionally ignoring, add a comment explaining why.",
|
|
17
|
+
reference: "ESLint no-empty / Error Handling Best Practices",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// Catch with no error parameter
|
|
21
|
+
const catchNoParamPattern = /catch\s*\(\s*\)\s*\{/g;
|
|
22
|
+
const catchNoParamLines = getLineNumbers(code, catchNoParamPattern);
|
|
23
|
+
if (catchNoParamLines.length > 0) {
|
|
24
|
+
findings.push({
|
|
25
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
26
|
+
severity: "medium",
|
|
27
|
+
title: "Catch block discards error object",
|
|
28
|
+
description: "Catch block does not capture the error object. The error details (message, stack trace, type) are lost, making debugging impossible.",
|
|
29
|
+
lineNumbers: catchNoParamLines,
|
|
30
|
+
recommendation: "Capture the error parameter: catch(error) { ... } and use it for logging, error classification, or re-throwing.",
|
|
31
|
+
reference: "Error Handling Best Practices",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// No global error handler / middleware
|
|
35
|
+
const hasGlobalHandler = /app\.use\s*\(\s*(?:function\s*)?\(\s*err/gi.test(code) ||
|
|
36
|
+
/process\.on\s*\(\s*['"](?:uncaughtException|unhandledRejection)['"]/gi.test(code) ||
|
|
37
|
+
/window\.onerror|window\.addEventListener\s*\(\s*['"]error['"]/gi.test(code) ||
|
|
38
|
+
/app\.use\s*\(\s*errorHandler\b/gi.test(code);
|
|
39
|
+
const hasServerCode = /app\.(listen|use|get|post|put|delete|patch)|createServer|express\(\)|new\s+Hono/gi.test(code);
|
|
40
|
+
if (hasServerCode && !hasGlobalHandler && code.split("\n").length > 30) {
|
|
41
|
+
findings.push({
|
|
42
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
43
|
+
severity: "high",
|
|
44
|
+
title: "No global error handler detected",
|
|
45
|
+
description: "Server code without a global error handler. Unhandled errors will crash the process or return raw stack traces to clients.",
|
|
46
|
+
recommendation: "Add Express error middleware (app.use((err, req, res, next) => { ... })), process.on('uncaughtException'), and process.on('unhandledRejection') handlers.",
|
|
47
|
+
reference: "Express Error Handling / Node.js Best Practices",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// Generic error responses
|
|
51
|
+
const genericErrorPattern = /res\.(status|json|send)\s*\([^)]*(?:["'`](?:Error|Something went wrong|Internal server error|Server error|An error occurred)["'`])/gi;
|
|
52
|
+
const genericErrorLines = getLineNumbers(code, genericErrorPattern);
|
|
53
|
+
if (genericErrorLines.length > 0) {
|
|
54
|
+
findings.push({
|
|
55
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
56
|
+
severity: "low",
|
|
57
|
+
title: "Generic error messages returned to clients",
|
|
58
|
+
description: "Generic error messages like 'Internal server error' or 'Something went wrong' don't help API consumers understand or fix the issue.",
|
|
59
|
+
lineNumbers: genericErrorLines,
|
|
60
|
+
recommendation: "Return structured error responses with error codes, human-readable messages, and suggested actions. Use a consistent error response schema.",
|
|
61
|
+
reference: "RFC 7807 (Problem Details for HTTP APIs)",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Async function without try/catch or .catch
|
|
65
|
+
const asyncFuncPattern = /async\s+(?:function\s+\w+|\([^)]*\)\s*=>|\w+\s*=\s*async)/g;
|
|
66
|
+
const hasTryCatch = /try\s*\{/g;
|
|
67
|
+
const asyncMatches = code.match(asyncFuncPattern)?.length || 0;
|
|
68
|
+
const tryCatchMatches = code.match(hasTryCatch)?.length || 0;
|
|
69
|
+
if (asyncMatches > 0 && tryCatchMatches === 0) {
|
|
70
|
+
findings.push({
|
|
71
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
72
|
+
severity: "medium",
|
|
73
|
+
title: "Async functions without error handling",
|
|
74
|
+
description: `Found ${asyncMatches} async function(s) but no try/catch blocks. Unhandled promise rejections can crash the process in Node.js.`,
|
|
75
|
+
recommendation: "Wrap async operations in try/catch or use .catch() on promises. Consider a global unhandledRejection handler as a safety net.",
|
|
76
|
+
reference: "Node.js Unhandled Rejections / Async Error Handling",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// Callback without error check (Node.js pattern)
|
|
80
|
+
const callbackNoErrPattern = /(?:callback|cb|done|next)\s*\(\s*(?:null|undefined)\s*[,)]/gi;
|
|
81
|
+
const callbackErrPattern = /(?:if\s*\(\s*err|if\s*\(\s*error)/gi;
|
|
82
|
+
const hasCallbacks = /function\s*\([^)]*(?:err|error|cb|callback|done)[^)]*\)/gi.test(code);
|
|
83
|
+
if (hasCallbacks && !callbackErrPattern.test(code) && code.split("\n").length > 20) {
|
|
84
|
+
findings.push({
|
|
85
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
86
|
+
severity: "medium",
|
|
87
|
+
title: "Callback pattern without error checking",
|
|
88
|
+
description: "Code uses callbacks but doesn't appear to check for errors. In Node.js, the error-first callback pattern requires checking the error parameter.",
|
|
89
|
+
recommendation: "Always check the error parameter first in callbacks: if (err) { return handleError(err); }",
|
|
90
|
+
reference: "Node.js Error-First Callbacks",
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Throwing strings instead of Error objects
|
|
94
|
+
const throwStringPattern = /throw\s+["'`]/g;
|
|
95
|
+
const throwStringLines = getLineNumbers(code, throwStringPattern);
|
|
96
|
+
if (throwStringLines.length > 0) {
|
|
97
|
+
findings.push({
|
|
98
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
99
|
+
severity: "medium",
|
|
100
|
+
title: "Throwing string literals instead of Error objects",
|
|
101
|
+
description: "Throwing strings instead of Error objects loses the stack trace and makes error handling inconsistent.",
|
|
102
|
+
lineNumbers: throwStringLines,
|
|
103
|
+
recommendation: "Always throw Error objects: throw new Error('message') or custom error classes that extend Error.",
|
|
104
|
+
reference: "ESLint no-throw-literal / JavaScript Error Handling",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// process.exit() without error handling
|
|
108
|
+
const processExitPattern = /process\.exit\s*\(/g;
|
|
109
|
+
const processExitLines = getLineNumbers(code, processExitPattern);
|
|
110
|
+
if (processExitLines.length > 0) {
|
|
111
|
+
findings.push({
|
|
112
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
113
|
+
severity: "high",
|
|
114
|
+
title: "process.exit() used instead of proper error handling",
|
|
115
|
+
description: "process.exit() immediately terminates the process, skipping cleanup handlers, dropping in-flight requests, and potentially corrupting data.",
|
|
116
|
+
lineNumbers: processExitLines,
|
|
117
|
+
recommendation: "Use proper error propagation instead of process.exit(). In HTTP servers, return error responses. Let the process shutdown gracefully.",
|
|
118
|
+
reference: "Node.js Graceful Shutdown Best Practices",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return findings;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=error-handling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handling.js","sourceRoot":"","sources":["../../src/evaluators/error-handling.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,QAAgB;IACjE,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,MAAM,GAAG,KAAK,CAAC;IAErB,qBAAqB;IACrB,MAAM,iBAAiB,GAAG,8BAA8B,CAAC;IACzD,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAChE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,mCAAmC;YAC1C,WAAW,EAAE,SAAS,eAAe,CAAC,MAAM,mJAAmJ;YAC/L,WAAW,EAAE,eAAe;YAC5B,cAAc,EAAE,8HAA8H;YAC9I,SAAS,EAAE,iDAAiD;SAC7D,CAAC,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;IACpD,MAAM,iBAAiB,GAAG,cAAc,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACpE,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,mCAAmC;YAC1C,WAAW,EAAE,sIAAsI;YACnJ,WAAW,EAAE,iBAAiB;YAC9B,cAAc,EAAE,iHAAiH;YACjI,SAAS,EAAE,+BAA+B;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,uCAAuC;IACvC,MAAM,gBAAgB,GAAG,4CAA4C,CAAC,IAAI,CAAC,IAAI,CAAC;QAC9E,uEAAuE,CAAC,IAAI,CAAC,IAAI,CAAC;QAClF,iEAAiE,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5E,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,aAAa,GAAG,mFAAmF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrH,IAAI,aAAa,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACvE,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,kCAAkC;YACzC,WAAW,EAAE,4HAA4H;YACzI,cAAc,EAAE,2JAA2J;YAC3K,SAAS,EAAE,iDAAiD;SAC7D,CAAC,CAAC;IACL,CAAC;IAED,0BAA0B;IAC1B,MAAM,mBAAmB,GAAG,sIAAsI,CAAC;IACnK,MAAM,iBAAiB,GAAG,cAAc,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;IACpE,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,4CAA4C;YACnD,WAAW,EAAE,qIAAqI;YAClJ,WAAW,EAAE,iBAAiB;YAC9B,cAAc,EAAE,6IAA6I;YAC7J,SAAS,EAAE,0CAA0C;SACtD,CAAC,CAAC;IACL,CAAC;IAED,6CAA6C;IAC7C,MAAM,gBAAgB,GAAG,4DAA4D,CAAC;IACtF,MAAM,WAAW,GAAG,WAAW,CAAC;IAChC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IAC/D,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IAC7D,IAAI,YAAY,GAAG,CAAC,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,wCAAwC;YAC/C,WAAW,EAAE,SAAS,YAAY,4GAA4G;YAC9I,cAAc,EAAE,+HAA+H;YAC/I,SAAS,EAAE,qDAAqD;SACjE,CAAC,CAAC;IACL,CAAC;IAED,iDAAiD;IACjD,MAAM,oBAAoB,GAAG,8DAA8D,CAAC;IAC5F,MAAM,kBAAkB,GAAG,qCAAqC,CAAC;IACjE,MAAM,YAAY,GAAG,2DAA2D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5F,IAAI,YAAY,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACnF,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,yCAAyC;YAChD,WAAW,EAAE,iJAAiJ;YAC9J,cAAc,EAAE,4FAA4F;YAC5G,SAAS,EAAE,+BAA+B;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,4CAA4C;IAC5C,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;IAC5C,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAClE,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,mDAAmD;YAC1D,WAAW,EAAE,wGAAwG;YACrH,WAAW,EAAE,gBAAgB;YAC7B,cAAc,EAAE,mGAAmG;YACnH,SAAS,EAAE,qDAAqD;SACjE,CAAC,CAAC;IACL,CAAC;IAED,wCAAwC;IACxC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;IACjD,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAClE,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzD,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,sDAAsD;YAC7D,WAAW,EAAE,6IAA6I;YAC1J,WAAW,EAAE,gBAAgB;YAC7B,cAAc,EAAE,uIAAuI;YACvJ,SAAS,EAAE,0CAA0C;SACtD,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evaluators/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,eAAe,EACf,eAAe,EACf,eAAe,EAGhB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAKL,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evaluators/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,eAAe,EACf,eAAe,EACf,eAAe,EAGhB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAKL,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,aAAa,CAAC;AAoCrB;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,eAAe,CA4GjB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,eAAe,CAsCjB;AAID,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,CAAC"}
|
package/dist/evaluators/index.js
CHANGED
|
@@ -23,6 +23,18 @@ import { analyzeInternationalization } from "./internationalization.js";
|
|
|
23
23
|
import { analyzeDependencyHealth } from "./dependency-health.js";
|
|
24
24
|
import { analyzeConcurrency } from "./concurrency.js";
|
|
25
25
|
import { analyzeEthicsBias } from "./ethics-bias.js";
|
|
26
|
+
import { analyzeMaintainability } from "./maintainability.js";
|
|
27
|
+
import { analyzeErrorHandling } from "./error-handling.js";
|
|
28
|
+
import { analyzeAuthentication } from "./authentication.js";
|
|
29
|
+
import { analyzeDatabase } from "./database.js";
|
|
30
|
+
import { analyzeCaching } from "./caching.js";
|
|
31
|
+
import { analyzeConfigurationManagement } from "./configuration-management.js";
|
|
32
|
+
import { analyzeBackwardsCompatibility } from "./backwards-compatibility.js";
|
|
33
|
+
import { analyzePortability } from "./portability.js";
|
|
34
|
+
import { analyzeUx } from "./ux.js";
|
|
35
|
+
import { analyzeLoggingPrivacy } from "./logging-privacy.js";
|
|
36
|
+
import { analyzeRateLimiting } from "./rate-limiting.js";
|
|
37
|
+
import { analyzeCiCd } from "./ci-cd.js";
|
|
26
38
|
// ─── Evaluation Engine ──────────────────────────────────────────────────────
|
|
27
39
|
/**
|
|
28
40
|
* Run a single judge against the provided code.
|
|
@@ -84,6 +96,42 @@ export function evaluateWithJudge(judge, code, language, context) {
|
|
|
84
96
|
case "ethics-bias":
|
|
85
97
|
findings.push(...analyzeEthicsBias(code, language));
|
|
86
98
|
break;
|
|
99
|
+
case "maintainability":
|
|
100
|
+
findings.push(...analyzeMaintainability(code, language));
|
|
101
|
+
break;
|
|
102
|
+
case "error-handling":
|
|
103
|
+
findings.push(...analyzeErrorHandling(code, language));
|
|
104
|
+
break;
|
|
105
|
+
case "authentication":
|
|
106
|
+
findings.push(...analyzeAuthentication(code, language));
|
|
107
|
+
break;
|
|
108
|
+
case "database":
|
|
109
|
+
findings.push(...analyzeDatabase(code, language));
|
|
110
|
+
break;
|
|
111
|
+
case "caching":
|
|
112
|
+
findings.push(...analyzeCaching(code, language));
|
|
113
|
+
break;
|
|
114
|
+
case "configuration-management":
|
|
115
|
+
findings.push(...analyzeConfigurationManagement(code, language));
|
|
116
|
+
break;
|
|
117
|
+
case "backwards-compatibility":
|
|
118
|
+
findings.push(...analyzeBackwardsCompatibility(code, language));
|
|
119
|
+
break;
|
|
120
|
+
case "portability":
|
|
121
|
+
findings.push(...analyzePortability(code, language));
|
|
122
|
+
break;
|
|
123
|
+
case "ux":
|
|
124
|
+
findings.push(...analyzeUx(code, language));
|
|
125
|
+
break;
|
|
126
|
+
case "logging-privacy":
|
|
127
|
+
findings.push(...analyzeLoggingPrivacy(code, language));
|
|
128
|
+
break;
|
|
129
|
+
case "rate-limiting":
|
|
130
|
+
findings.push(...analyzeRateLimiting(code, language));
|
|
131
|
+
break;
|
|
132
|
+
case "ci-cd":
|
|
133
|
+
findings.push(...analyzeCiCd(code, language));
|
|
134
|
+
break;
|
|
87
135
|
}
|
|
88
136
|
const score = calculateScore(findings);
|
|
89
137
|
const verdict = deriveVerdict(findings, score);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/evaluators/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,2EAA2E;AAC3E,iFAAiF;AASjF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,gFAAgF;AAChF,OAAO,EACL,cAAc,EACd,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAErB,gFAAgF;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/evaluators/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-privacy.d.ts","sourceRoot":"","sources":["../../src/evaluators/logging-privacy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CA8G/E"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { getLineNumbers } from "./shared.js";
|
|
2
|
+
export function analyzeLoggingPrivacy(code, language) {
|
|
3
|
+
const findings = [];
|
|
4
|
+
let ruleNum = 1;
|
|
5
|
+
const prefix = "LOGPRIV";
|
|
6
|
+
// Logging authorization/token headers
|
|
7
|
+
const logAuthPattern = /console\.(?:log|info|warn|error|debug)\s*\([^)]*(?:authorization|bearer|token|auth)/gi;
|
|
8
|
+
const logAuthLines = getLineNumbers(code, logAuthPattern);
|
|
9
|
+
if (logAuthLines.length > 0) {
|
|
10
|
+
findings.push({
|
|
11
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
12
|
+
severity: "critical",
|
|
13
|
+
title: "Authentication tokens logged",
|
|
14
|
+
description: `Found ${logAuthLines.length} instance(s) where authentication tokens or authorization headers are logged. Tokens in logs can be used for session hijacking.`,
|
|
15
|
+
lineNumbers: logAuthLines,
|
|
16
|
+
recommendation: "Never log authentication tokens, Authorization headers, or session IDs. If request logging is needed, redact sensitive headers before logging.",
|
|
17
|
+
reference: "OWASP Logging Cheat Sheet / CWE-532",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// Logging passwords
|
|
21
|
+
const logPasswordPattern = /console\.(?:log|info|warn|error|debug)\s*\([^)]*(?:password|passwd|pwd|secret|credential)/gi;
|
|
22
|
+
const logPasswordLines = getLineNumbers(code, logPasswordPattern);
|
|
23
|
+
if (logPasswordLines.length > 0) {
|
|
24
|
+
findings.push({
|
|
25
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
26
|
+
severity: "critical",
|
|
27
|
+
title: "Passwords/secrets logged",
|
|
28
|
+
description: `Found ${logPasswordLines.length} instance(s) where passwords or secrets appear in log statements. This exposes credentials in log files, monitoring systems, and SIEM tools.`,
|
|
29
|
+
lineNumbers: logPasswordLines,
|
|
30
|
+
recommendation: "Never log passwords, credentials, or secrets. Implement a log sanitizer that redacts sensitive fields automatically.",
|
|
31
|
+
reference: "OWASP Logging Cheat Sheet / GDPR Art. 5(1)(f)",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// Logging PII (email, name, SSN, phone)
|
|
35
|
+
const logPiiPattern = /console\.(?:log|info|warn|error|debug)\s*\([^)]*(?:email|ssn|phone|address|name|firstName|lastName|dateOfBirth|dob|social.?security)/gi;
|
|
36
|
+
const logPiiLines = getLineNumbers(code, logPiiPattern);
|
|
37
|
+
if (logPiiLines.length > 0) {
|
|
38
|
+
findings.push({
|
|
39
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
40
|
+
severity: "high",
|
|
41
|
+
title: "Personally Identifiable Information (PII) in logs",
|
|
42
|
+
description: `Found ${logPiiLines.length} instance(s) where PII may be logged. PII in logs violates data minimization principles and may breach GDPR/CCPA requirements.`,
|
|
43
|
+
lineNumbers: logPiiLines,
|
|
44
|
+
recommendation: "Redact PII before logging. Use anonymized identifiers. Implement a log redaction filter that automatically masks sensitive fields.",
|
|
45
|
+
reference: "GDPR Article 5: Data Minimization / OWASP Logging Cheat Sheet",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Logging full request/response bodies
|
|
49
|
+
const logBodyPattern = /console\.(?:log|info|warn|error|debug)\s*\([^)]*(?:req\.body|request\.body|res\.body|response\.body|JSON\.stringify\s*\(\s*req)/gi;
|
|
50
|
+
const logBodyLines = getLineNumbers(code, logBodyPattern);
|
|
51
|
+
if (logBodyLines.length > 0) {
|
|
52
|
+
findings.push({
|
|
53
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
54
|
+
severity: "high",
|
|
55
|
+
title: "Full request/response bodies logged",
|
|
56
|
+
description: "Full request or response bodies are logged, which may contain sensitive user data, credentials, or PII that should not appear in logs.",
|
|
57
|
+
lineNumbers: logBodyLines,
|
|
58
|
+
recommendation: "Log only necessary metadata (method, URL, status, duration). If body logging is needed, implement a whitelist of safe fields and redact everything else.",
|
|
59
|
+
reference: "Log Sanitization Best Practices",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// Logging financial data
|
|
63
|
+
const logFinancePattern = /console\.(?:log|info|warn|error|debug)\s*\([^)]*(?:card.?number|credit.?card|cvv|expir|bank.?account|routing.?number|iban|swift)/gi;
|
|
64
|
+
const logFinanceLines = getLineNumbers(code, logFinancePattern);
|
|
65
|
+
if (logFinanceLines.length > 0) {
|
|
66
|
+
findings.push({
|
|
67
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
68
|
+
severity: "critical",
|
|
69
|
+
title: "Financial data logged",
|
|
70
|
+
description: "Credit card numbers, CVVs, or bank account details appear in log statements. This is a PCI DSS violation and a data breach risk.",
|
|
71
|
+
lineNumbers: logFinanceLines,
|
|
72
|
+
recommendation: "Never log financial data. Mask card numbers (show only last 4 digits). PCI DSS prohibits storing CVV data in any form.",
|
|
73
|
+
reference: "PCI DSS Requirement 3: Protect Stored Data",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Console.log used instead of proper logger (with privacy context)
|
|
77
|
+
const consoleLogCount = (code.match(/console\.(log|info|warn|error|debug)\s*\(/g) || []).length;
|
|
78
|
+
const hasProperLogger = /winston|pino|bunyan|log4j|serilog|NLog|structuredLog|logger\./gi.test(code);
|
|
79
|
+
if (consoleLogCount > 3 && !hasProperLogger) {
|
|
80
|
+
findings.push({
|
|
81
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
82
|
+
severity: "medium",
|
|
83
|
+
title: "Console.log lacks redaction capabilities",
|
|
84
|
+
description: `Found ${consoleLogCount} console.log statements. Console.log has no built-in redaction, log level filtering, or structured output — making it impossible to automatically strip sensitive data.`,
|
|
85
|
+
recommendation: "Use a structured logging library (pino, winston) that supports field-level redaction, log level filtering, and structured output for automated sensitivity scanning.",
|
|
86
|
+
reference: "Structured Logging / Log Redaction Patterns",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// String concatenation in logs (prevents redaction)
|
|
90
|
+
const logConcatPattern = /console\.(?:log|info|warn|error|debug)\s*\([^)]*\+/g;
|
|
91
|
+
const logConcatLines = getLineNumbers(code, logConcatPattern);
|
|
92
|
+
if (logConcatLines.length > 0) {
|
|
93
|
+
findings.push({
|
|
94
|
+
ruleId: `${prefix}-${String(ruleNum++).padStart(3, "0")}`,
|
|
95
|
+
severity: "low",
|
|
96
|
+
title: "String concatenation in log statements",
|
|
97
|
+
description: `Found ${logConcatLines.length} log statement(s) using string concatenation. Concatenated logs are unstructured and make it impossible to apply field-level redaction.`,
|
|
98
|
+
lineNumbers: logConcatLines.slice(0, 5),
|
|
99
|
+
recommendation: "Use structured logging with named fields: logger.info({ userId, action }, 'User action performed'). This allows automated redaction of specific fields.",
|
|
100
|
+
reference: "Structured Logging Best Practices",
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return findings;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=logging-privacy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-privacy.js","sourceRoot":"","sources":["../../src/evaluators/logging-privacy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintainability.d.ts","sourceRoot":"","sources":["../../src/evaluators/maintainability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAkJhF"}
|