@vibecheckai/cli 3.5.0 → 3.5.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 (224) hide show
  1. package/bin/registry.js +214 -237
  2. package/bin/runners/cli-utils.js +33 -2
  3. package/bin/runners/context/analyzer.js +52 -1
  4. package/bin/runners/context/generators/cursor.js +2 -49
  5. package/bin/runners/context/git-context.js +3 -1
  6. package/bin/runners/context/team-conventions.js +33 -7
  7. package/bin/runners/lib/analysis-core.js +25 -5
  8. package/bin/runners/lib/analyzers.js +431 -481
  9. package/bin/runners/lib/default-config.js +127 -0
  10. package/bin/runners/lib/doctor/modules/security.js +3 -1
  11. package/bin/runners/lib/engine/ast-cache.js +210 -0
  12. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  13. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  14. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  15. package/bin/runners/lib/engine/env-extractor.js +207 -0
  16. package/bin/runners/lib/engine/express-extractor.js +208 -0
  17. package/bin/runners/lib/engine/extractors.js +849 -0
  18. package/bin/runners/lib/engine/index.js +207 -0
  19. package/bin/runners/lib/engine/repo-index.js +514 -0
  20. package/bin/runners/lib/engine/types.js +124 -0
  21. package/bin/runners/lib/engines/accessibility-engine.js +18 -218
  22. package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
  23. package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
  24. package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
  25. package/bin/runners/lib/engines/mock-data-engine.js +10 -53
  26. package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
  27. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
  28. package/bin/runners/lib/engines/type-aware-engine.js +39 -263
  29. package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
  30. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  31. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  32. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  33. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  34. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  35. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  36. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  37. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
  38. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  39. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  40. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  41. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  42. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  43. package/bin/runners/lib/entitlements-v2.js +73 -97
  44. package/bin/runners/lib/error-handler.js +44 -3
  45. package/bin/runners/lib/error-messages.js +289 -0
  46. package/bin/runners/lib/evidence-pack.js +7 -1
  47. package/bin/runners/lib/finding-id.js +69 -0
  48. package/bin/runners/lib/finding-sorter.js +89 -0
  49. package/bin/runners/lib/html-proof-report.js +700 -350
  50. package/bin/runners/lib/missions/plan.js +6 -46
  51. package/bin/runners/lib/missions/templates.js +0 -232
  52. package/bin/runners/lib/next-action.js +560 -0
  53. package/bin/runners/lib/prerequisites.js +149 -0
  54. package/bin/runners/lib/route-detection.js +137 -68
  55. package/bin/runners/lib/scan-output.js +91 -76
  56. package/bin/runners/lib/scan-runner.js +135 -0
  57. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  58. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  59. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  60. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  61. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  62. package/bin/runners/lib/schemas/validator.js +27 -0
  63. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  64. package/bin/runners/lib/ship-output-enterprise.js +23 -23
  65. package/bin/runners/lib/ship-output.js +75 -31
  66. package/bin/runners/lib/terminal-ui.js +6 -113
  67. package/bin/runners/lib/truth.js +351 -10
  68. package/bin/runners/lib/unified-cli-output.js +430 -603
  69. package/bin/runners/lib/unified-output.js +13 -9
  70. package/bin/runners/runAIAgent.js +10 -5
  71. package/bin/runners/runAgent.js +0 -3
  72. package/bin/runners/runAllowlist.js +389 -0
  73. package/bin/runners/runApprove.js +0 -33
  74. package/bin/runners/runAuth.js +73 -45
  75. package/bin/runners/runCheckpoint.js +51 -11
  76. package/bin/runners/runClassify.js +85 -21
  77. package/bin/runners/runContext.js +0 -3
  78. package/bin/runners/runDoctor.js +41 -28
  79. package/bin/runners/runEvidencePack.js +362 -0
  80. package/bin/runners/runFirewall.js +0 -3
  81. package/bin/runners/runFirewallHook.js +0 -3
  82. package/bin/runners/runFix.js +66 -76
  83. package/bin/runners/runGuard.js +18 -411
  84. package/bin/runners/runInit.js +113 -30
  85. package/bin/runners/runLabs.js +424 -0
  86. package/bin/runners/runMcp.js +19 -25
  87. package/bin/runners/runPolish.js +64 -240
  88. package/bin/runners/runPromptFirewall.js +12 -5
  89. package/bin/runners/runProve.js +57 -22
  90. package/bin/runners/runQuickstart.js +531 -0
  91. package/bin/runners/runReality.js +59 -68
  92. package/bin/runners/runReport.js +38 -33
  93. package/bin/runners/runRuntime.js +8 -5
  94. package/bin/runners/runScan.js +1413 -190
  95. package/bin/runners/runShip.js +113 -719
  96. package/bin/runners/runTruth.js +0 -3
  97. package/bin/runners/runValidate.js +13 -9
  98. package/bin/runners/runWatch.js +23 -14
  99. package/bin/scan.js +6 -1
  100. package/bin/vibecheck.js +204 -185
  101. package/mcp-server/deprecation-middleware.js +282 -0
  102. package/mcp-server/handlers/index.ts +15 -0
  103. package/mcp-server/handlers/tool-handler.ts +554 -0
  104. package/mcp-server/index-v1.js +698 -0
  105. package/mcp-server/index.js +210 -238
  106. package/mcp-server/lib/cache-wrapper.cjs +383 -0
  107. package/mcp-server/lib/error-envelope.js +138 -0
  108. package/mcp-server/lib/executor.ts +499 -0
  109. package/mcp-server/lib/index.ts +19 -0
  110. package/mcp-server/lib/rate-limiter.js +166 -0
  111. package/mcp-server/lib/sandbox.test.ts +519 -0
  112. package/mcp-server/lib/sandbox.ts +395 -0
  113. package/mcp-server/lib/types.ts +267 -0
  114. package/mcp-server/package.json +12 -3
  115. package/mcp-server/registry/tool-registry.js +794 -0
  116. package/mcp-server/registry/tools.json +605 -0
  117. package/mcp-server/registry.test.ts +334 -0
  118. package/mcp-server/tests/tier-gating.test.js +297 -0
  119. package/mcp-server/tier-auth.js +378 -45
  120. package/mcp-server/tools-v3.js +353 -442
  121. package/mcp-server/tsconfig.json +37 -0
  122. package/mcp-server/vibecheck-2.0-tools.js +14 -1
  123. package/package.json +1 -1
  124. package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
  125. package/bin/runners/lib/audit-logger.js +0 -532
  126. package/bin/runners/lib/authority/authorities/architecture.js +0 -364
  127. package/bin/runners/lib/authority/authorities/compliance.js +0 -341
  128. package/bin/runners/lib/authority/authorities/human.js +0 -343
  129. package/bin/runners/lib/authority/authorities/quality.js +0 -420
  130. package/bin/runners/lib/authority/authorities/security.js +0 -228
  131. package/bin/runners/lib/authority/index.js +0 -293
  132. package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
  133. package/bin/runners/lib/cli-charts.js +0 -368
  134. package/bin/runners/lib/cli-config-display.js +0 -405
  135. package/bin/runners/lib/cli-demo.js +0 -275
  136. package/bin/runners/lib/cli-errors.js +0 -438
  137. package/bin/runners/lib/cli-help-formatter.js +0 -439
  138. package/bin/runners/lib/cli-interactive-menu.js +0 -509
  139. package/bin/runners/lib/cli-prompts.js +0 -441
  140. package/bin/runners/lib/cli-scan-cards.js +0 -362
  141. package/bin/runners/lib/compliance-reporter.js +0 -710
  142. package/bin/runners/lib/conductor/index.js +0 -671
  143. package/bin/runners/lib/easy/README.md +0 -123
  144. package/bin/runners/lib/easy/index.js +0 -140
  145. package/bin/runners/lib/easy/interactive-wizard.js +0 -788
  146. package/bin/runners/lib/easy/one-click-firewall.js +0 -564
  147. package/bin/runners/lib/easy/zero-config-reality.js +0 -714
  148. package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
  149. package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
  150. package/bin/runners/lib/engines/confidence-scoring.js +0 -276
  151. package/bin/runners/lib/engines/context-detection.js +0 -264
  152. package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
  153. package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
  154. package/bin/runners/lib/engines/env-variables-engine.js +0 -458
  155. package/bin/runners/lib/engines/error-handling-engine.js +0 -437
  156. package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
  157. package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
  158. package/bin/runners/lib/engines/framework-detection.js +0 -508
  159. package/bin/runners/lib/engines/import-order-engine.js +0 -429
  160. package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
  161. package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
  162. package/bin/runners/lib/engines/orchestrator.js +0 -334
  163. package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
  164. package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
  165. package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
  166. package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
  167. package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
  168. package/bin/runners/lib/enhanced-features/index.js +0 -305
  169. package/bin/runners/lib/enhanced-output.js +0 -631
  170. package/bin/runners/lib/enterprise.js +0 -300
  171. package/bin/runners/lib/firewall/command-validator.js +0 -351
  172. package/bin/runners/lib/firewall/config.js +0 -341
  173. package/bin/runners/lib/firewall/content-validator.js +0 -519
  174. package/bin/runners/lib/firewall/index.js +0 -101
  175. package/bin/runners/lib/firewall/path-validator.js +0 -256
  176. package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
  177. package/bin/runners/lib/mcp-utils.js +0 -425
  178. package/bin/runners/lib/output/index.js +0 -1022
  179. package/bin/runners/lib/policy-engine.js +0 -652
  180. package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
  181. package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
  182. package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
  183. package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
  184. package/bin/runners/lib/polish/autofix/index.js +0 -200
  185. package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
  186. package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
  187. package/bin/runners/lib/polish/backend-checks.js +0 -148
  188. package/bin/runners/lib/polish/documentation-checks.js +0 -111
  189. package/bin/runners/lib/polish/frontend-checks.js +0 -168
  190. package/bin/runners/lib/polish/index.js +0 -71
  191. package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
  192. package/bin/runners/lib/polish/library-detection.js +0 -175
  193. package/bin/runners/lib/polish/performance-checks.js +0 -100
  194. package/bin/runners/lib/polish/security-checks.js +0 -148
  195. package/bin/runners/lib/polish/utils.js +0 -203
  196. package/bin/runners/lib/prompt-builder.js +0 -540
  197. package/bin/runners/lib/proof-certificate.js +0 -634
  198. package/bin/runners/lib/reality/accessibility-audit.js +0 -946
  199. package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
  200. package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
  201. package/bin/runners/lib/reality/performance-tracker.js +0 -1077
  202. package/bin/runners/lib/reality/scenario-generator.js +0 -1404
  203. package/bin/runners/lib/reality/visual-regression.js +0 -852
  204. package/bin/runners/lib/reality-profiler.js +0 -717
  205. package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
  206. package/bin/runners/lib/review/ai-code-review.js +0 -832
  207. package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
  208. package/bin/runners/lib/sbom-generator.js +0 -641
  209. package/bin/runners/lib/scan-output-enhanced.js +0 -512
  210. package/bin/runners/lib/security/owasp-scanner.js +0 -939
  211. package/bin/runners/lib/validators/contract-validator.js +0 -283
  212. package/bin/runners/lib/validators/dead-export-detector.js +0 -279
  213. package/bin/runners/lib/validators/dep-audit.js +0 -245
  214. package/bin/runners/lib/validators/env-validator.js +0 -319
  215. package/bin/runners/lib/validators/index.js +0 -120
  216. package/bin/runners/lib/validators/license-checker.js +0 -252
  217. package/bin/runners/lib/validators/route-validator.js +0 -290
  218. package/bin/runners/runAuthority.js +0 -528
  219. package/bin/runners/runConductor.js +0 -772
  220. package/bin/runners/runContainer.js +0 -366
  221. package/bin/runners/runEasy.js +0 -410
  222. package/bin/runners/runIaC.js +0 -372
  223. package/bin/runners/runVibe.js +0 -791
  224. package/mcp-server/tools.js +0 -495
