@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.
- package/bin/registry.js +214 -237
- package/bin/runners/cli-utils.js +33 -2
- package/bin/runners/context/analyzer.js +52 -1
- package/bin/runners/context/generators/cursor.js +2 -49
- package/bin/runners/context/git-context.js +3 -1
- package/bin/runners/context/team-conventions.js +33 -7
- package/bin/runners/lib/analysis-core.js +25 -5
- package/bin/runners/lib/analyzers.js +431 -481
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/doctor/modules/security.js +3 -1
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +18 -218
- package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
- package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
- package/bin/runners/lib/engines/mock-data-engine.js +10 -53
- package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
- package/bin/runners/lib/engines/type-aware-engine.js +39 -263
- package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/entitlements-v2.js +73 -97
- package/bin/runners/lib/error-handler.js +44 -3
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +7 -1
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/html-proof-report.js +700 -350
- package/bin/runners/lib/missions/plan.js +6 -46
- package/bin/runners/lib/missions/templates.js +0 -232
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/route-detection.js +137 -68
- package/bin/runners/lib/scan-output.js +91 -76
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/validator.js +27 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/ship-output-enterprise.js +23 -23
- package/bin/runners/lib/ship-output.js +75 -31
- package/bin/runners/lib/terminal-ui.js +6 -113
- package/bin/runners/lib/truth.js +351 -10
- package/bin/runners/lib/unified-cli-output.js +430 -603
- package/bin/runners/lib/unified-output.js +13 -9
- package/bin/runners/runAIAgent.js +10 -5
- package/bin/runners/runAgent.js +0 -3
- package/bin/runners/runAllowlist.js +389 -0
- package/bin/runners/runApprove.js +0 -33
- package/bin/runners/runAuth.js +73 -45
- package/bin/runners/runCheckpoint.js +51 -11
- package/bin/runners/runClassify.js +85 -21
- package/bin/runners/runContext.js +0 -3
- package/bin/runners/runDoctor.js +41 -28
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.js +0 -3
- package/bin/runners/runFirewallHook.js +0 -3
- package/bin/runners/runFix.js +66 -76
- package/bin/runners/runGuard.js +18 -411
- package/bin/runners/runInit.js +113 -30
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runMcp.js +19 -25
- package/bin/runners/runPolish.js +64 -240
- package/bin/runners/runPromptFirewall.js +12 -5
- package/bin/runners/runProve.js +57 -22
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +59 -68
- package/bin/runners/runReport.js +38 -33
- package/bin/runners/runRuntime.js +8 -5
- package/bin/runners/runScan.js +1413 -190
- package/bin/runners/runShip.js +113 -719
- package/bin/runners/runTruth.js +0 -3
- package/bin/runners/runValidate.js +13 -9
- package/bin/runners/runWatch.js +23 -14
- package/bin/scan.js +6 -1
- package/bin/vibecheck.js +204 -185
- package/mcp-server/deprecation-middleware.js +282 -0
- package/mcp-server/handlers/index.ts +15 -0
- package/mcp-server/handlers/tool-handler.ts +554 -0
- package/mcp-server/index-v1.js +698 -0
- package/mcp-server/index.js +210 -238
- package/mcp-server/lib/cache-wrapper.cjs +383 -0
- package/mcp-server/lib/error-envelope.js +138 -0
- package/mcp-server/lib/executor.ts +499 -0
- package/mcp-server/lib/index.ts +19 -0
- package/mcp-server/lib/rate-limiter.js +166 -0
- package/mcp-server/lib/sandbox.test.ts +519 -0
- package/mcp-server/lib/sandbox.ts +395 -0
- package/mcp-server/lib/types.ts +267 -0
- package/mcp-server/package.json +12 -3
- package/mcp-server/registry/tool-registry.js +794 -0
- package/mcp-server/registry/tools.json +605 -0
- package/mcp-server/registry.test.ts +334 -0
- package/mcp-server/tests/tier-gating.test.js +297 -0
- package/mcp-server/tier-auth.js +378 -45
- package/mcp-server/tools-v3.js +353 -442
- package/mcp-server/tsconfig.json +37 -0
- package/mcp-server/vibecheck-2.0-tools.js +14 -1
- package/package.json +1 -1
- package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
- package/bin/runners/lib/audit-logger.js +0 -532
- package/bin/runners/lib/authority/authorities/architecture.js +0 -364
- package/bin/runners/lib/authority/authorities/compliance.js +0 -341
- package/bin/runners/lib/authority/authorities/human.js +0 -343
- package/bin/runners/lib/authority/authorities/quality.js +0 -420
- package/bin/runners/lib/authority/authorities/security.js +0 -228
- package/bin/runners/lib/authority/index.js +0 -293
- package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
- package/bin/runners/lib/cli-charts.js +0 -368
- package/bin/runners/lib/cli-config-display.js +0 -405
- package/bin/runners/lib/cli-demo.js +0 -275
- package/bin/runners/lib/cli-errors.js +0 -438
- package/bin/runners/lib/cli-help-formatter.js +0 -439
- package/bin/runners/lib/cli-interactive-menu.js +0 -509
- package/bin/runners/lib/cli-prompts.js +0 -441
- package/bin/runners/lib/cli-scan-cards.js +0 -362
- package/bin/runners/lib/compliance-reporter.js +0 -710
- package/bin/runners/lib/conductor/index.js +0 -671
- package/bin/runners/lib/easy/README.md +0 -123
- package/bin/runners/lib/easy/index.js +0 -140
- package/bin/runners/lib/easy/interactive-wizard.js +0 -788
- package/bin/runners/lib/easy/one-click-firewall.js +0 -564
- package/bin/runners/lib/easy/zero-config-reality.js +0 -714
- package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
- package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
- package/bin/runners/lib/engines/confidence-scoring.js +0 -276
- package/bin/runners/lib/engines/context-detection.js +0 -264
- package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
- package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
- package/bin/runners/lib/engines/env-variables-engine.js +0 -458
- package/bin/runners/lib/engines/error-handling-engine.js +0 -437
- package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
- package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
- package/bin/runners/lib/engines/framework-detection.js +0 -508
- package/bin/runners/lib/engines/import-order-engine.js +0 -429
- package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
- package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
- package/bin/runners/lib/engines/orchestrator.js +0 -334
- package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
- package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
- package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
- package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
- package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
- package/bin/runners/lib/enhanced-features/index.js +0 -305
- package/bin/runners/lib/enhanced-output.js +0 -631
- package/bin/runners/lib/enterprise.js +0 -300
- package/bin/runners/lib/firewall/command-validator.js +0 -351
- package/bin/runners/lib/firewall/config.js +0 -341
- package/bin/runners/lib/firewall/content-validator.js +0 -519
- package/bin/runners/lib/firewall/index.js +0 -101
- package/bin/runners/lib/firewall/path-validator.js +0 -256
- package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
- package/bin/runners/lib/mcp-utils.js +0 -425
- package/bin/runners/lib/output/index.js +0 -1022
- package/bin/runners/lib/policy-engine.js +0 -652
- package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
- package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
- package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
- package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
- package/bin/runners/lib/polish/autofix/index.js +0 -200
- package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
- package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
- package/bin/runners/lib/polish/backend-checks.js +0 -148
- package/bin/runners/lib/polish/documentation-checks.js +0 -111
- package/bin/runners/lib/polish/frontend-checks.js +0 -168
- package/bin/runners/lib/polish/index.js +0 -71
- package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
- package/bin/runners/lib/polish/library-detection.js +0 -175
- package/bin/runners/lib/polish/performance-checks.js +0 -100
- package/bin/runners/lib/polish/security-checks.js +0 -148
- package/bin/runners/lib/polish/utils.js +0 -203
- package/bin/runners/lib/prompt-builder.js +0 -540
- package/bin/runners/lib/proof-certificate.js +0 -634
- package/bin/runners/lib/reality/accessibility-audit.js +0 -946
- package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
- package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
- package/bin/runners/lib/reality/performance-tracker.js +0 -1077
- package/bin/runners/lib/reality/scenario-generator.js +0 -1404
- package/bin/runners/lib/reality/visual-regression.js +0 -852
- package/bin/runners/lib/reality-profiler.js +0 -717
- package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
- package/bin/runners/lib/review/ai-code-review.js +0 -832
- package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
- package/bin/runners/lib/sbom-generator.js +0 -641
- package/bin/runners/lib/scan-output-enhanced.js +0 -512
- package/bin/runners/lib/security/owasp-scanner.js +0 -939
- package/bin/runners/lib/validators/contract-validator.js +0 -283
- package/bin/runners/lib/validators/dead-export-detector.js +0 -279
- package/bin/runners/lib/validators/dep-audit.js +0 -245
- package/bin/runners/lib/validators/env-validator.js +0 -319
- package/bin/runners/lib/validators/index.js +0 -120
- package/bin/runners/lib/validators/license-checker.js +0 -252
- package/bin/runners/lib/validators/route-validator.js +0 -290
- package/bin/runners/runAuthority.js +0 -528
- package/bin/runners/runConductor.js +0 -772
- package/bin/runners/runContainer.js +0 -366
- package/bin/runners/runEasy.js +0 -410
- package/bin/runners/runIaC.js +0 -372
- package/bin/runners/runVibe.js +0 -791
- 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
|
|
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"
|
|
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
|
|
49
|
+
line,
|
|
206
50
|
column: node.loc.start.column,
|
|
207
51
|
title: "Potential SQL injection vulnerability",
|
|
208
|
-
message: "SQL query constructed with
|
|
209
|
-
codeSnippet:
|
|
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
|
|
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
|
-
|
|
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
|
|
86
|
+
line,
|
|
260
87
|
column: node.loc.start.column,
|
|
261
88
|
title: "Potential XSS vulnerability",
|
|
262
|
-
message: `Using ${prop.name} with potentially unsafe content
|
|
263
|
-
codeSnippet:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
394
|
-
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
|
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
|
-
|
|
142
|
+
if (t.isMemberExpression(node.callee) &&
|
|
143
|
+
t.isIdentifier(node.callee.object, { name: "fs" })) {
|
|
441
144
|
const prop = node.callee.property;
|
|
442
145
|
|
|
443
|
-
|
|
444
|
-
|
|
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
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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
|
}
|