@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.
Files changed (208) hide show
  1. package/README.md +6 -6
  2. package/dist/index.d.ts +0 -2
  3. package/dist/index.js +7902 -8
  4. package/package.json +13 -7
  5. package/dist/__tests__/cli.test.d.ts +0 -2
  6. package/dist/__tests__/cli.test.d.ts.map +0 -1
  7. package/dist/__tests__/cli.test.js +0 -243
  8. package/dist/__tests__/fixtures/safe-app/app/api/users/route.js +0 -36
  9. package/dist/__tests__/fixtures/vulnerable-app/app/api/users/route.js +0 -28
  10. package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts +0 -4
  11. package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts.map +0 -1
  12. package/dist/__tests__/fixtures/vulnerable-app/lib/config.js +0 -6
  13. package/dist/__tests__/scanners/env-config.test.d.ts +0 -2
  14. package/dist/__tests__/scanners/env-config.test.d.ts.map +0 -1
  15. package/dist/__tests__/scanners/env-config.test.js +0 -142
  16. package/dist/__tests__/scanners/nextjs-middleware.test.d.ts +0 -2
  17. package/dist/__tests__/scanners/nextjs-middleware.test.d.ts.map +0 -1
  18. package/dist/__tests__/scanners/nextjs-middleware.test.js +0 -193
  19. package/dist/__tests__/scanners/scanner-packs.test.d.ts +0 -2
  20. package/dist/__tests__/scanners/scanner-packs.test.d.ts.map +0 -1
  21. package/dist/__tests__/scanners/scanner-packs.test.js +0 -126
  22. package/dist/__tests__/scanners/unused-security-imports.test.d.ts +0 -2
  23. package/dist/__tests__/scanners/unused-security-imports.test.d.ts.map +0 -1
  24. package/dist/__tests__/scanners/unused-security-imports.test.js +0 -145
  25. package/dist/commands/demo-artifact.d.ts +0 -7
  26. package/dist/commands/demo-artifact.d.ts.map +0 -1
  27. package/dist/commands/demo-artifact.js +0 -322
  28. package/dist/commands/evaluate.d.ts +0 -30
  29. package/dist/commands/evaluate.d.ts.map +0 -1
  30. package/dist/commands/evaluate.js +0 -258
  31. package/dist/commands/explain.d.ts +0 -12
  32. package/dist/commands/explain.d.ts.map +0 -1
  33. package/dist/commands/explain.js +0 -214
  34. package/dist/commands/index.d.ts +0 -7
  35. package/dist/commands/index.d.ts.map +0 -1
  36. package/dist/commands/index.js +0 -6
  37. package/dist/commands/intent.d.ts +0 -21
  38. package/dist/commands/intent.d.ts.map +0 -1
  39. package/dist/commands/intent.js +0 -192
  40. package/dist/commands/scan.d.ts +0 -44
  41. package/dist/commands/scan.d.ts.map +0 -1
  42. package/dist/commands/scan.js +0 -497
  43. package/dist/commands/waivers.d.ts +0 -30
  44. package/dist/commands/waivers.d.ts.map +0 -1
  45. package/dist/commands/waivers.js +0 -249
  46. package/dist/index.d.ts.map +0 -1
  47. package/dist/phase3/index.d.ts +0 -11
  48. package/dist/phase3/index.d.ts.map +0 -1
  49. package/dist/phase3/index.js +0 -12
  50. package/dist/phase3/intent-miner.d.ts +0 -32
  51. package/dist/phase3/intent-miner.d.ts.map +0 -1
  52. package/dist/phase3/intent-miner.js +0 -323
  53. package/dist/phase3/proof-trace-builder.d.ts +0 -42
  54. package/dist/phase3/proof-trace-builder.d.ts.map +0 -1
  55. package/dist/phase3/proof-trace-builder.js +0 -441
  56. package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts +0 -15
  57. package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts.map +0 -1
  58. package/dist/phase3/scanners/auth-by-ui-server-gap.js +0 -237
  59. package/dist/phase3/scanners/comment-claim-unproven.d.ts +0 -14
  60. package/dist/phase3/scanners/comment-claim-unproven.d.ts.map +0 -1
  61. package/dist/phase3/scanners/comment-claim-unproven.js +0 -161
  62. package/dist/phase3/scanners/index.d.ts +0 -31
  63. package/dist/phase3/scanners/index.d.ts.map +0 -1
  64. package/dist/phase3/scanners/index.js +0 -40
  65. package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts +0 -14
  66. package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts.map +0 -1
  67. package/dist/phase3/scanners/middleware-assumed-not-matching.js +0 -172
  68. package/dist/phase3/scanners/validation-claimed-missing.d.ts +0 -15
  69. package/dist/phase3/scanners/validation-claimed-missing.d.ts.map +0 -1
  70. package/dist/phase3/scanners/validation-claimed-missing.js +0 -204
  71. package/dist/scanners/abuse/compute-abuse.d.ts +0 -20
  72. package/dist/scanners/abuse/compute-abuse.d.ts.map +0 -1
  73. package/dist/scanners/abuse/compute-abuse.js +0 -509
  74. package/dist/scanners/abuse/index.d.ts +0 -12
  75. package/dist/scanners/abuse/index.d.ts.map +0 -1
  76. package/dist/scanners/abuse/index.js +0 -15
  77. package/dist/scanners/auth/index.d.ts +0 -5
  78. package/dist/scanners/auth/index.d.ts.map +0 -1
  79. package/dist/scanners/auth/index.js +0 -10
  80. package/dist/scanners/auth/middleware-gap.d.ts +0 -22
  81. package/dist/scanners/auth/middleware-gap.d.ts.map +0 -1
  82. package/dist/scanners/auth/middleware-gap.js +0 -203
  83. package/dist/scanners/auth/unprotected-api-route.d.ts +0 -12
  84. package/dist/scanners/auth/unprotected-api-route.d.ts.map +0 -1
  85. package/dist/scanners/auth/unprotected-api-route.js +0 -126
  86. package/dist/scanners/config/index.d.ts +0 -5
  87. package/dist/scanners/config/index.d.ts.map +0 -1
  88. package/dist/scanners/config/index.js +0 -10
  89. package/dist/scanners/config/insecure-defaults.d.ts +0 -12
  90. package/dist/scanners/config/insecure-defaults.d.ts.map +0 -1
  91. package/dist/scanners/config/insecure-defaults.js +0 -77
  92. package/dist/scanners/config/undocumented-env.d.ts +0 -24
  93. package/dist/scanners/config/undocumented-env.d.ts.map +0 -1
  94. package/dist/scanners/config/undocumented-env.js +0 -159
  95. package/dist/scanners/crypto/index.d.ts +0 -6
  96. package/dist/scanners/crypto/index.d.ts.map +0 -1
  97. package/dist/scanners/crypto/index.js +0 -11
  98. package/dist/scanners/crypto/jwt-decode-unverified.d.ts +0 -14
  99. package/dist/scanners/crypto/jwt-decode-unverified.d.ts.map +0 -1
  100. package/dist/scanners/crypto/jwt-decode-unverified.js +0 -87
  101. package/dist/scanners/crypto/math-random-tokens.d.ts +0 -13
  102. package/dist/scanners/crypto/math-random-tokens.d.ts.map +0 -1
  103. package/dist/scanners/crypto/math-random-tokens.js +0 -80
  104. package/dist/scanners/crypto/weak-hashing.d.ts +0 -11
  105. package/dist/scanners/crypto/weak-hashing.d.ts.map +0 -1
  106. package/dist/scanners/crypto/weak-hashing.js +0 -95
  107. package/dist/scanners/env-config.d.ts +0 -24
  108. package/dist/scanners/env-config.d.ts.map +0 -1
  109. package/dist/scanners/env-config.js +0 -164
  110. package/dist/scanners/hallucinations/index.d.ts +0 -4
  111. package/dist/scanners/hallucinations/index.d.ts.map +0 -1
  112. package/dist/scanners/hallucinations/index.js +0 -8
  113. package/dist/scanners/hallucinations/unused-security-imports.d.ts +0 -36
  114. package/dist/scanners/hallucinations/unused-security-imports.d.ts.map +0 -1
  115. package/dist/scanners/hallucinations/unused-security-imports.js +0 -309
  116. package/dist/scanners/helpers/ast-helpers.d.ts +0 -6
  117. package/dist/scanners/helpers/ast-helpers.d.ts.map +0 -1
  118. package/dist/scanners/helpers/ast-helpers.js +0 -945
  119. package/dist/scanners/helpers/context-builder.d.ts +0 -17
  120. package/dist/scanners/helpers/context-builder.d.ts.map +0 -1
  121. package/dist/scanners/helpers/context-builder.js +0 -148
  122. package/dist/scanners/helpers/index.d.ts +0 -3
  123. package/dist/scanners/helpers/index.d.ts.map +0 -1
  124. package/dist/scanners/helpers/index.js +0 -2
  125. package/dist/scanners/index.d.ts +0 -30
  126. package/dist/scanners/index.d.ts.map +0 -1
  127. package/dist/scanners/index.js +0 -102
  128. package/dist/scanners/middleware/index.d.ts +0 -4
  129. package/dist/scanners/middleware/index.d.ts.map +0 -1
  130. package/dist/scanners/middleware/index.js +0 -7
  131. package/dist/scanners/middleware/missing-rate-limit.d.ts +0 -13
  132. package/dist/scanners/middleware/missing-rate-limit.d.ts.map +0 -1
  133. package/dist/scanners/middleware/missing-rate-limit.js +0 -140
  134. package/dist/scanners/network/cors-misconfiguration.d.ts +0 -14
  135. package/dist/scanners/network/cors-misconfiguration.d.ts.map +0 -1
  136. package/dist/scanners/network/cors-misconfiguration.js +0 -89
  137. package/dist/scanners/network/index.d.ts +0 -7
  138. package/dist/scanners/network/index.d.ts.map +0 -1
  139. package/dist/scanners/network/index.js +0 -18
  140. package/dist/scanners/network/missing-timeout.d.ts +0 -15
  141. package/dist/scanners/network/missing-timeout.d.ts.map +0 -1
  142. package/dist/scanners/network/missing-timeout.js +0 -93
  143. package/dist/scanners/network/open-redirect.d.ts +0 -15
  144. package/dist/scanners/network/open-redirect.d.ts.map +0 -1
  145. package/dist/scanners/network/open-redirect.js +0 -88
  146. package/dist/scanners/network/ssrf-prone-fetch.d.ts +0 -12
  147. package/dist/scanners/network/ssrf-prone-fetch.d.ts.map +0 -1
  148. package/dist/scanners/network/ssrf-prone-fetch.js +0 -90
  149. package/dist/scanners/nextjs-middleware.d.ts +0 -26
  150. package/dist/scanners/nextjs-middleware.d.ts.map +0 -1
  151. package/dist/scanners/nextjs-middleware.js +0 -246
  152. package/dist/scanners/privacy/debug-flags.d.ts +0 -13
  153. package/dist/scanners/privacy/debug-flags.d.ts.map +0 -1
  154. package/dist/scanners/privacy/debug-flags.js +0 -124
  155. package/dist/scanners/privacy/index.d.ts +0 -6
  156. package/dist/scanners/privacy/index.d.ts.map +0 -1
  157. package/dist/scanners/privacy/index.js +0 -11
  158. package/dist/scanners/privacy/over-broad-response.d.ts +0 -15
  159. package/dist/scanners/privacy/over-broad-response.d.ts.map +0 -1
  160. package/dist/scanners/privacy/over-broad-response.js +0 -109
  161. package/dist/scanners/privacy/sensitive-logging.d.ts +0 -11
  162. package/dist/scanners/privacy/sensitive-logging.d.ts.map +0 -1
  163. package/dist/scanners/privacy/sensitive-logging.js +0 -78
  164. package/dist/scanners/types.d.ts +0 -456
  165. package/dist/scanners/types.d.ts.map +0 -1
  166. package/dist/scanners/types.js +0 -16
  167. package/dist/scanners/unused-security-imports.d.ts +0 -34
  168. package/dist/scanners/unused-security-imports.d.ts.map +0 -1
  169. package/dist/scanners/unused-security-imports.js +0 -206
  170. package/dist/scanners/uploads/index.d.ts +0 -5
  171. package/dist/scanners/uploads/index.d.ts.map +0 -1
  172. package/dist/scanners/uploads/index.js +0 -9
  173. package/dist/scanners/uploads/missing-constraints.d.ts +0 -15
  174. package/dist/scanners/uploads/missing-constraints.d.ts.map +0 -1
  175. package/dist/scanners/uploads/missing-constraints.js +0 -109
  176. package/dist/scanners/uploads/public-path.d.ts +0 -11
  177. package/dist/scanners/uploads/public-path.d.ts.map +0 -1
  178. package/dist/scanners/uploads/public-path.js +0 -87
  179. package/dist/scanners/validation/client-side-only.d.ts +0 -14
  180. package/dist/scanners/validation/client-side-only.d.ts.map +0 -1
  181. package/dist/scanners/validation/client-side-only.js +0 -140
  182. package/dist/scanners/validation/ignored-validation.d.ts +0 -12
  183. package/dist/scanners/validation/ignored-validation.d.ts.map +0 -1
  184. package/dist/scanners/validation/ignored-validation.js +0 -119
  185. package/dist/scanners/validation/index.d.ts +0 -5
  186. package/dist/scanners/validation/index.d.ts.map +0 -1
  187. package/dist/scanners/validation/index.js +0 -9
  188. package/dist/utils/exclude-patterns.d.ts +0 -35
  189. package/dist/utils/exclude-patterns.d.ts.map +0 -1
  190. package/dist/utils/exclude-patterns.js +0 -78
  191. package/dist/utils/file-utils.d.ts +0 -37
  192. package/dist/utils/file-utils.d.ts.map +0 -1
  193. package/dist/utils/file-utils.js +0 -77
  194. package/dist/utils/fingerprint.d.ts +0 -25
  195. package/dist/utils/fingerprint.d.ts.map +0 -1
  196. package/dist/utils/fingerprint.js +0 -28
  197. package/dist/utils/git-info.d.ts +0 -14
  198. package/dist/utils/git-info.d.ts.map +0 -1
  199. package/dist/utils/git-info.js +0 -55
  200. package/dist/utils/index.d.ts +0 -4
  201. package/dist/utils/index.d.ts.map +0 -1
  202. package/dist/utils/index.js +0 -3
  203. package/dist/utils/progress.d.ts +0 -42
  204. package/dist/utils/progress.d.ts.map +0 -1
  205. package/dist/utils/progress.js +0 -165
  206. package/dist/utils/sarif-formatter.d.ts +0 -92
  207. package/dist/utils/sarif-formatter.d.ts.map +0 -1
  208. package/dist/utils/sarif-formatter.js +0 -172
