@sun-asterisk/sunlint 1.3.1 → 1.3.3
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/CHANGELOG.md +85 -0
- package/CONTRIBUTING.md +210 -1691
- package/README.md +5 -3
- package/config/rule-analysis-strategies.js +17 -1
- package/config/rules/enhanced-rules-registry.json +506 -1161
- package/config/rules/rules-registry-generated.json +1 -1
- package/core/analysis-orchestrator.js +167 -42
- package/core/auto-performance-manager.js +243 -0
- package/core/cli-action-handler.js +9 -1
- package/core/cli-program.js +19 -5
- package/core/constants/defaults.js +56 -0
- package/core/enhanced-rules-registry.js +2 -1
- package/core/performance-optimizer.js +271 -0
- package/core/semantic-engine.js +15 -3
- package/core/semantic-rule-base.js +4 -2
- package/docs/FILE_LIMITS_COMPLETION_REPORT.md +151 -0
- package/docs/FILE_LIMITS_EXPLANATION.md +190 -0
- package/docs/PERFORMANCE.md +311 -0
- package/docs/PERFORMANCE_MIGRATION_GUIDE.md +368 -0
- package/docs/PERFORMANCE_OPTIMIZATION_PLAN.md +255 -0
- package/docs/QUICK_FILE_LIMITS.md +64 -0
- package/docs/SIMPLIFIED_USAGE_GUIDE.md +208 -0
- package/engines/heuristic-engine.js +247 -9
- package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +59 -1
- package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +26 -1
- package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +54 -19
- package/origin-rules/common-en.md +11 -7
- package/package.json +2 -1
- package/rules/common/C002_no_duplicate_code/analyzer.js +334 -36
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +220 -35
- package/rules/common/C006_function_naming/analyzer.js +29 -3
- package/rules/common/C010_limit_block_nesting/analyzer.js +181 -337
- package/rules/common/C010_limit_block_nesting/config.json +64 -0
- package/rules/common/C010_limit_block_nesting/regex-based-analyzer.js +379 -0
- package/rules/common/C010_limit_block_nesting/symbol-based-analyzer.js +231 -0
- package/rules/common/C013_no_dead_code/analyzer.js +75 -177
- package/rules/common/C013_no_dead_code/config.json +61 -0
- package/rules/common/C013_no_dead_code/regex-based-analyzer.js +345 -0
- package/rules/common/C013_no_dead_code/symbol-based-analyzer.js +640 -0
- package/rules/common/C014_dependency_injection/analyzer.js +48 -313
- package/rules/common/C014_dependency_injection/config.json +26 -0
- package/rules/common/C014_dependency_injection/symbol-based-analyzer.js +751 -0
- package/rules/common/C018_no_throw_generic_error/analyzer.js +232 -0
- package/rules/common/C018_no_throw_generic_error/config.json +50 -0
- package/rules/common/C018_no_throw_generic_error/regex-based-analyzer.js +387 -0
- package/rules/common/C018_no_throw_generic_error/symbol-based-analyzer.js +314 -0
- package/rules/common/C019_log_level_usage/analyzer.js +110 -317
- package/rules/common/C019_log_level_usage/pattern-analyzer.js +88 -0
- package/rules/common/C019_log_level_usage/system-log-analyzer.js +1267 -0
- package/rules/common/C023_no_duplicate_variable/analyzer.js +180 -0
- package/rules/common/C023_no_duplicate_variable/config.json +50 -0
- package/rules/common/C023_no_duplicate_variable/symbol-based-analyzer.js +158 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/analyzer.js +180 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/config.json +50 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/symbol-based-analyzer.js +181 -0
- package/rules/common/C030_use_custom_error_classes/analyzer.js +200 -0
- package/rules/common/C035_error_logging_context/analyzer.js +3 -1
- package/rules/common/C048_no_bypass_architectural_layers/analyzer.js +180 -0
- package/rules/common/C048_no_bypass_architectural_layers/config.json +50 -0
- package/rules/common/C048_no_bypass_architectural_layers/symbol-based-analyzer.js +235 -0
- package/rules/common/C052_parsing_or_data_transformation/analyzer.js +180 -0
- package/rules/common/C052_parsing_or_data_transformation/config.json +50 -0
- package/rules/common/C052_parsing_or_data_transformation/symbol-based-analyzer.js +132 -0
- package/rules/index.js +7 -1
- package/rules/security/S009_no_insecure_encryption/README.md +158 -0
- package/rules/security/S009_no_insecure_encryption/analyzer.js +319 -0
- package/rules/security/S009_no_insecure_encryption/config.json +55 -0
- package/rules/security/S010_no_insecure_encryption/README.md +224 -0
- package/rules/security/S010_no_insecure_encryption/analyzer.js +493 -0
- package/rules/security/S010_no_insecure_encryption/config.json +48 -0
- package/rules/security/S016_no_sensitive_querystring/STRATEGY.md +149 -0
- package/rules/security/S016_no_sensitive_querystring/analyzer.js +276 -0
- package/rules/security/S016_no_sensitive_querystring/config.json +127 -0
- package/rules/security/S016_no_sensitive_querystring/regex-based-analyzer.js +258 -0
- package/rules/security/S016_no_sensitive_querystring/symbol-based-analyzer.js +495 -0
- package/rules/security/S017_use_parameterized_queries/README.md +128 -0
- package/rules/security/S017_use_parameterized_queries/analyzer.js +286 -0
- package/rules/security/S017_use_parameterized_queries/config.json +109 -0
- package/rules/security/S017_use_parameterized_queries/regex-based-analyzer.js +541 -0
- package/rules/security/S017_use_parameterized_queries/symbol-based-analyzer.js +777 -0
- package/rules/security/S031_secure_session_cookies/README.md +127 -0
- package/rules/security/S031_secure_session_cookies/analyzer.js +245 -0
- package/rules/security/S031_secure_session_cookies/config.json +86 -0
- package/rules/security/S031_secure_session_cookies/regex-based-analyzer.js +196 -0
- package/rules/security/S031_secure_session_cookies/symbol-based-analyzer.js +1084 -0
- package/rules/security/S032_httponly_session_cookies/FRAMEWORK_SUPPORT.md +209 -0
- package/rules/security/S032_httponly_session_cookies/README.md +184 -0
- package/rules/security/S032_httponly_session_cookies/analyzer.js +282 -0
- package/rules/security/S032_httponly_session_cookies/config.json +96 -0
- package/rules/security/S032_httponly_session_cookies/regex-based-analyzer.js +715 -0
- package/rules/security/S032_httponly_session_cookies/symbol-based-analyzer.js +1348 -0
- package/rules/security/S033_samesite_session_cookies/README.md +227 -0
- package/rules/security/S033_samesite_session_cookies/analyzer.js +242 -0
- package/rules/security/S033_samesite_session_cookies/config.json +87 -0
- package/rules/security/S033_samesite_session_cookies/regex-based-analyzer.js +703 -0
- package/rules/security/S033_samesite_session_cookies/symbol-based-analyzer.js +732 -0
- package/rules/security/S034_host_prefix_session_cookies/README.md +204 -0
- package/rules/security/S034_host_prefix_session_cookies/analyzer.js +290 -0
- package/rules/security/S034_host_prefix_session_cookies/config.json +62 -0
- package/rules/security/S034_host_prefix_session_cookies/regex-based-analyzer.js +478 -0
- package/rules/security/S034_host_prefix_session_cookies/symbol-based-analyzer.js +277 -0
- package/rules/security/S035_path_session_cookies/README.md +257 -0
- package/rules/security/S035_path_session_cookies/analyzer.js +316 -0
- package/rules/security/S035_path_session_cookies/config.json +99 -0
- package/rules/security/S035_path_session_cookies/regex-based-analyzer.js +724 -0
- package/rules/security/S035_path_session_cookies/symbol-based-analyzer.js +373 -0
- package/rules/security/S048_no_current_password_in_reset/README.md +222 -0
- package/rules/security/S048_no_current_password_in_reset/analyzer.js +366 -0
- package/rules/security/S048_no_current_password_in_reset/config.json +48 -0
- package/rules/security/S055_content_type_validation/README.md +176 -0
- package/rules/security/S055_content_type_validation/analyzer.js +312 -0
- package/rules/security/S055_content_type_validation/config.json +48 -0
- package/rules/utils/rule-helpers.js +140 -1
- package/scripts/batch-processing-demo.js +334 -0
- package/scripts/consolidate-config.js +116 -0
- package/scripts/performance-test.js +541 -0
- package/scripts/quick-performance-test.js +108 -0
- package/config/rules/S027-categories.json +0 -122
- package/config/rules/rules-registry.json +0 -777
- package/rules/common/C006_function_naming/smart-analyzer.js +0 -503
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S017 Main Analyzer - Always use parameterized queries
|
|
3
|
+
* Primary: Symbol-based analysis (when available)
|
|
4
|
+
* Fallback: Regex-based for all other cases
|
|
5
|
+
* Command: node cli.js --rule=S017 --input=examples/rule-test-fixtures/rules/S017_use_parameterized_queries --engine=heuristic
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const S017SymbolBasedAnalyzer = require("./symbol-based-analyzer.js");
|
|
9
|
+
const S017RegexBasedAnalyzer = require("./regex-based-analyzer.js");
|
|
10
|
+
|
|
11
|
+
class S017Analyzer {
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
14
|
+
console.log(`🔧 [S017] Constructor called with options:`, !!options);
|
|
15
|
+
console.log(
|
|
16
|
+
`🔧 [S017] Options type:`,
|
|
17
|
+
typeof options,
|
|
18
|
+
Object.keys(options || {})
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.ruleId = "S017";
|
|
23
|
+
this.ruleName = "Always use parameterized queries";
|
|
24
|
+
this.description =
|
|
25
|
+
"Always use parameterized queries instead of string concatenation to build SQL queries. This prevents SQL injection attacks by separating SQL logic from data";
|
|
26
|
+
this.semanticEngine = options.semanticEngine || null;
|
|
27
|
+
this.verbose = options.verbose || false;
|
|
28
|
+
|
|
29
|
+
// Configuration
|
|
30
|
+
this.config = {
|
|
31
|
+
useSymbolBased: true, // Primary approach
|
|
32
|
+
fallbackToRegex: true, // Secondary approach
|
|
33
|
+
regexBasedOnly: false, // Can be set to true for pure mode
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Initialize analyzers
|
|
37
|
+
try {
|
|
38
|
+
this.symbolAnalyzer = new S017SymbolBasedAnalyzer(this.semanticEngine);
|
|
39
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
40
|
+
console.log(`🔧 [S017] Symbol analyzer created successfully`);
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(`🔧 [S017] Error creating symbol analyzer:`, error);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
this.regexAnalyzer = new S017RegexBasedAnalyzer(this.semanticEngine);
|
|
48
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
49
|
+
console.log(`🔧 [S017] Regex analyzer created successfully`);
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(`🔧 [S017] Error creating regex analyzer:`, error);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
56
|
+
console.log(`🔧 [S017] Constructor completed`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Initialize with semantic engine
|
|
62
|
+
*/
|
|
63
|
+
async initialize(semanticEngine = null) {
|
|
64
|
+
if (semanticEngine) {
|
|
65
|
+
this.semanticEngine = semanticEngine;
|
|
66
|
+
}
|
|
67
|
+
this.verbose = semanticEngine?.verbose || false;
|
|
68
|
+
|
|
69
|
+
// Initialize both analyzers
|
|
70
|
+
if (this.symbolAnalyzer) {
|
|
71
|
+
await this.symbolAnalyzer.initialize?.(semanticEngine);
|
|
72
|
+
}
|
|
73
|
+
if (this.regexAnalyzer) {
|
|
74
|
+
await this.regexAnalyzer.initialize?.(semanticEngine);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Ensure verbose flag is propagated
|
|
78
|
+
if (this.regexAnalyzer) {
|
|
79
|
+
this.regexAnalyzer.verbose = this.verbose;
|
|
80
|
+
}
|
|
81
|
+
if (this.symbolAnalyzer) {
|
|
82
|
+
this.symbolAnalyzer.verbose = this.verbose;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (this.verbose) {
|
|
86
|
+
console.log(
|
|
87
|
+
`🔧 [S017 Hybrid] Analyzer initialized - verbose: ${this.verbose}`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Single file analysis method for testing
|
|
94
|
+
*/
|
|
95
|
+
analyzeSingle(filePath, options = {}) {
|
|
96
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
97
|
+
console.log(`🔍 [S017] analyzeSingle() called for: ${filePath}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Return result using same format as analyze method
|
|
101
|
+
return this.analyze([filePath], "typescript", options);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async analyze(files, language, options = {}) {
|
|
105
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
106
|
+
console.log(
|
|
107
|
+
`🔧 [S017] analyze() method called with ${files.length} files, language: ${language}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const violations = [];
|
|
112
|
+
|
|
113
|
+
for (const filePath of files) {
|
|
114
|
+
try {
|
|
115
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
116
|
+
console.log(`🔧 [S017] Processing file: ${filePath}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const fileViolations = await this.analyzeFile(filePath, options);
|
|
120
|
+
violations.push(...fileViolations);
|
|
121
|
+
|
|
122
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
123
|
+
console.log(
|
|
124
|
+
`🔧 [S017] File ${filePath}: Found ${fileViolations.length} violations`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.warn(
|
|
129
|
+
`⚠ [S017] Analysis failed for ${filePath}:`,
|
|
130
|
+
error.message
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
136
|
+
console.log(`🔧 [S017] Total violations found: ${violations.length}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return violations;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async analyzeFile(filePath, options = {}) {
|
|
143
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
144
|
+
console.log(`🔍 [S017] analyzeFile() called for: ${filePath}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Create a Set to track unique violations and prevent duplicates
|
|
148
|
+
const violationMap = new Map();
|
|
149
|
+
|
|
150
|
+
// 1. Try Symbol-based analysis first (primary)
|
|
151
|
+
if (
|
|
152
|
+
this.config.useSymbolBased &&
|
|
153
|
+
this.semanticEngine?.project &&
|
|
154
|
+
this.semanticEngine?.initialized
|
|
155
|
+
) {
|
|
156
|
+
try {
|
|
157
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
158
|
+
console.log(`🔧 [S017] Trying symbol-based analysis...`);
|
|
159
|
+
}
|
|
160
|
+
const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
|
|
161
|
+
if (sourceFile) {
|
|
162
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
163
|
+
console.log(
|
|
164
|
+
`🔧 [S017] Source file found, analyzing with symbol-based...`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Read file content for symbol analyzer
|
|
169
|
+
const fs = require("fs");
|
|
170
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
|
171
|
+
|
|
172
|
+
const violations = await this.symbolAnalyzer.analyzeFile(
|
|
173
|
+
filePath,
|
|
174
|
+
fileContent,
|
|
175
|
+
{ ...options, verbose: options.verbose }
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Add violations to map to deduplicate
|
|
179
|
+
violations.forEach((v) => {
|
|
180
|
+
const key = `${v.line}:${v.column}:${v.message}`;
|
|
181
|
+
if (!violationMap.has(key)) {
|
|
182
|
+
v.analysisStrategy = "symbol-based";
|
|
183
|
+
violationMap.set(key, v);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
188
|
+
console.log(
|
|
189
|
+
`✅ [S017] Symbol-based analysis: ${violations.length} violations`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
return Array.from(violationMap.values()); // Return deduplicated violations
|
|
193
|
+
} else {
|
|
194
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
195
|
+
console.log(`⚠️ [S017] Source file not found in project`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.warn(`⚠️ [S017] Symbol analysis failed: ${error.message}`);
|
|
200
|
+
// Continue to fallback
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
204
|
+
console.log(`🔄 [S017] Symbol analysis conditions check:`);
|
|
205
|
+
console.log(` - useSymbolBased: ${this.config.useSymbolBased}`);
|
|
206
|
+
console.log(` - semanticEngine: ${!!this.semanticEngine}`);
|
|
207
|
+
console.log(
|
|
208
|
+
` - semanticEngine.project: ${!!this.semanticEngine?.project}`
|
|
209
|
+
);
|
|
210
|
+
console.log(
|
|
211
|
+
` - semanticEngine.initialized: ${this.semanticEngine?.initialized}`
|
|
212
|
+
);
|
|
213
|
+
console.log(
|
|
214
|
+
`🔄 [S017] Symbol analysis unavailable, using regex fallback`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 2. Fallback to regex-based analysis (only if symbol-based failed or unavailable)
|
|
220
|
+
if (this.config.fallbackToRegex) {
|
|
221
|
+
try {
|
|
222
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
223
|
+
console.log(`🔧 [S017] Trying regex-based analysis...`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Read file content for regex analyzer
|
|
227
|
+
const fs = require("fs");
|
|
228
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
|
229
|
+
|
|
230
|
+
const violations = await this.regexAnalyzer.analyzeFile(
|
|
231
|
+
filePath,
|
|
232
|
+
fileContent,
|
|
233
|
+
options
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// Add violations to map to deduplicate
|
|
237
|
+
violations.forEach((v) => {
|
|
238
|
+
const key = `${v.line}:${v.column}:${v.message}`;
|
|
239
|
+
if (!violationMap.has(key)) {
|
|
240
|
+
v.analysisStrategy = "regex-fallback";
|
|
241
|
+
violationMap.set(key, v);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
246
|
+
console.log(
|
|
247
|
+
`🔄 [S017] Regex-based analysis: ${violations.length} violations`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
return Array.from(violationMap.values()); // Return deduplicated violations
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.error(`⚠ [S017] Regex analysis failed: ${error.message}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
console.log(`🔧 [S017] No analysis methods succeeded, returning empty`);
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Methods for compatibility with different engine invocation patterns
|
|
262
|
+
*/
|
|
263
|
+
async analyzeFileWithSymbols(filePath, options = {}) {
|
|
264
|
+
return this.analyzeFile(filePath, options);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async analyzeWithSemantics(filePath, options = {}) {
|
|
268
|
+
return this.analyzeFile(filePath, options);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get analyzer metadata
|
|
273
|
+
*/
|
|
274
|
+
getMetadata() {
|
|
275
|
+
return {
|
|
276
|
+
rule: "S017",
|
|
277
|
+
name: "Always use parameterized queries",
|
|
278
|
+
category: "security",
|
|
279
|
+
type: "hybrid",
|
|
280
|
+
description:
|
|
281
|
+
"Uses symbol-based and regex analysis to detect SQL injection vulnerabilities",
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
module.exports = S017Analyzer;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "S017",
|
|
3
|
+
"name": "Always use parameterized queries",
|
|
4
|
+
"category": "security",
|
|
5
|
+
"description": "S017 - Always use parameterized queries instead of string concatenation to build SQL queries. This prevents SQL injection attacks by separating SQL logic from data",
|
|
6
|
+
"severity": "error",
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"semantic": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"priority": "high",
|
|
11
|
+
"fallback": "heuristic"
|
|
12
|
+
},
|
|
13
|
+
"patterns": {
|
|
14
|
+
"include": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"],
|
|
15
|
+
"exclude": [
|
|
16
|
+
"**/*.test.js",
|
|
17
|
+
"**/*.test.ts",
|
|
18
|
+
"**/*.spec.js",
|
|
19
|
+
"**/*.spec.ts",
|
|
20
|
+
"**/node_modules/**",
|
|
21
|
+
"**/dist/**",
|
|
22
|
+
"**/build/**"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"analysis": {
|
|
26
|
+
"approach": "symbol-based-primary",
|
|
27
|
+
"fallback": "regex-based",
|
|
28
|
+
"depth": 2,
|
|
29
|
+
"timeout": 5000
|
|
30
|
+
},
|
|
31
|
+
"validation": {
|
|
32
|
+
"sqlMethods": [
|
|
33
|
+
"query",
|
|
34
|
+
"execute",
|
|
35
|
+
"exec",
|
|
36
|
+
"run",
|
|
37
|
+
"all",
|
|
38
|
+
"get",
|
|
39
|
+
"prepare",
|
|
40
|
+
"createQuery",
|
|
41
|
+
"executeQuery",
|
|
42
|
+
"executeSql",
|
|
43
|
+
"rawQuery"
|
|
44
|
+
],
|
|
45
|
+
"dangerousPatterns": [
|
|
46
|
+
"SELECT.*\\+",
|
|
47
|
+
"INSERT.*\\+",
|
|
48
|
+
"UPDATE.*\\+",
|
|
49
|
+
"DELETE.*\\+",
|
|
50
|
+
"WHERE.*\\+",
|
|
51
|
+
"ORDER BY.*\\+",
|
|
52
|
+
"GROUP BY.*\\+",
|
|
53
|
+
"HAVING.*\\+",
|
|
54
|
+
"\\$\\{.*\\}",
|
|
55
|
+
"\\`.*\\$\\{.*\\}.*\\`"
|
|
56
|
+
],
|
|
57
|
+
"sqlKeywords": [
|
|
58
|
+
"SELECT",
|
|
59
|
+
"INSERT",
|
|
60
|
+
"UPDATE",
|
|
61
|
+
"DELETE",
|
|
62
|
+
"DROP",
|
|
63
|
+
"CREATE",
|
|
64
|
+
"ALTER",
|
|
65
|
+
"UNION",
|
|
66
|
+
"WHERE",
|
|
67
|
+
"ORDER BY",
|
|
68
|
+
"GROUP BY",
|
|
69
|
+
"HAVING",
|
|
70
|
+
"FROM",
|
|
71
|
+
"JOIN",
|
|
72
|
+
"INNER JOIN",
|
|
73
|
+
"LEFT JOIN",
|
|
74
|
+
"RIGHT JOIN",
|
|
75
|
+
"FULL JOIN"
|
|
76
|
+
],
|
|
77
|
+
"databaseLibraries": [
|
|
78
|
+
"mysql",
|
|
79
|
+
"mysql2",
|
|
80
|
+
"pg",
|
|
81
|
+
"postgres",
|
|
82
|
+
"sqlite3",
|
|
83
|
+
"sqlite",
|
|
84
|
+
"mssql",
|
|
85
|
+
"tedious",
|
|
86
|
+
"oracle",
|
|
87
|
+
"mongodb",
|
|
88
|
+
"mongoose",
|
|
89
|
+
"sequelize",
|
|
90
|
+
"typeorm",
|
|
91
|
+
"prisma",
|
|
92
|
+
"knex",
|
|
93
|
+
"objection"
|
|
94
|
+
],
|
|
95
|
+
"safePatterns": [
|
|
96
|
+
"\\?",
|
|
97
|
+
"\\$1",
|
|
98
|
+
"\\$2",
|
|
99
|
+
"\\$3",
|
|
100
|
+
"\\$4",
|
|
101
|
+
"\\$5",
|
|
102
|
+
"prepare",
|
|
103
|
+
"bind",
|
|
104
|
+
"params",
|
|
105
|
+
"parameters",
|
|
106
|
+
"values"
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
}
|