@@ -1,11 +1,6 @@
1
1
  /**
2
2
  * Security Vulnerabilities Detection Engine
3
3
  * Detects SQL injection, XSS, command injection, path traversal, and other security issues
4
- * Enhanced with smart detection to reduce false positives:
5
- * - Detects parameterized queries (prepared statements)
6
- * - Detects sanitization libraries (DOMPurify, xss, sanitize-html)
7
- * - Detects path validation (path.resolve, path.normalize)
8
- * - Framework-specific patterns (Prisma, Drizzle, Knex, TypeORM)
9
4
  */
10
5
 
11
6
  const { getAST } = require("./ast-cache");
@@ -13,138 +8,6 @@ const traverse = require("@babel/traverse").default;
13
8
  const t = require("@babel/types");
14
9
  const { shouldExcludeFile } = require("./file-filter");
15
10
 
16
- /**
17
- * Safe ORM/Query Builder patterns that use parameterized queries by default
18
- */
19
- const SAFE_ORM_PATTERNS = [
20
- // Prisma
21
- /prisma\.\w+\.(?:findUnique|findFirst|findMany|create|update|delete|upsert)/i,
22
- /prisma\.\$queryRaw`/i, // Tagged template = safe
23
- /prisma\.\$executeRaw`/i,
24
- // Drizzle
25
- /db\.select\(\)|db\.insert\(\)|db\.update\(\)|db\.delete\(\)/i,
26
- // TypeORM
27
- /\.createQueryBuilder\(\)/i,
28
- /getRepository\(\)\.find/i,
29
- // Knex
30
- /knex\(\s*['"]?\w+['"]?\s*\)\.where/i,
31
- /knex\.raw\(\s*['"][^'"]+['"]\s*,\s*\[/i, // knex.raw with params array
32
- // Sequelize
33
- /\.findAll\(|\.findOne\(|\.create\(|\.update\(/i,
34
- // MongoDB/Mongoose
35
- /\.find\(\{|\.findOne\(\{|\.aggregate\(\[/i,
36
- ];
37
-
38
- /**
39
- * Check if a line uses a safe ORM pattern
40
- */
41
- function usesSafeORM(line, surroundingLines) {
42
- const context = surroundingLines ? [...surroundingLines, line].join('\n') : line;
43
- return SAFE_ORM_PATTERNS.some(pattern => pattern.test(context));
44
- }
45
-
46
- /**
47
- * Sanitization library patterns
48
- */
49
- const SANITIZATION_PATTERNS = [
50
- // DOMPurify
51
- /DOMPurify\.sanitize\(/i,
52
- /purify\.sanitize\(/i,
53
- // xss library
54
- /\bxss\s*\(/i,
55
- /filterXSS\(/i,
56
- // sanitize-html
57
- /sanitizeHtml\(/i,
58
- /sanitize\(/i,
59
- // escape-html
60
- /escapeHtml\(/i,
61
- /escape\(/i,
62
- // React's built-in escaping (JSX)
63
- /dangerouslySetInnerHTML/i, // When this is NOT present, React escapes by default
64
- // encode-html-entities
65
- /htmlEncode\(/i,
66
- /encodeHTML\(/i,
67
- ];
68
-
69
- /**
70
- * Check if content is sanitized before use
71
- */
72
- function isSanitized(line, surroundingLines) {
73
- const context = surroundingLines ? [...surroundingLines, line].join('\n') : line;
74
- return SANITIZATION_PATTERNS.some(pattern => pattern.test(context));
75
- }
76
-
77
- /**
78
- * Path validation patterns
79
- */
80
- const PATH_VALIDATION_PATTERNS = [
81
- // path.resolve normalizes and makes absolute
82
- /path\.resolve\(/i,
83
- // path.normalize removes .. traversals
84
- /path\.normalize\(/i,
85
- // path.join with validation
86
- /path\.join\(\s*__dirname/i,
87
- /path\.join\(\s*process\.cwd\(\)/i,
88
- // Common validation patterns
89
- /\.startsWith\(\s*(?:baseDir|rootDir|allowedPath|safeDir)/i,
90
- /\.includes\(\s*['"]\.\.["']\s*\)/i, // Manual check for ..
91
- /!.*\.includes\(\s*['"]\.\.["']\s*\)/i, // Negated check
92
- ];
93
-
94
- /**
95
- * Check if path is validated/sanitized
96
- */
97
- function isPathValidated(line, surroundingLines) {
98
- const context = surroundingLines ? [...surroundingLines, line].join('\n') : line;
99
- return PATH_VALIDATION_PATTERNS.some(pattern => pattern.test(context));
100
- }
101
-
102
- /**
103
- * Check if SQL query uses parameterized placeholders
104
- */
105
- function usesParameterizedQuery(args, code) {
106
- if (!args || args.length === 0) return false;
107
-
108
- const firstArg = args[0];
109
-
110
- // Check for placeholder patterns in the query string
111
- if (t.isStringLiteral(firstArg)) {
112
- const query = firstArg.value;
113
- // PostgreSQL: $1, $2, etc.
114
- if (/\$\d+/.test(query)) return true;
115
- // MySQL: ?, ?? placeholders
116
- if (/\?/.test(query)) return true;
117
- // Named parameters: :name, @name
118
- if (/[:@]\w+/.test(query)) return true;
119
- }
120
-
121
- // Check for tagged template literals (safe by default in most ORMs)
122
- if (t.isTaggedTemplateExpression(args[0])) {
123
- return true;
124
- }
125
-
126
- // Check if there's a second argument that's an array (params)
127
- if (args.length >= 2 && t.isArrayExpression(args[1])) {
128
- return true;
129
- }
130
-
131
- // Check if second argument is an object (named params)
132
- if (args.length >= 2 && t.isObjectExpression(args[1])) {
133
- return true;
134
- }
135
-
136
- return false;
137
- }
138
-
139
- /**
140
- * Get surrounding lines for context analysis
141
- */
142
- function getSurroundingLines(lines, lineIndex, range = 3) {
143
- const start = Math.max(0, lineIndex - range);
144
- const end = Math.min(lines.length, lineIndex + range + 1);
145
- return lines.slice(start, end);
146
- }
147
-
148
11
  /**
149
12
  * Analyze a file for security vulnerabilities
150
13
  */
@@ -159,7 +22,7 @@ function analyzeSecurityVulnerabilities(code, filePath) {
159
22
 
160
23
  const lines = code.split("\n");
161
24
 
162
- // SQL Injection patterns - Enhanced with ORM/parameterization detection
25
+ // SQL Injection patterns
163
26
  traverse(ast, {
164
27
  CallExpression(path) {
165
28
  const node = path.node;
@@ -171,44 +34,24 @@ function analyzeSecurityVulnerabilities(code, filePath) {
171
34
 
172
35
  // Database query methods
173
36
  if (t.isIdentifier(prop) &&
174
- ["query", "execute", "exec", "run", "raw"].includes(prop.name)) {
175
-
176
- const lineNum = node.loc.start.line;
177
- const lineContent = lines[lineNum - 1] || "";
178
- const surroundingLines = getSurroundingLines(lines, lineNum - 1);
179
-
180
- // Skip if using safe ORM patterns
181
- if (usesSafeORM(lineContent, surroundingLines)) {
182
- return;
183
- }
184
-
185
- // Skip if using parameterized queries
186
- if (usesParameterizedQuery(node.arguments, code)) {
187
- return;
188
- }
37
+ ["query", "execute", "exec", "run"].includes(prop.name)) {
189
38
 
190
39
  // Check if arguments contain template literals or string concatenation
191
40
  for (const arg of node.arguments) {
192
41
  if (t.isTemplateLiteral(arg) ||
193
42
  (t.isBinaryExpression(arg) && arg.operator === "+")) {
194
-
195
- // Double-check it's not a tagged template (safe)
196
- if (t.isTaggedTemplateExpression(arg)) {
197
- continue;
198
- }
199
-
43
+ const line = node.loc.start.line;
200
44
  findings.push({
201
45
  type: "sql_injection",
202
46
  severity: "BLOCK",
203
47
  category: "Security",
204
48
  file: filePath,
205
- line: lineNum,
49
+ line,
206
50
  column: node.loc.start.column,
207
51
  title: "Potential SQL injection vulnerability",
208
- message: "SQL query constructed with string interpolation. Use parameterized queries instead.",
209
- codeSnippet: lineContent.trim(),
52
+ message: "SQL query constructed with user input without parameterization",
53
+ codeSnippet: lines[line - 1]?.trim(),
210
54
  confidence: "high",
211
- fixHint: "Use parameterized queries: query('SELECT * FROM users WHERE id = $1', [userId])",
212
55
  });
213
56
  break;
214
57
  }
@@ -218,7 +61,7 @@ function analyzeSecurityVulnerabilities(code, filePath) {
218
61
  },
219
62
  });
220
63
 
221
- // XSS vulnerabilities - Enhanced with sanitization detection
64
+ // XSS vulnerabilities
222
65
  traverse(ast, {
223
66
  CallExpression(path) {
224
67
  const node = path.node;
@@ -231,38 +74,21 @@ function analyzeSecurityVulnerabilities(code, filePath) {
231
74
  if (t.isIdentifier(prop) &&
232
75
  ["innerHTML", "outerHTML", "insertAdjacentHTML"].includes(prop.name)) {
233
76
 
234
- const lineNum = node.loc.start.line;
235
- const lineContent = lines[lineNum - 1] || "";
236
- const surroundingLines = getSurroundingLines(lines, lineNum - 1, 5);
237
-
238
- // Skip if content is sanitized
239
- if (isSanitized(lineContent, surroundingLines)) {
240
- return;
241
- }
242
-
243
77
  // Check if argument comes from user input or URL params
244
78
  for (const arg of node.arguments) {
245
79
  if (t.isIdentifier(arg) || t.isMemberExpression(arg)) {
246
- // Check if the argument itself is a sanitize call
247
- if (t.isCallExpression(arg)) {
248
- const argCode = code.substring(arg.start, arg.end);
249
- if (SANITIZATION_PATTERNS.some(p => p.test(argCode))) {
250
- continue;
251
- }
252
- }
253
-
80
+ const line = node.loc.start.line;
254
81
  findings.push({
255
82
  type: "xss",
256
83
  severity: "BLOCK",
257
84
  category: "Security",
258
85
  file: filePath,
259
- line: lineNum,
86
+ line,
260
87
  column: node.loc.start.column,
261
88
  title: "Potential XSS vulnerability",
262
- message: `Using ${prop.name} with potentially unsafe content. Sanitize before rendering.`,
263
- codeSnippet: lineContent.trim(),
89
+ message: `Using ${prop.name} with potentially unsafe content`,
90
+ codeSnippet: lines[line - 1]?.trim(),
264
91
  confidence: "med",
265
- fixHint: "Use DOMPurify.sanitize(content) or sanitize-html before setting innerHTML",
266
92
  });
267
93
  break;
268
94
  }
@@ -271,229 +97,75 @@ function analyzeSecurityVulnerabilities(code, filePath) {
271
97
  }
272
98
  },
273
99
  });
274
-
275
- // Also check for dangerouslySetInnerHTML in React
276
- traverse(ast, {
277
- JSXAttribute(path) {
278
- const node = path.node;
279
-
280
- if (t.isJSXIdentifier(node.name, { name: "dangerouslySetInnerHTML" })) {
281
- const lineNum = node.loc.start.line;
282
- const lineContent = lines[lineNum - 1] || "";
283
- const surroundingLines = getSurroundingLines(lines, lineNum - 1, 5);
284
-
285
- // Skip if content is sanitized
286
- if (isSanitized(lineContent, surroundingLines)) {
287
- return;
288
- }
289
-
290
- findings.push({
291
- type: "xss",
292
- severity: "WARN",
293
- category: "Security",
294
- file: filePath,
295
- line: lineNum,
296
- column: node.loc.start.column,
297
- title: "Potential XSS via dangerouslySetInnerHTML",
298
- message: "Using dangerouslySetInnerHTML without visible sanitization",
299
- codeSnippet: lineContent.trim(),
300
- confidence: "med",
301
- fixHint: "Sanitize content with DOMPurify.sanitize() before rendering",
302
- });
303
- }
304
- },
305
- });
306
100
 
307
- // Command injection - Enhanced with shell escape detection
308
- const SHELL_ESCAPE_PATTERNS = [
309
- /shellEscape\(/i,
310
- /escapeShell\(/i,
311
- /shell-escape/i,
312
- /shellescape/i,
313
- /quote\(/i, // shell-quote
314
- ];
315
-
316
- function isShellEscaped(line, surroundingLines) {
317
- const context = surroundingLines ? [...surroundingLines, line].join('\n') : line;
318
- return SHELL_ESCAPE_PATTERNS.some(pattern => pattern.test(context));
319
- }
320
-
101
+ // Command injection
321
102
  traverse(ast, {
322
103
  CallExpression(path) {
323
104
  const node = path.node;
324
105
 
325
106
  // Dangerous command execution methods
326
- let methodName = null;
327
-
328
- if (t.isIdentifier(node.callee)) {
329
- methodName = node.callee.name;
330
- } else if (t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.property)) {
331
- methodName = node.callee.property.name;
332
- }
333
-
334
- const dangerousMethods = ["exec", "spawn", "execSync", "spawnSync", "execFile", "execFileSync"];
335
-
336
- if (methodName && dangerousMethods.includes(methodName)) {
337
- const lineNum = node.loc.start.line;
338
- const lineContent = lines[lineNum - 1] || "";
339
- const surroundingLines = getSurroundingLines(lines, lineNum - 1, 5);
340
-
341
- // Skip if shell-escaped
342
- if (isShellEscaped(lineContent, surroundingLines)) {
343
- return;
344
- }
345
-
346
- // Check if arguments contain user input
347
- for (const arg of node.arguments) {
348
- if (t.isTemplateLiteral(arg) ||
349
- (t.isBinaryExpression(arg) && arg.operator === "+")) {
350
- findings.push({
351
- type: "command_injection",
352
- severity: "BLOCK",
353
- category: "Security",
354
- file: filePath,
355
- line: lineNum,
356
- column: node.loc.start.column,
357
- title: "Potential command injection vulnerability",
358
- message: "Command execution with string interpolation. Use array args or shell-escape.",
359
- codeSnippet: lineContent.trim(),
360
- confidence: "high",
361
- fixHint: "Use spawn with array arguments: spawn('cmd', [arg1, arg2]) instead of shell strings",
362
- });
363
- break;
364
- }
365
- }
366
- }
367
- },
368
- });
369
-
370
- // SSRF (Server-Side Request Forgery) detection
371
- traverse(ast, {
372
- CallExpression(path) {
373
- const node = path.node;
374
-
375
- // Check for fetch, axios, http.request with dynamic URLs
376
- let isHttpCall = false;
377
- let methodName = "";
378
-
379
107
  if (t.isIdentifier(node.callee)) {
380
- isHttpCall = ["fetch", "axios", "request", "got", "superagent"].includes(node.callee.name);
381
- methodName = node.callee.name;
382
- } else if (t.isMemberExpression(node.callee)) {
383
- const prop = node.callee.property;
384
- if (t.isIdentifier(prop)) {
385
- isHttpCall = ["get", "post", "put", "delete", "request", "fetch"].includes(prop.name);
386
- methodName = prop.name;
387
- }
388
- }
389
-
390
- if (isHttpCall && node.arguments.length > 0) {
391
- const urlArg = node.arguments[0];
108
+ const dangerousMethods = ["exec", "spawn", "execSync", "spawnSync"];
392
109
 
393
- // Check if URL contains user input
394
- if (t.isTemplateLiteral(urlArg) && urlArg.expressions && urlArg.expressions.length > 0) {
395
- const lineNum = node.loc.start.line;
396
- const lineContent = lines[lineNum - 1] || "";
397
- const surroundingLines = getSurroundingLines(lines, lineNum - 1, 5);
398
-
399
- // Check for URL validation patterns
400
- const urlValidationPatterns = [
401
- /new URL\(/i,
402
- /url\.parse\(/i,
403
- /isValidUrl\(/i,
404
- /validateUrl\(/i,
405
- /allowedHosts/i,
406
- /whitelist/i,
407
- ];
408
-
409
- const hasUrlValidation = urlValidationPatterns.some(p =>
410
- p.test(lineContent) || p.test(surroundingLines.join('\n'))
411
- );
412
-
413
- if (!hasUrlValidation) {
414
- findings.push({
415
- type: "ssrf",
416
- severity: "WARN",
417
- category: "Security",
418
- file: filePath,
419
- line: lineNum,
420
- column: node.loc.start.column,
421
- title: "Potential SSRF vulnerability",
422
- message: "HTTP request with user-controlled URL without visible validation",
423
- codeSnippet: lineContent.trim(),
424
- confidence: "med",
425
- fixHint: "Validate URLs against an allowlist of hosts before making requests",
426
- });
110
+ if (dangerousMethods.includes(node.callee.name)) {
111
+ // Check if arguments contain user input
112
+ for (const arg of node.arguments) {
113
+ if (t.isTemplateLiteral(arg) ||
114
+ (t.isBinaryExpression(arg) && arg.operator === "+")) {
115
+ const line = node.loc.start.line;
116
+ findings.push({
117
+ type: "command_injection",
118
+ severity: "BLOCK",
119
+ category: "Security",
120
+ file: filePath,
121
+ line,
122
+ column: node.loc.start.column,
123
+ title: "Potential command injection vulnerability",
124
+ message: "Command execution with potentially unsafe user input",
125
+ codeSnippet: lines[line - 1]?.trim(),
126
+ confidence: "high",
127
+ });
128
+ break;
129
+ }
427
130
  }
428
131
  }
429
132
  }
430
133
  },
431
134
  });
432
135
 
433
- // Path traversal - Enhanced with path validation detection
136
+ // Path traversal
434
137
  traverse(ast, {
435
138
  CallExpression(path) {
436
139
  const node = path.node;
437
140
 
438
141
  // File system operations
439
- if (t.isMemberExpression(node.callee)) {
440
- const obj = node.callee.object;
142
+ if (t.isMemberExpression(node.callee) &&
143
+ t.isIdentifier(node.callee.object, { name: "fs" })) {
441
144
  const prop = node.callee.property;
442
145
 
443
- // Check for fs.* or fs/promises methods
444
- const isFsCall = t.isIdentifier(obj, { name: "fs" }) ||
445
- t.isIdentifier(obj, { name: "fsp" }) ||
446
- t.isIdentifier(obj, { name: "fsPromises" });
447
-
448
- if (isFsCall && t.isIdentifier(prop) &&
449
- ["readFile", "writeFile", "readFileSync", "writeFileSync", "unlink",
450
- "unlinkSync", "access", "accessSync", "stat", "statSync",
451
- "readdir", "readdirSync", "mkdir", "mkdirSync"].includes(prop.name)) {
452
-
453
- const lineNum = node.loc.start.line;
454
- const lineContent = lines[lineNum - 1] || "";
455
- const surroundingLines = getSurroundingLines(lines, lineNum - 1, 5);
456
-
457
- // Skip if path is validated/sanitized
458
- if (isPathValidated(lineContent, surroundingLines)) {
459
- return;
460
- }
146
+ if (t.isIdentifier(prop) &&
147
+ ["readFile", "writeFile", "readFileSync", "writeFileSync", "unlink"].includes(prop.name)) {
461
148
 
462
149
  // Check if path contains user input or "../"
463
150
  for (const arg of node.arguments) {
464
- let hasTraversal = false;
465
- let hasUserInput = false;
466
-
467
151
  if (t.isTemplateLiteral(arg)) {
468
152
  const template = code.substring(arg.start, arg.end);
469
- hasTraversal = template.includes("../") || template.includes("..\\");
470
- hasUserInput = arg.expressions && arg.expressions.length > 0;
471
- } else if (t.isBinaryExpression(arg) && arg.operator === "+") {
472
- // String concatenation with user input
473
- hasUserInput = true;
474
- } else if (t.isIdentifier(arg)) {
475
- // Variable path - check if it looks like user input
476
- const varName = arg.name.toLowerCase();
477
- hasUserInput = /path|file|dir|folder|name|input|param|query|body|req/i.test(varName);
478
- }
479
-
480
- if (hasTraversal || hasUserInput) {
481
- findings.push({
482
- type: "path_traversal",
483
- severity: hasTraversal ? "BLOCK" : "WARN",
484
- category: "Security",
485
- file: filePath,
486
- line: lineNum,
487
- column: node.loc.start.column,
488
- title: "Potential path traversal vulnerability",
489
- message: hasTraversal
490
- ? "File operation with path containing '..' - validate and sanitize paths"
491
- : "File operation with potentially user-controlled path - validate before use",
492
- codeSnippet: lineContent.trim(),
493
- confidence: hasTraversal ? "high" : "med",
494
- fixHint: "Use path.resolve() with a base directory and validate the result starts with the expected prefix",
495
- });
496
- break;
153
+ if (template.includes("../") || template.includes("..\\")) {
154
+ const line = node.loc.start.line;
155
+ findings.push({
156
+ type: "path_traversal",
157
+ severity: "BLOCK",
158
+ category: "Security",
159
+ file: filePath,
160
+ line,
161
+ column: node.loc.start.column,
162
+ title: "Potential path traversal vulnerability",
163
+ message: "File operation with path containing '..' - validate and sanitize paths",
164
+ codeSnippet: lines[line - 1]?.trim(),
165
+ confidence: "high",
166
+ });
167
+ break;
168
+ }
497
169
  }
498
170
  }
499
171
  }