@@ -1,172 +0,0 @@
1
- /**
2
- * VC-HALL-011: Middleware Assumed But Not Matching
3
- *
4
- * Detects routes that appear to expect middleware protection
5
- * but are not covered by the middleware matcher patterns.
6
- *
7
- * Severity: High
8
- * Category: hallucinations
9
- * Confidence: 0.70
10
- */
11
- import crypto from "node:crypto";
12
- import { buildRouteMap, buildMiddlewareMap, isRouteCoveredByMiddleware, } from "../proof-trace-builder.js";
13
- import { mineAllIntentClaims } from "../intent-miner.js";
14
- const RULE_ID = "VC-HALL-011";
15
- /**
16
- * Signals that a route expects middleware protection
17
- */
18
- const MIDDLEWARE_EXPECTATION_SIGNALS = [
19
- // Comments
20
- /middleware.*protect/i,
21
- /protected\s*by\s*middleware/i,
22
- /middleware\s*handles?\s*auth/i,
23
- /auth\s*(is|handled)\s*(by|in)\s*middleware/i,
24
- // Code patterns that suggest middleware dependency
25
- /withMiddleware/,
26
- /requireMiddleware/,
27
- /middlewareProtected/,
28
- ];
29
- export async function scanMiddlewareAssumedNotMatching(ctx) {
30
- const findings = [];
31
- // Build maps
32
- const routes = buildRouteMap(ctx);
33
- const middlewareMap = buildMiddlewareMap(ctx);
34
- // If no middleware file exists, skip this scanner
35
- if (middlewareMap.length === 0) {
36
- return findings;
37
- }
38
- const allMatchers = middlewareMap.flatMap((m) => m.matchers);
39
- const intentClaims = mineAllIntentClaims(ctx, routes);
40
- // Find routes that expect middleware but aren't covered
41
- for (const route of routes) {
42
- const isCovered = isRouteCoveredByMiddleware(route.path, allMatchers);
43
- if (isCovered)
44
- continue;
45
- // Check if this route has signals expecting middleware
46
- const expectsMiddleware = checkMiddlewareExpectation(ctx, route, intentClaims);
47
- if (expectsMiddleware.expected) {
48
- findings.push({
49
- id: generateFindingId(route),
50
- severity: "high",
51
- confidence: 0.7,
52
- category: "hallucinations",
53
- ruleId: RULE_ID,
54
- title: `Route ${route.method} ${route.path} expects middleware but is not covered`,
55
- description: generateDescription(route, middlewareMap[0], expectsMiddleware.reason),
56
- evidence: [
57
- {
58
- file: route.file,
59
- startLine: route.startLine,
60
- endLine: route.endLine,
61
- snippet: `export async function ${route.method}(request: Request)`,
62
- label: "Route expecting middleware protection",
63
- },
64
- ...(expectsMiddleware.evidenceLocation
65
- ? [
66
- {
67
- file: expectsMiddleware.evidenceLocation.file,
68
- startLine: expectsMiddleware.evidenceLocation.line,
69
- endLine: expectsMiddleware.evidenceLocation.line,
70
- snippet: expectsMiddleware.evidenceSnippet || "",
71
- label: "Signal expecting middleware",
72
- },
73
- ]
74
- : []),
75
- {
76
- file: middlewareMap[0].file,
77
- startLine: middlewareMap[0].startLine,
78
- endLine: middlewareMap[0].startLine,
79
- snippet: `matcher: ${JSON.stringify(allMatchers)}`,
80
- label: "Current middleware matcher (does not cover this route)",
81
- },
82
- ],
83
- remediation: {
84
- recommendedFix: generateRemediation(route, allMatchers),
85
- },
86
- fingerprint: generateFingerprint(route),
87
- });
88
- }
89
- }
90
- return findings;
91
- }
92
- function checkMiddlewareExpectation(ctx, route, claims) {
93
- // Check intent claims for middleware protection
94
- const middlewareClaims = claims.filter((c) => c.type === "MIDDLEWARE_PROTECTED" &&
95
- (c.targetRouteId === route.routeId || c.scope === "global" || c.location.file === route.file));
96
- if (middlewareClaims.length > 0) {
97
- const claim = middlewareClaims[0];
98
- return {
99
- expected: true,
100
- reason: "Intent claim indicates middleware protection expected",
101
- evidenceLocation: {
102
- file: claim.location.file,
103
- line: claim.location.startLine,
104
- },
105
- evidenceSnippet: claim.textEvidence,
106
- };
107
- }
108
- // Check source file for middleware expectation signals
109
- const sourceFile = ctx.helpers.parseFile(require("path").join(ctx.repoRoot, route.file));
110
- if (sourceFile) {
111
- const fullText = sourceFile.getFullText();
112
- for (const signal of MIDDLEWARE_EXPECTATION_SIGNALS) {
113
- const match = fullText.match(signal);
114
- if (match) {
115
- const pos = match.index || 0;
116
- const line = sourceFile.getLineAndColumnAtPos(pos).line;
117
- return {
118
- expected: true,
119
- reason: "Code pattern suggests middleware protection expected",
120
- evidenceLocation: {
121
- file: route.file,
122
- line,
123
- },
124
- evidenceSnippet: match[0],
125
- };
126
- }
127
- }
128
- }
129
- // Check if auth claims exist but no auth check in handler
130
- const authClaims = claims.filter((c) => c.type === "AUTH_ENFORCED" &&
131
- c.source === "comment" &&
132
- (c.targetRouteId === route.routeId || c.location.file === route.file));
133
- if (authClaims.length > 0) {
134
- // Check if the handler has its own auth check
135
- const handlers = ctx.helpers.findRouteHandlers(sourceFile);
136
- const handler = handlers.find((h) => h.method === route.method);
137
- if (handler && !ctx.helpers.containsAuthCheck(handler.functionNode)) {
138
- // Auth is claimed but not in handler - might expect middleware
139
- const claim = authClaims[0];
140
- return {
141
- expected: true,
142
- reason: "Auth claimed in comment but not in handler - may expect middleware",
143
- evidenceLocation: {
144
- file: claim.location.file,
145
- line: claim.location.startLine,
146
- },
147
- evidenceSnippet: claim.textEvidence,
148
- };
149
- }
150
- }
151
- return { expected: false, reason: "" };
152
- }
153
- function generateDescription(route, middleware, reason) {
154
- return (`The route ${route.method} ${route.path} shows signals that it expects middleware protection, ` +
155
- `but the middleware matcher in ${middleware.file} does not cover this path. ` +
156
- `${reason}. This could leave the route unprotected.`);
157
- }
158
- function generateRemediation(route, currentMatchers) {
159
- const suggestedPattern = route.path.includes("/api/")
160
- ? "/api/:path*"
161
- : `${route.path}/:path*`;
162
- return (`Update the middleware matcher to include this route. ` +
163
- `Current matchers: ${JSON.stringify(currentMatchers)}. ` +
164
- `Consider adding "${suggestedPattern}" or add explicit auth in the handler.`);
165
- }
166
- function generateFindingId(route) {
167
- return `f-${crypto.randomUUID().slice(0, 8)}`;
168
- }
169
- function generateFingerprint(route) {
170
- const data = `${RULE_ID}:${route.file}:${route.method}:${route.path}`;
171
- return `sha256:${crypto.createHash("sha256").update(data).digest("hex")}`;
172
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * VC-HALL-012: Validation Claimed But Missing/Ignored
3
- *
4
- * Detects routes where validation is claimed (via comments, imports,
5
- * or identifiers) but is either not implemented or the validated
6
- * result is not used.
7
- *
8
- * Severity: Medium
9
- * Category: hallucinations
10
- * Confidence: 0.80
11
- */
12
- import type { Finding } from "@vibecheck/schema";
13
- import type { ScanContext } from "../../scanners/types.js";
14
- export declare function scanValidationClaimedMissing(ctx: ScanContext): Promise<Finding[]>;
15
- //# sourceMappingURL=validation-claimed-missing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validation-claimed-missing.d.ts","sourceRoot":"","sources":["../../../src/phase3/scanners/validation-claimed-missing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAA0B,MAAM,yBAAyB,CAAC;AAMnF,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,OAAO,EAAE,CAAC,CAmGpB"}
@@ -1,204 +0,0 @@
1
- /**
2
- * VC-HALL-012: Validation Claimed But Missing/Ignored
3
- *
4
- * Detects routes where validation is claimed (via comments, imports,
5
- * or identifiers) but is either not implemented or the validated
6
- * result is not used.
7
- *
8
- * Severity: Medium
9
- * Category: hallucinations
10
- * Confidence: 0.80
11
- */
12
- import crypto from "node:crypto";
13
- import path from "node:path";
14
- import { buildRouteMap, buildAllProofTraces } from "../proof-trace-builder.js";
15
- import { mineAllIntentClaims } from "../intent-miner.js";
16
- const RULE_ID = "VC-HALL-012";
17
- export async function scanValidationClaimedMissing(ctx) {
18
- const findings = [];
19
- // Build route map and proof traces
20
- const routes = buildRouteMap(ctx);
21
- const proofTraces = buildAllProofTraces(ctx, routes);
22
- const intentClaims = mineAllIntentClaims(ctx, routes);
23
- // Find validation claims
24
- const validationClaims = intentClaims.filter((c) => c.type === "INPUT_VALIDATED");
25
- // Group claims by file for efficiency
26
- const claimsByFile = new Map();
27
- for (const claim of validationClaims) {
28
- const existing = claimsByFile.get(claim.location.file) || [];
29
- existing.push(claim);
30
- claimsByFile.set(claim.location.file, existing);
31
- }
32
- // Check each file with validation claims
33
- for (const [file, claims] of claimsByFile) {
34
- const sourceFile = ctx.helpers.parseFile(path.join(ctx.repoRoot, file));
35
- if (!sourceFile)
36
- continue;
37
- // Find routes in this file
38
- const fileRoutes = routes.filter((r) => r.file === file);
39
- const handlers = ctx.helpers.findRouteHandlers(sourceFile);
40
- for (const handler of handlers) {
41
- const route = fileRoutes.find((r) => r.method === handler.method);
42
- if (!route)
43
- continue;
44
- // Check if this handler should have validation
45
- const relevantClaims = claims.filter((c) => c.targetRouteId === route.routeId ||
46
- c.scope === "module" ||
47
- c.scope === "global" ||
48
- (c.location.startLine <= handler.startLine &&
49
- c.location.endLine >= handler.startLine - 5) // Claim is near handler
50
- );
51
- if (relevantClaims.length === 0)
52
- continue;
53
- // Check actual validation status
54
- const validationUsage = ctx.helpers.findValidationUsage(handler.functionNode);
55
- // Case 1: No validation at all despite claims
56
- if (validationUsage.length === 0) {
57
- findings.push(createFinding(route, relevantClaims[0], "missing", "Validation is claimed but no validation library usage found in handler"));
58
- continue;
59
- }
60
- // Case 2: Validation exists but result not assigned
61
- const unassigned = validationUsage.filter((v) => !v.resultAssigned);
62
- if (unassigned.length > 0) {
63
- findings.push(createFinding(route, relevantClaims[0], "ignored_result", "Validation is called but the result is not assigned to a variable", {
64
- file: route.file,
65
- line: unassigned[0].line,
66
- snippet: ctx.helpers.getNodeText(unassigned[0].node).slice(0, 100),
67
- }));
68
- continue;
69
- }
70
- // Case 3: Validation result assigned but raw body still used
71
- const rawBodyUsed = validationUsage.filter((v) => v.rawBodyUsedAfter);
72
- if (rawBodyUsed.length > 0) {
73
- findings.push(createFinding(route, relevantClaims[0], "bypassed", "Validation is performed but raw request body is used afterward instead of validated data", {
74
- file: route.file,
75
- line: rawBodyUsed[0].line,
76
- snippet: ctx.helpers.getNodeText(rawBodyUsed[0].node).slice(0, 100),
77
- }));
78
- }
79
- }
80
- }
81
- // Also check for validation imports that are never used
82
- findings.push(...checkUnusedValidationImports(ctx, routes, intentClaims));
83
- return findings;
84
- }
85
- function createFinding(route, claim, issueType, description, additionalEvidence) {
86
- const evidence = [
87
- {
88
- file: claim.location.file,
89
- startLine: claim.location.startLine,
90
- endLine: claim.location.endLine,
91
- snippet: claim.textEvidence,
92
- label: `Validation claim (${claim.source})`,
93
- },
94
- {
95
- file: route.file,
96
- startLine: route.startLine,
97
- endLine: route.endLine,
98
- snippet: `${route.method} ${route.path}`,
99
- label: "Route handler",
100
- },
101
- ];
102
- if (additionalEvidence) {
103
- evidence.push({
104
- file: additionalEvidence.file,
105
- startLine: additionalEvidence.line,
106
- endLine: additionalEvidence.line,
107
- snippet: additionalEvidence.snippet,
108
- label: issueType === "ignored_result" ? "Unused validation call" : "Raw body usage",
109
- });
110
- }
111
- return {
112
- id: `f-${crypto.randomUUID().slice(0, 8)}`,
113
- severity: "medium",
114
- confidence: 0.8,
115
- category: "hallucinations",
116
- ruleId: RULE_ID,
117
- title: generateTitle(route, issueType),
118
- description,
119
- evidence,
120
- remediation: {
121
- recommendedFix: generateRemediation(issueType),
122
- },
123
- fingerprint: generateFingerprint(route, issueType),
124
- };
125
- }
126
- function generateTitle(route, issueType) {
127
- switch (issueType) {
128
- case "missing":
129
- return `Validation claimed but missing in ${route.method} ${route.path}`;
130
- case "ignored_result":
131
- return `Validation result ignored in ${route.method} ${route.path}`;
132
- case "bypassed":
133
- return `Validation bypassed in ${route.method} ${route.path}`;
134
- default:
135
- return `Validation issue in ${route.method} ${route.path}`;
136
- }
137
- }
138
- function generateRemediation(issueType) {
139
- switch (issueType) {
140
- case "missing":
141
- return ("Implement validation using Zod, Yup, or Joi. " +
142
- "Example: `const validated = schema.parse(await request.json());` " +
143
- "Then use `validated` instead of the raw request body.");
144
- case "ignored_result":
145
- return ("Assign the validation result to a variable and use it: " +
146
- "`const validated = schema.parse(body);` " +
147
- "Then pass `validated` to database operations.");
148
- case "bypassed":
149
- return ("Replace usage of raw `body`, `req.body`, or `request.json()` result " +
150
- "with the validated data. Using raw input after validation defeats its purpose.");
151
- default:
152
- return "Ensure validation is properly implemented and the validated result is used.";
153
- }
154
- }
155
- function checkUnusedValidationImports(ctx, routes, claims) {
156
- const findings = [];
157
- // Find import-based validation claims
158
- const importClaims = claims.filter((c) => c.type === "INPUT_VALIDATED" && c.source === "import");
159
- for (const claim of importClaims) {
160
- const sourceFile = ctx.helpers.parseFile(path.join(ctx.repoRoot, claim.location.file));
161
- if (!sourceFile)
162
- continue;
163
- // Check if validation schemas/methods are actually defined and used
164
- const hasSchemas = ctx.helpers.hasValidationSchemas(sourceFile);
165
- if (!hasSchemas) {
166
- // Validation library imported but no schemas defined
167
- const fileRoutes = routes.filter((r) => r.file === claim.location.file);
168
- if (fileRoutes.length > 0) {
169
- findings.push({
170
- id: `f-${crypto.randomUUID().slice(0, 8)}`,
171
- severity: "medium",
172
- confidence: 0.7,
173
- category: "hallucinations",
174
- ruleId: RULE_ID,
175
- title: `Validation library imported but no schemas defined in ${claim.location.file}`,
176
- description: "A validation library is imported suggesting validation intent, " +
177
- "but no validation schemas are defined in the file. " +
178
- "This could be dead code or incomplete implementation.",
179
- evidence: [
180
- {
181
- file: claim.location.file,
182
- startLine: claim.location.startLine,
183
- endLine: claim.location.endLine,
184
- snippet: claim.textEvidence,
185
- label: "Validation import",
186
- },
187
- ],
188
- remediation: {
189
- recommendedFix: "Define validation schemas using the imported library, or remove the unused import.",
190
- },
191
- fingerprint: `sha256:${crypto
192
- .createHash("sha256")
193
- .update(`${RULE_ID}:${claim.location.file}:import_unused`)
194
- .digest("hex")}`,
195
- });
196
- }
197
- }
198
- }
199
- return findings;
200
- }
201
- function generateFingerprint(route, issueType) {
202
- const data = `${RULE_ID}:${route.file}:${route.method}:${issueType}`;
203
- return `sha256:${crypto.createHash("sha256").update(data).digest("hex")}`;
204
- }
@@ -1,20 +0,0 @@
1
- import type { Finding } from "@vibecheck/schema";
2
- import type { ScanContext } from "../types.js";
3
- /**
4
- * VC-ABUSE-001 to VC-ABUSE-004: Compute Abuse Detection
5
- *
6
- * Detects compute-intensive endpoints that may be vulnerable to abuse:
7
- * - AI/LLM generation endpoints
8
- * - Code execution endpoints
9
- * - File processing endpoints
10
- * - Expensive API endpoints
11
- *
12
- * Checks for missing enforcement:
13
- * - Authentication
14
- * - Rate limiting
15
- * - Request size limits
16
- * - Timeouts
17
- * - Input validation
18
- */
19
- export declare function scanComputeAbuse(context: ScanContext): Promise<Finding[]>;
20
- //# sourceMappingURL=compute-abuse.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compute-abuse.d.ts","sourceRoot":"","sources":["../../../src/scanners/abuse/compute-abuse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqC,MAAM,mBAAmB,CAAC;AACpF,OAAO,KAAK,EAAE,WAAW,EAA8B,MAAM,aAAa,CAAC;AAyW3E;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA8H/E"}