@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,124 +0,0 @@
1
- import { resolvePath, readFileSync } from "../../utils/file-utils.js";
2
- import { generateFingerprint, generateFindingId } from "../../utils/fingerprint.js";
3
- const RULE_ID = "VC-PRIV-003";
4
- /**
5
- * VC-PRIV-003: Debug flags enabled in production-ish config
6
- *
7
- * Detect:
8
- * - next.config.* or server config with `dev: true`, `debug: true`, or logging level "debug"
9
- *
10
- * Precision:
11
- * - Only if NODE_ENV is checked or project appears production-ready
12
- */
13
- export async function scanDebugFlags(context) {
14
- const { repoRoot, fileIndex } = context;
15
- const findings = [];
16
- // Check if project appears production-ready
17
- const hasVercelConfig = fileIndex.configFiles.some((f) => f.includes("vercel.json"));
18
- const pkgPath = resolvePath(repoRoot, "package.json");
19
- const pkgContent = readFileSync(pkgPath);
20
- const hasBuildScript = pkgContent && /"build"\s*:/.test(pkgContent);
21
- const isProdReady = hasVercelConfig || hasBuildScript;
22
- if (!isProdReady) {
23
- return findings;
24
- }
25
- // Check config files for debug flags
26
- const configPatterns = [
27
- "next.config.js",
28
- "next.config.mjs",
29
- "next.config.ts",
30
- "server.config.js",
31
- "server.config.ts",
32
- "app.config.js",
33
- "app.config.ts",
34
- ];
35
- for (const configFile of configPatterns) {
36
- const relPath = fileIndex.configFiles.find((f) => f.endsWith(configFile));
37
- if (!relPath)
38
- continue;
39
- const absPath = resolvePath(repoRoot, relPath);
40
- const content = readFileSync(absPath);
41
- if (!content)
42
- continue;
43
- // Check for debug flags
44
- const debugPatterns = [
45
- { pattern: /\bdev\s*:\s*true\b/, flag: "dev: true" },
46
- { pattern: /\bdebug\s*:\s*true\b/, flag: "debug: true" },
47
- { pattern: /logLevel\s*:\s*['"]debug['"]/, flag: 'logLevel: "debug"' },
48
- { pattern: /LOG_LEVEL\s*=\s*['"]debug['"]/, flag: 'LOG_LEVEL="debug"' },
49
- { pattern: /reactStrictMode\s*:\s*false\b/, flag: "reactStrictMode: false" },
50
- ];
51
- for (const { pattern, flag } of debugPatterns) {
52
- const match = content.match(pattern);
53
- if (!match)
54
- continue;
55
- // Check if it's conditional on NODE_ENV (which is acceptable)
56
- const lineIndex = content.substring(0, match.index).split("\n").length;
57
- const lines = content.split("\n");
58
- const contextStart = Math.max(0, lineIndex - 5);
59
- const contextEnd = Math.min(lines.length, lineIndex + 3);
60
- const contextLines = lines.slice(contextStart, contextEnd).join("\n");
61
- // Skip if guarded by NODE_ENV check
62
- if (/process\.env\.NODE_ENV\s*[!=]==?\s*['"]development['"]/i.test(contextLines)) {
63
- continue;
64
- }
65
- const evidence = [
66
- {
67
- file: relPath,
68
- startLine: lineIndex,
69
- endLine: lineIndex,
70
- snippet: lines[lineIndex - 1]?.trim() ?? flag,
71
- label: `Debug flag: ${flag}`,
72
- },
73
- ];
74
- if (hasVercelConfig) {
75
- evidence.push({
76
- file: "vercel.json",
77
- startLine: 1,
78
- endLine: 1,
79
- snippet: "Project has Vercel deployment config",
80
- label: "Production deployment detected",
81
- });
82
- }
83
- const fingerprint = generateFingerprint({
84
- ruleId: RULE_ID,
85
- file: relPath,
86
- symbol: flag,
87
- startLine: lineIndex,
88
- });
89
- findings.push({
90
- id: generateFindingId({
91
- ruleId: RULE_ID,
92
- file: relPath,
93
- symbol: flag,
94
- }),
95
- ruleId: RULE_ID,
96
- title: `Debug flag "${flag}" may be enabled in production`,
97
- description: `The configuration file contains ${flag} which may be active in production. Debug modes often expose sensitive information, enable verbose error messages, or disable security features. This configuration is not guarded by a NODE_ENV check.`,
98
- severity: "medium",
99
- confidence: 0.75,
100
- category: "config",
101
- evidence,
102
- remediation: {
103
- recommendedFix: `Ensure debug flags are only enabled in development. Use environment variables or NODE_ENV checks.`,
104
- patch: `// Guard debug flags with environment check:
105
- const isDev = process.env.NODE_ENV === 'development';
106
-
107
- module.exports = {
108
- // Only enable in development
109
- ...(isDev && { debug: true }),
110
-
111
- // Or use environment variable:
112
- debug: process.env.DEBUG === 'true',
113
- };`,
114
- },
115
- links: {
116
- cwe: "https://cwe.mitre.org/data/definitions/489.html",
117
- owasp: "https://owasp.org/Top10/A05_2021-Security_Misconfiguration/",
118
- },
119
- fingerprint,
120
- });
121
- }
122
- }
123
- return findings;
124
- }
@@ -1,6 +0,0 @@
1
- import type { ScannerPack } from "../types.js";
2
- export declare const privacyPack: ScannerPack;
3
- export { scanSensitiveLogging } from "./sensitive-logging.js";
4
- export { scanOverBroadResponse } from "./over-broad-response.js";
5
- export { scanDebugFlags } from "./debug-flags.js";
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/privacy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,eAAO,MAAM,WAAW,EAAE,WAIzB,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,11 +0,0 @@
1
- import { scanSensitiveLogging } from "./sensitive-logging.js";
2
- import { scanOverBroadResponse } from "./over-broad-response.js";
3
- import { scanDebugFlags } from "./debug-flags.js";
4
- export const privacyPack = {
5
- id: "privacy",
6
- name: "Privacy & Data Protection",
7
- scanners: [scanSensitiveLogging, scanOverBroadResponse, scanDebugFlags],
8
- };
9
- export { scanSensitiveLogging } from "./sensitive-logging.js";
10
- export { scanOverBroadResponse } from "./over-broad-response.js";
11
- export { scanDebugFlags } from "./debug-flags.js";
@@ -1,15 +0,0 @@
1
- import type { Finding } from "@vibecheck/schema";
2
- import type { ScanContext } from "../types.js";
3
- /**
4
- * VC-PRIV-002: Over-broad API response (returns whole ORM model)
5
- *
6
- * Detect in route handlers returning:
7
- * - prisma.<model>.findMany({}) without select/include restrictions AND direct return
8
- * - prisma.<model>.findUnique({ where }) without select AND direct return
9
- *
10
- * Precision:
11
- * - Only flag if the model name suggests sensitive entity (user, account, etc.)
12
- * - OR fields: password, hash, token are present in schema.prisma
13
- */
14
- export declare function scanOverBroadResponse(context: ScanContext): Promise<Finding[]>;
15
- //# sourceMappingURL=over-broad-response.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"over-broad-response.d.ts","sourceRoot":"","sources":["../../../src/scanners/privacy/over-broad-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAwGpF"}
@@ -1,109 +0,0 @@
1
- import { resolvePath } from "../../utils/file-utils.js";
2
- import { generateFingerprint, generateFindingId } from "../../utils/fingerprint.js";
3
- const RULE_ID = "VC-PRIV-002";
4
- /**
5
- * VC-PRIV-002: Over-broad API response (returns whole ORM model)
6
- *
7
- * Detect in route handlers returning:
8
- * - prisma.<model>.findMany({}) without select/include restrictions AND direct return
9
- * - prisma.<model>.findUnique({ where }) without select AND direct return
10
- *
11
- * Precision:
12
- * - Only flag if the model name suggests sensitive entity (user, account, etc.)
13
- * - OR fields: password, hash, token are present in schema.prisma
14
- */
15
- export async function scanOverBroadResponse(context) {
16
- const { repoRoot, fileIndex, helpers, prismaSchemaInfo } = context;
17
- const findings = [];
18
- // Scan API route files
19
- for (const relPath of fileIndex.apiRouteFiles) {
20
- const absPath = resolvePath(repoRoot, relPath);
21
- const sourceFile = helpers.parseFile(absPath);
22
- if (!sourceFile)
23
- continue;
24
- const handlers = helpers.findRouteHandlers(sourceFile);
25
- for (const handler of handlers) {
26
- const prismaQueries = helpers.findPrismaQueries(handler.functionNode);
27
- for (const query of prismaQueries) {
28
- // Skip if has select (data is restricted)
29
- if (query.hasSelect)
30
- continue;
31
- // Check if model has sensitive fields from prisma schema
32
- let hasSensitiveFields = false;
33
- if (prismaSchemaInfo) {
34
- const modelInfo = prismaSchemaInfo.models.get(query.model.toLowerCase());
35
- if (modelInfo) {
36
- hasSensitiveFields = modelInfo.hasSensitiveFields;
37
- }
38
- }
39
- // Determine severity based on sensitive fields
40
- const severity = hasSensitiveFields ? "high" : "medium";
41
- const evidence = [
42
- {
43
- file: relPath,
44
- startLine: query.line,
45
- endLine: query.line,
46
- snippet: query.snippet,
47
- label: `Returns full ${query.model} model without select restriction`,
48
- },
49
- ];
50
- // Add prisma schema evidence if available
51
- if (hasSensitiveFields && prismaSchemaInfo) {
52
- const modelInfo = prismaSchemaInfo.models.get(query.model.toLowerCase());
53
- if (modelInfo) {
54
- evidence.push({
55
- file: "prisma/schema.prisma",
56
- startLine: 1,
57
- endLine: 1,
58
- snippet: `Model ${modelInfo.name} has sensitive fields: ${modelInfo.fields.filter(f => /password|hash|token|secret/i.test(f)).join(", ")}`,
59
- label: "Sensitive fields in model",
60
- });
61
- }
62
- }
63
- const fingerprint = generateFingerprint({
64
- ruleId: RULE_ID,
65
- file: relPath,
66
- symbol: `${query.model}.${query.operation}`,
67
- startLine: query.line,
68
- });
69
- findings.push({
70
- id: generateFindingId({
71
- ruleId: RULE_ID,
72
- file: relPath,
73
- symbol: `${query.model}.${query.operation}`,
74
- startLine: query.line,
75
- }),
76
- ruleId: RULE_ID,
77
- title: `Over-broad ${query.model} response exposes all fields`,
78
- description: `The ${query.operation} query on the ${query.model} model returns all fields without using a \`select\` clause. This may inadvertently expose sensitive fields like passwords, tokens, or internal IDs to API consumers.${hasSensitiveFields ? " The Prisma schema indicates this model contains sensitive fields." : ""}`,
79
- severity,
80
- confidence: hasSensitiveFields ? 0.9 : 0.75,
81
- category: "privacy",
82
- evidence,
83
- remediation: {
84
- recommendedFix: `Use Prisma's \`select\` clause to explicitly choose which fields to return. Never expose password hashes, tokens, or other sensitive data in API responses.`,
85
- patch: `// Instead of:
86
- const users = await prisma.${query.model.toLowerCase()}.${query.operation}();
87
-
88
- // Use select to return only needed fields:
89
- const users = await prisma.${query.model.toLowerCase()}.${query.operation}({
90
- select: {
91
- id: true,
92
- name: true,
93
- email: true,
94
- createdAt: true,
95
- // Explicitly omit: password, passwordHash, tokens, etc.
96
- },
97
- });`,
98
- },
99
- links: {
100
- cwe: "https://cwe.mitre.org/data/definitions/359.html",
101
- owasp: "https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/",
102
- },
103
- fingerprint,
104
- });
105
- }
106
- }
107
- }
108
- return findings;
109
- }
@@ -1,11 +0,0 @@
1
- import type { Finding } from "@vibecheck/schema";
2
- import type { ScanContext } from "../types.js";
3
- /**
4
- * VC-PRIV-001: Sensitive data logged
5
- *
6
- * Detects console.log/info/error or logger calls that include:
7
- * - tokens, authorization headers, passwords, secrets
8
- * - Variables named: password, token, auth, authorization, cookie, session, secret, apiKey
9
- */
10
- export declare function scanSensitiveLogging(context: ScanContext): Promise<Finding[]>;
11
- //# sourceMappingURL=sensitive-logging.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sensitive-logging.d.ts","sourceRoot":"","sources":["../../../src/scanners/privacy/sensitive-logging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA2EnF"}
@@ -1,78 +0,0 @@
1
- import { resolvePath } from "../../utils/file-utils.js";
2
- import { generateFingerprint, generateFindingId } from "../../utils/fingerprint.js";
3
- const RULE_ID = "VC-PRIV-001";
4
- /**
5
- * VC-PRIV-001: Sensitive data logged
6
- *
7
- * Detects console.log/info/error or logger calls that include:
8
- * - tokens, authorization headers, passwords, secrets
9
- * - Variables named: password, token, auth, authorization, cookie, session, secret, apiKey
10
- */
11
- export async function scanSensitiveLogging(context) {
12
- const { repoRoot, fileIndex, helpers } = context;
13
- const findings = [];
14
- // Scan all source files
15
- for (const relPath of fileIndex.allSourceFiles) {
16
- const absPath = resolvePath(repoRoot, relPath);
17
- const sourceFile = helpers.parseFile(absPath);
18
- if (!sourceFile)
19
- continue;
20
- // Find all functions in the file
21
- const functions = sourceFile.getFunctions();
22
- const arrowFunctions = sourceFile.getDescendantsOfKind(
23
- // @ts-expect-error - ts-morph types
24
- sourceFile.getProject().getTypeChecker().compilerObject.SyntaxKind?.ArrowFunction ?? 213);
25
- // Check module-level code as well
26
- const sensitiveLogCalls = helpers.findSensitiveLogCalls({
27
- // Create a pseudo-function node that covers the whole file
28
- getDescendantsOfKind: (kind) => sourceFile.getDescendantsOfKind(kind),
29
- getText: () => sourceFile.getText(),
30
- });
31
- for (const logCall of sensitiveLogCalls) {
32
- const evidence = [
33
- {
34
- file: relPath,
35
- startLine: logCall.line,
36
- endLine: logCall.line,
37
- snippet: logCall.snippet,
38
- label: `Sensitive data logged: ${logCall.sensitiveVars.join(", ")}`,
39
- },
40
- ];
41
- const fingerprint = generateFingerprint({
42
- ruleId: RULE_ID,
43
- file: relPath,
44
- symbol: logCall.sensitiveVars[0],
45
- startLine: logCall.line,
46
- });
47
- findings.push({
48
- id: generateFindingId({
49
- ruleId: RULE_ID,
50
- file: relPath,
51
- symbol: logCall.sensitiveVars[0],
52
- startLine: logCall.line,
53
- }),
54
- ruleId: RULE_ID,
55
- title: `Sensitive data in logs: ${logCall.sensitiveVars.join(", ")}`,
56
- description: `The ${logCall.logMethod} call includes sensitive data (${logCall.sensitiveVars.join(", ")}). This could expose credentials, tokens, or other sensitive information in log files, monitoring systems, or console output.`,
57
- severity: logCall.severity,
58
- confidence: 0.88,
59
- category: "privacy",
60
- evidence,
61
- remediation: {
62
- recommendedFix: `Remove sensitive data from log statements. Only log non-sensitive identifiers like user IDs, timestamps, or action types.`,
63
- patch: `// Instead of:
64
- console.log("Login:", { email, password });
65
-
66
- // Do:
67
- console.log("Login attempt:", { email, timestamp: Date.now() });`,
68
- },
69
- links: {
70
- cwe: "https://cwe.mitre.org/data/definitions/532.html",
71
- owasp: "https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/",
72
- },
73
- fingerprint,
74
- });
75
- }
76
- }
77
- return findings;
78
- }