@quantracode/vibecheck 0.0.1 → 0.0.2
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 +6 -6
- package/dist/index.d.ts +0 -2
- package/dist/index.js +7902 -8
- package/package.json +13 -7
- package/dist/__tests__/cli.test.d.ts +0 -2
- package/dist/__tests__/cli.test.d.ts.map +0 -1
- package/dist/__tests__/cli.test.js +0 -243
- package/dist/__tests__/fixtures/safe-app/app/api/users/route.js +0 -36
- package/dist/__tests__/fixtures/vulnerable-app/app/api/users/route.js +0 -28
- package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts +0 -4
- package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts.map +0 -1
- package/dist/__tests__/fixtures/vulnerable-app/lib/config.js +0 -6
- package/dist/__tests__/scanners/env-config.test.d.ts +0 -2
- package/dist/__tests__/scanners/env-config.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/env-config.test.js +0 -142
- package/dist/__tests__/scanners/nextjs-middleware.test.d.ts +0 -2
- package/dist/__tests__/scanners/nextjs-middleware.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/nextjs-middleware.test.js +0 -193
- package/dist/__tests__/scanners/scanner-packs.test.d.ts +0 -2
- package/dist/__tests__/scanners/scanner-packs.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/scanner-packs.test.js +0 -126
- package/dist/__tests__/scanners/unused-security-imports.test.d.ts +0 -2
- package/dist/__tests__/scanners/unused-security-imports.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/unused-security-imports.test.js +0 -145
- package/dist/commands/demo-artifact.d.ts +0 -7
- package/dist/commands/demo-artifact.d.ts.map +0 -1
- package/dist/commands/demo-artifact.js +0 -322
- package/dist/commands/evaluate.d.ts +0 -30
- package/dist/commands/evaluate.d.ts.map +0 -1
- package/dist/commands/evaluate.js +0 -258
- package/dist/commands/explain.d.ts +0 -12
- package/dist/commands/explain.d.ts.map +0 -1
- package/dist/commands/explain.js +0 -214
- package/dist/commands/index.d.ts +0 -7
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js +0 -6
- package/dist/commands/intent.d.ts +0 -21
- package/dist/commands/intent.d.ts.map +0 -1
- package/dist/commands/intent.js +0 -192
- package/dist/commands/scan.d.ts +0 -44
- package/dist/commands/scan.d.ts.map +0 -1
- package/dist/commands/scan.js +0 -497
- package/dist/commands/waivers.d.ts +0 -30
- package/dist/commands/waivers.d.ts.map +0 -1
- package/dist/commands/waivers.js +0 -249
- package/dist/index.d.ts.map +0 -1
- package/dist/phase3/index.d.ts +0 -11
- package/dist/phase3/index.d.ts.map +0 -1
- package/dist/phase3/index.js +0 -12
- package/dist/phase3/intent-miner.d.ts +0 -32
- package/dist/phase3/intent-miner.d.ts.map +0 -1
- package/dist/phase3/intent-miner.js +0 -323
- package/dist/phase3/proof-trace-builder.d.ts +0 -42
- package/dist/phase3/proof-trace-builder.d.ts.map +0 -1
- package/dist/phase3/proof-trace-builder.js +0 -441
- package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts +0 -15
- package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts.map +0 -1
- package/dist/phase3/scanners/auth-by-ui-server-gap.js +0 -237
- package/dist/phase3/scanners/comment-claim-unproven.d.ts +0 -14
- package/dist/phase3/scanners/comment-claim-unproven.d.ts.map +0 -1
- package/dist/phase3/scanners/comment-claim-unproven.js +0 -161
- package/dist/phase3/scanners/index.d.ts +0 -31
- package/dist/phase3/scanners/index.d.ts.map +0 -1
- package/dist/phase3/scanners/index.js +0 -40
- package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts +0 -14
- package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts.map +0 -1
- package/dist/phase3/scanners/middleware-assumed-not-matching.js +0 -172
- package/dist/phase3/scanners/validation-claimed-missing.d.ts +0 -15
- package/dist/phase3/scanners/validation-claimed-missing.d.ts.map +0 -1
- package/dist/phase3/scanners/validation-claimed-missing.js +0 -204
- package/dist/scanners/abuse/compute-abuse.d.ts +0 -20
- package/dist/scanners/abuse/compute-abuse.d.ts.map +0 -1
- package/dist/scanners/abuse/compute-abuse.js +0 -509
- package/dist/scanners/abuse/index.d.ts +0 -12
- package/dist/scanners/abuse/index.d.ts.map +0 -1
- package/dist/scanners/abuse/index.js +0 -15
- package/dist/scanners/auth/index.d.ts +0 -5
- package/dist/scanners/auth/index.d.ts.map +0 -1
- package/dist/scanners/auth/index.js +0 -10
- package/dist/scanners/auth/middleware-gap.d.ts +0 -22
- package/dist/scanners/auth/middleware-gap.d.ts.map +0 -1
- package/dist/scanners/auth/middleware-gap.js +0 -203
- package/dist/scanners/auth/unprotected-api-route.d.ts +0 -12
- package/dist/scanners/auth/unprotected-api-route.d.ts.map +0 -1
- package/dist/scanners/auth/unprotected-api-route.js +0 -126
- package/dist/scanners/config/index.d.ts +0 -5
- package/dist/scanners/config/index.d.ts.map +0 -1
- package/dist/scanners/config/index.js +0 -10
- package/dist/scanners/config/insecure-defaults.d.ts +0 -12
- package/dist/scanners/config/insecure-defaults.d.ts.map +0 -1
- package/dist/scanners/config/insecure-defaults.js +0 -77
- package/dist/scanners/config/undocumented-env.d.ts +0 -24
- package/dist/scanners/config/undocumented-env.d.ts.map +0 -1
- package/dist/scanners/config/undocumented-env.js +0 -159
- package/dist/scanners/crypto/index.d.ts +0 -6
- package/dist/scanners/crypto/index.d.ts.map +0 -1
- package/dist/scanners/crypto/index.js +0 -11
- package/dist/scanners/crypto/jwt-decode-unverified.d.ts +0 -14
- package/dist/scanners/crypto/jwt-decode-unverified.d.ts.map +0 -1
- package/dist/scanners/crypto/jwt-decode-unverified.js +0 -87
- package/dist/scanners/crypto/math-random-tokens.d.ts +0 -13
- package/dist/scanners/crypto/math-random-tokens.d.ts.map +0 -1
- package/dist/scanners/crypto/math-random-tokens.js +0 -80
- package/dist/scanners/crypto/weak-hashing.d.ts +0 -11
- package/dist/scanners/crypto/weak-hashing.d.ts.map +0 -1
- package/dist/scanners/crypto/weak-hashing.js +0 -95
- package/dist/scanners/env-config.d.ts +0 -24
- package/dist/scanners/env-config.d.ts.map +0 -1
- package/dist/scanners/env-config.js +0 -164
- package/dist/scanners/hallucinations/index.d.ts +0 -4
- package/dist/scanners/hallucinations/index.d.ts.map +0 -1
- package/dist/scanners/hallucinations/index.js +0 -8
- package/dist/scanners/hallucinations/unused-security-imports.d.ts +0 -36
- package/dist/scanners/hallucinations/unused-security-imports.d.ts.map +0 -1
- package/dist/scanners/hallucinations/unused-security-imports.js +0 -309
- package/dist/scanners/helpers/ast-helpers.d.ts +0 -6
- package/dist/scanners/helpers/ast-helpers.d.ts.map +0 -1
- package/dist/scanners/helpers/ast-helpers.js +0 -945
- package/dist/scanners/helpers/context-builder.d.ts +0 -17
- package/dist/scanners/helpers/context-builder.d.ts.map +0 -1
- package/dist/scanners/helpers/context-builder.js +0 -148
- package/dist/scanners/helpers/index.d.ts +0 -3
- package/dist/scanners/helpers/index.d.ts.map +0 -1
- package/dist/scanners/helpers/index.js +0 -2
- package/dist/scanners/index.d.ts +0 -30
- package/dist/scanners/index.d.ts.map +0 -1
- package/dist/scanners/index.js +0 -102
- package/dist/scanners/middleware/index.d.ts +0 -4
- package/dist/scanners/middleware/index.d.ts.map +0 -1
- package/dist/scanners/middleware/index.js +0 -7
- package/dist/scanners/middleware/missing-rate-limit.d.ts +0 -13
- package/dist/scanners/middleware/missing-rate-limit.d.ts.map +0 -1
- package/dist/scanners/middleware/missing-rate-limit.js +0 -140
- package/dist/scanners/network/cors-misconfiguration.d.ts +0 -14
- package/dist/scanners/network/cors-misconfiguration.d.ts.map +0 -1
- package/dist/scanners/network/cors-misconfiguration.js +0 -89
- package/dist/scanners/network/index.d.ts +0 -7
- package/dist/scanners/network/index.d.ts.map +0 -1
- package/dist/scanners/network/index.js +0 -18
- package/dist/scanners/network/missing-timeout.d.ts +0 -15
- package/dist/scanners/network/missing-timeout.d.ts.map +0 -1
- package/dist/scanners/network/missing-timeout.js +0 -93
- package/dist/scanners/network/open-redirect.d.ts +0 -15
- package/dist/scanners/network/open-redirect.d.ts.map +0 -1
- package/dist/scanners/network/open-redirect.js +0 -88
- package/dist/scanners/network/ssrf-prone-fetch.d.ts +0 -12
- package/dist/scanners/network/ssrf-prone-fetch.d.ts.map +0 -1
- package/dist/scanners/network/ssrf-prone-fetch.js +0 -90
- package/dist/scanners/nextjs-middleware.d.ts +0 -26
- package/dist/scanners/nextjs-middleware.d.ts.map +0 -1
- package/dist/scanners/nextjs-middleware.js +0 -246
- package/dist/scanners/privacy/debug-flags.d.ts +0 -13
- package/dist/scanners/privacy/debug-flags.d.ts.map +0 -1
- package/dist/scanners/privacy/debug-flags.js +0 -124
- package/dist/scanners/privacy/index.d.ts +0 -6
- package/dist/scanners/privacy/index.d.ts.map +0 -1
- package/dist/scanners/privacy/index.js +0 -11
- package/dist/scanners/privacy/over-broad-response.d.ts +0 -15
- package/dist/scanners/privacy/over-broad-response.d.ts.map +0 -1
- package/dist/scanners/privacy/over-broad-response.js +0 -109
- package/dist/scanners/privacy/sensitive-logging.d.ts +0 -11
- package/dist/scanners/privacy/sensitive-logging.d.ts.map +0 -1
- package/dist/scanners/privacy/sensitive-logging.js +0 -78
- package/dist/scanners/types.d.ts +0 -456
- package/dist/scanners/types.d.ts.map +0 -1
- package/dist/scanners/types.js +0 -16
- package/dist/scanners/unused-security-imports.d.ts +0 -34
- package/dist/scanners/unused-security-imports.d.ts.map +0 -1
- package/dist/scanners/unused-security-imports.js +0 -206
- package/dist/scanners/uploads/index.d.ts +0 -5
- package/dist/scanners/uploads/index.d.ts.map +0 -1
- package/dist/scanners/uploads/index.js +0 -9
- package/dist/scanners/uploads/missing-constraints.d.ts +0 -15
- package/dist/scanners/uploads/missing-constraints.d.ts.map +0 -1
- package/dist/scanners/uploads/missing-constraints.js +0 -109
- package/dist/scanners/uploads/public-path.d.ts +0 -11
- package/dist/scanners/uploads/public-path.d.ts.map +0 -1
- package/dist/scanners/uploads/public-path.js +0 -87
- package/dist/scanners/validation/client-side-only.d.ts +0 -14
- package/dist/scanners/validation/client-side-only.d.ts.map +0 -1
- package/dist/scanners/validation/client-side-only.js +0 -140
- package/dist/scanners/validation/ignored-validation.d.ts +0 -12
- package/dist/scanners/validation/ignored-validation.d.ts.map +0 -1
- package/dist/scanners/validation/ignored-validation.js +0 -119
- package/dist/scanners/validation/index.d.ts +0 -5
- package/dist/scanners/validation/index.d.ts.map +0 -1
- package/dist/scanners/validation/index.js +0 -9
- package/dist/utils/exclude-patterns.d.ts +0 -35
- package/dist/utils/exclude-patterns.d.ts.map +0 -1
- package/dist/utils/exclude-patterns.js +0 -78
- package/dist/utils/file-utils.d.ts +0 -37
- package/dist/utils/file-utils.d.ts.map +0 -1
- package/dist/utils/file-utils.js +0 -77
- package/dist/utils/fingerprint.d.ts +0 -25
- package/dist/utils/fingerprint.d.ts.map +0 -1
- package/dist/utils/fingerprint.js +0 -28
- package/dist/utils/git-info.d.ts +0 -14
- package/dist/utils/git-info.d.ts.map +0 -1
- package/dist/utils/git-info.js +0 -55
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -3
- package/dist/utils/progress.d.ts +0 -42
- package/dist/utils/progress.d.ts.map +0 -1
- package/dist/utils/progress.js +0 -165
- package/dist/utils/sarif-formatter.d.ts +0 -92
- package/dist/utils/sarif-formatter.d.ts.map +0 -1
- package/dist/utils/sarif-formatter.js +0 -172
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import { readFileSync, resolvePath } from "../../utils/file-utils.js";
|
|
2
|
-
import { generateFingerprint, generateFindingId } from "../../utils/fingerprint.js";
|
|
3
|
-
const RULE_ID = "VC-HALL-001";
|
|
4
|
-
const RULE_ID_002 = "VC-HALL-002";
|
|
5
|
-
const SECURITY_LIBS = [
|
|
6
|
-
{
|
|
7
|
-
name: "zod",
|
|
8
|
-
category: "validation",
|
|
9
|
-
severity: "medium",
|
|
10
|
-
description: "Schema validation library",
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
name: "yup",
|
|
14
|
-
category: "validation",
|
|
15
|
-
severity: "medium",
|
|
16
|
-
description: "Schema validation library",
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
name: "joi",
|
|
20
|
-
category: "validation",
|
|
21
|
-
severity: "medium",
|
|
22
|
-
description: "Schema validation library",
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: "helmet",
|
|
26
|
-
category: "middleware",
|
|
27
|
-
severity: "medium",
|
|
28
|
-
description: "Security headers middleware",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: "cors",
|
|
32
|
-
category: "middleware",
|
|
33
|
-
severity: "low",
|
|
34
|
-
description: "CORS middleware",
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: "csurf",
|
|
38
|
-
category: "middleware",
|
|
39
|
-
severity: "medium",
|
|
40
|
-
description: "CSRF protection middleware",
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: "express-rate-limit",
|
|
44
|
-
category: "middleware",
|
|
45
|
-
severity: "medium",
|
|
46
|
-
description: "Rate limiting middleware",
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: "bcrypt",
|
|
50
|
-
category: "auth",
|
|
51
|
-
severity: "high",
|
|
52
|
-
description: "Password hashing library",
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
name: "argon2",
|
|
56
|
-
category: "auth",
|
|
57
|
-
severity: "high",
|
|
58
|
-
description: "Password hashing library",
|
|
59
|
-
},
|
|
60
|
-
];
|
|
61
|
-
/**
|
|
62
|
-
* Find imports of security libraries in a file
|
|
63
|
-
*/
|
|
64
|
-
export function findSecurityImports(content, libraries) {
|
|
65
|
-
const imports = [];
|
|
66
|
-
const lines = content.split("\n");
|
|
67
|
-
for (let i = 0; i < lines.length; i++) {
|
|
68
|
-
const line = lines[i];
|
|
69
|
-
for (const lib of libraries) {
|
|
70
|
-
// Check each library pattern
|
|
71
|
-
const patterns = [
|
|
72
|
-
// import X from 'lib'
|
|
73
|
-
new RegExp(`^\\s*import\\s+(\\w+)\\s+from\\s+['"]${lib}['"]`),
|
|
74
|
-
// import { x, y } from 'lib'
|
|
75
|
-
new RegExp(`^\\s*import\\s+\\{([^}]+)\\}\\s+from\\s+['"]${lib}['"]`),
|
|
76
|
-
// import * as X from 'lib'
|
|
77
|
-
new RegExp(`^\\s*import\\s+\\*\\s+as\\s+(\\w+)\\s+from\\s+['"]${lib}['"]`),
|
|
78
|
-
// import X, { y } from 'lib'
|
|
79
|
-
new RegExp(`^\\s*import\\s+(\\w+)\\s*,\\s*\\{([^}]+)\\}\\s+from\\s+['"]${lib}['"]`),
|
|
80
|
-
];
|
|
81
|
-
for (let p = 0; p < patterns.length; p++) {
|
|
82
|
-
const match = line.match(patterns[p]);
|
|
83
|
-
if (match) {
|
|
84
|
-
const importedNames = [];
|
|
85
|
-
let isDefaultImport = false;
|
|
86
|
-
let isNamespaceImport = false;
|
|
87
|
-
if (p === 0) {
|
|
88
|
-
// Default import
|
|
89
|
-
importedNames.push(match[1]);
|
|
90
|
-
isDefaultImport = true;
|
|
91
|
-
}
|
|
92
|
-
else if (p === 1) {
|
|
93
|
-
// Named imports
|
|
94
|
-
const names = match[1].split(",").map((n) => n.trim().split(/\s+as\s+/)[0].trim());
|
|
95
|
-
importedNames.push(...names.filter(Boolean));
|
|
96
|
-
}
|
|
97
|
-
else if (p === 2) {
|
|
98
|
-
// Namespace import
|
|
99
|
-
importedNames.push(match[1]);
|
|
100
|
-
isNamespaceImport = true;
|
|
101
|
-
}
|
|
102
|
-
else if (p === 3) {
|
|
103
|
-
// Default + named
|
|
104
|
-
importedNames.push(match[1]);
|
|
105
|
-
isDefaultImport = true;
|
|
106
|
-
const names = match[2].split(",").map((n) => n.trim().split(/\s+as\s+/)[0].trim());
|
|
107
|
-
importedNames.push(...names.filter(Boolean));
|
|
108
|
-
}
|
|
109
|
-
imports.push({
|
|
110
|
-
library: lib,
|
|
111
|
-
importedNames,
|
|
112
|
-
line: i + 1,
|
|
113
|
-
snippet: line.trim(),
|
|
114
|
-
isDefaultImport,
|
|
115
|
-
isNamespaceImport,
|
|
116
|
-
});
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return imports;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Check if any imported identifiers are used after the import line
|
|
126
|
-
*/
|
|
127
|
-
export function checkIdentifierUsage(content, importLine, identifiers, isNamespaceImport) {
|
|
128
|
-
const lines = content.split("\n");
|
|
129
|
-
const afterImport = lines.slice(importLine).join("\n");
|
|
130
|
-
return identifiers.map((id) => {
|
|
131
|
-
// For namespace imports, check for namespace.something
|
|
132
|
-
if (isNamespaceImport) {
|
|
133
|
-
const namespaceRegex = new RegExp(`\\b${id}\\s*\\.`, "g");
|
|
134
|
-
return { identifier: id, used: namespaceRegex.test(afterImport) };
|
|
135
|
-
}
|
|
136
|
-
// For regular imports, check for identifier usage
|
|
137
|
-
const usageRegex = new RegExp(`\\b${id}\\b`, "g");
|
|
138
|
-
const matches = afterImport.match(usageRegex);
|
|
139
|
-
return { identifier: id, used: matches !== null && matches.length > 0 };
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* VC-HALL-001: Unused Security Imports
|
|
144
|
-
*
|
|
145
|
-
* Detects when security libraries are imported but not used
|
|
146
|
-
*/
|
|
147
|
-
export async function scanUnusedSecurityImports(context) {
|
|
148
|
-
const { repoRoot, fileIndex } = context;
|
|
149
|
-
const findings = [];
|
|
150
|
-
const libNames = SECURITY_LIBS.map((l) => l.name);
|
|
151
|
-
for (const relFile of fileIndex.allSourceFiles) {
|
|
152
|
-
const absPath = resolvePath(repoRoot, relFile);
|
|
153
|
-
const content = readFileSync(absPath);
|
|
154
|
-
if (!content)
|
|
155
|
-
continue;
|
|
156
|
-
const imports = findSecurityImports(content, libNames);
|
|
157
|
-
for (const imp of imports) {
|
|
158
|
-
const libInfo = SECURITY_LIBS.find((l) => l.name === imp.library);
|
|
159
|
-
if (!libInfo)
|
|
160
|
-
continue;
|
|
161
|
-
const usageResults = checkIdentifierUsage(content, imp.line, imp.importedNames, imp.isNamespaceImport);
|
|
162
|
-
const unusedIdentifiers = usageResults
|
|
163
|
-
.filter((r) => !r.used)
|
|
164
|
-
.map((r) => r.identifier);
|
|
165
|
-
if (unusedIdentifiers.length === 0)
|
|
166
|
-
continue;
|
|
167
|
-
// All imported identifiers are unused
|
|
168
|
-
const allUnused = unusedIdentifiers.length === imp.importedNames.length;
|
|
169
|
-
const evidence = [
|
|
170
|
-
{
|
|
171
|
-
file: relFile,
|
|
172
|
-
startLine: imp.line,
|
|
173
|
-
endLine: imp.line,
|
|
174
|
-
snippet: imp.snippet,
|
|
175
|
-
label: allUnused
|
|
176
|
-
? `Unused import of ${imp.library}`
|
|
177
|
-
: `Partially unused import: ${unusedIdentifiers.join(", ")}`,
|
|
178
|
-
},
|
|
179
|
-
];
|
|
180
|
-
const fingerprint = generateFingerprint({
|
|
181
|
-
ruleId: RULE_ID,
|
|
182
|
-
file: relFile,
|
|
183
|
-
symbol: imp.library,
|
|
184
|
-
startLine: imp.line,
|
|
185
|
-
});
|
|
186
|
-
findings.push({
|
|
187
|
-
id: generateFindingId({
|
|
188
|
-
ruleId: RULE_ID,
|
|
189
|
-
file: relFile,
|
|
190
|
-
symbol: imp.library,
|
|
191
|
-
startLine: imp.line,
|
|
192
|
-
}),
|
|
193
|
-
severity: libInfo.severity,
|
|
194
|
-
confidence: allUnused ? 0.9 : 0.75,
|
|
195
|
-
category: libInfo.category,
|
|
196
|
-
ruleId: RULE_ID,
|
|
197
|
-
title: allUnused
|
|
198
|
-
? `Imported ${libInfo.description.toLowerCase()} "${imp.library}" is not used`
|
|
199
|
-
: `Partially unused import from "${imp.library}"`,
|
|
200
|
-
description: allUnused
|
|
201
|
-
? `The security library "${imp.library}" is imported but none of its exports are used. This may indicate incomplete implementation of ${libInfo.category} functionality.`
|
|
202
|
-
: `Some exports from "${imp.library}" (${unusedIdentifiers.join(", ")}) are imported but not used. This may indicate incomplete implementation.`,
|
|
203
|
-
evidence,
|
|
204
|
-
remediation: {
|
|
205
|
-
recommendedFix: allUnused
|
|
206
|
-
? `Either implement ${libInfo.category} using "${imp.library}" or remove the unused import.`
|
|
207
|
-
: `Remove unused imports (${unusedIdentifiers.join(", ")}) or implement their usage.`,
|
|
208
|
-
},
|
|
209
|
-
fingerprint,
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return findings;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* VC-HALL-002: next-auth present but not enforced
|
|
217
|
-
*
|
|
218
|
-
* Detects when next-auth is installed but there's no middleware
|
|
219
|
-
* or server-side auth enforcement in route handlers
|
|
220
|
-
*/
|
|
221
|
-
export async function scanNextAuthNotEnforced(context) {
|
|
222
|
-
const { repoRoot, fileIndex, repoMeta, helpers } = context;
|
|
223
|
-
const findings = [];
|
|
224
|
-
// Only check if next-auth is present
|
|
225
|
-
if (!repoMeta.hasNextAuth) {
|
|
226
|
-
return findings;
|
|
227
|
-
}
|
|
228
|
-
// Check if middleware exists and uses next-auth
|
|
229
|
-
if (fileIndex.middlewareFile) {
|
|
230
|
-
const content = readFileSync(resolvePath(repoRoot, fileIndex.middlewareFile));
|
|
231
|
-
if (content && /next-auth|withAuth|getToken/.test(content)) {
|
|
232
|
-
return findings; // Middleware seems to enforce auth
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
// Check API routes for auth enforcement
|
|
236
|
-
let routesWithoutAuth = 0;
|
|
237
|
-
let totalRoutes = 0;
|
|
238
|
-
for (const relPath of fileIndex.apiRouteFiles) {
|
|
239
|
-
const absPath = resolvePath(repoRoot, relPath);
|
|
240
|
-
const sourceFile = helpers.parseFile(absPath);
|
|
241
|
-
if (!sourceFile)
|
|
242
|
-
continue;
|
|
243
|
-
const handlers = helpers.findRouteHandlers(sourceFile);
|
|
244
|
-
for (const handler of handlers) {
|
|
245
|
-
totalRoutes++;
|
|
246
|
-
if (!helpers.containsAuthCheck(handler.functionNode)) {
|
|
247
|
-
routesWithoutAuth++;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
// If most routes lack auth checks, emit finding
|
|
252
|
-
if (totalRoutes > 0 && routesWithoutAuth / totalRoutes > 0.5) {
|
|
253
|
-
const evidence = [
|
|
254
|
-
{
|
|
255
|
-
file: "package.json",
|
|
256
|
-
startLine: 1,
|
|
257
|
-
endLine: 1,
|
|
258
|
-
label: "next-auth is installed",
|
|
259
|
-
},
|
|
260
|
-
];
|
|
261
|
-
if (!fileIndex.middlewareFile) {
|
|
262
|
-
evidence.push({
|
|
263
|
-
file: "middleware.ts",
|
|
264
|
-
startLine: 1,
|
|
265
|
-
endLine: 1,
|
|
266
|
-
label: "No middleware file exists",
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
const fingerprint = generateFingerprint({
|
|
270
|
-
ruleId: RULE_ID_002,
|
|
271
|
-
file: "package.json",
|
|
272
|
-
symbol: "next-auth",
|
|
273
|
-
});
|
|
274
|
-
findings.push({
|
|
275
|
-
id: generateFindingId({
|
|
276
|
-
ruleId: RULE_ID_002,
|
|
277
|
-
file: "package.json",
|
|
278
|
-
symbol: "next-auth",
|
|
279
|
-
}),
|
|
280
|
-
ruleId: RULE_ID_002,
|
|
281
|
-
title: "next-auth installed but not enforced in most routes",
|
|
282
|
-
description: `next-auth is installed but ${routesWithoutAuth} of ${totalRoutes} API route handlers (${Math.round(routesWithoutAuth / totalRoutes * 100)}%) lack authentication checks. This may indicate incomplete auth implementation.`,
|
|
283
|
-
severity: "medium",
|
|
284
|
-
confidence: 0.75,
|
|
285
|
-
category: "auth",
|
|
286
|
-
evidence,
|
|
287
|
-
remediation: {
|
|
288
|
-
recommendedFix: "Add authentication middleware or explicit auth checks to API routes. See https://next-auth.js.org/configuration/nextjs",
|
|
289
|
-
patch: `// middleware.ts
|
|
290
|
-
import { withAuth } from "next-auth/middleware";
|
|
291
|
-
|
|
292
|
-
export default withAuth({
|
|
293
|
-
callbacks: {
|
|
294
|
-
authorized: ({ token }) => !!token,
|
|
295
|
-
},
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
export const config = {
|
|
299
|
-
matcher: ["/api/:path*"],
|
|
300
|
-
};`,
|
|
301
|
-
},
|
|
302
|
-
links: {
|
|
303
|
-
owasp: "https://owasp.org/Top10/A01_2021-Broken_Access_Control/",
|
|
304
|
-
},
|
|
305
|
-
fingerprint,
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
return findings;
|
|
309
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { AstHelpers, FileProgressCallback } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Create AST helpers with a ts-morph project
|
|
4
|
-
*/
|
|
5
|
-
export declare function createAstHelpers(repoRoot: string, totalFiles?: number, onFileProgress?: FileProgressCallback): AstHelpers;
|
|
6
|
-
//# sourceMappingURL=ast-helpers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ast-helpers.d.ts","sourceRoot":"","sources":["../../../src/scanners/helpers/ast-helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EAiBV,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAgDrB;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,oBAAoB,GACpC,UAAU,CA4hCZ"}
|