@sun-asterisk/sunlint 1.3.7 → 1.3.9
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 +63 -0
- package/config/defaults/default.json +2 -1
- package/config/rule-analysis-strategies.js +20 -0
- package/config/rules/enhanced-rules-registry.json +247 -53
- package/core/file-targeting-service.js +98 -7
- package/package.json +1 -1
- package/rules/common/C065_one_behavior_per_test/analyzer.js +851 -0
- package/rules/common/C065_one_behavior_per_test/config.json +95 -0
- package/rules/security/S020_no_eval_dynamic_code/README.md +136 -0
- package/rules/security/S020_no_eval_dynamic_code/analyzer.js +263 -0
- package/rules/security/S020_no_eval_dynamic_code/config.json +54 -0
- package/rules/security/S020_no_eval_dynamic_code/regex-based-analyzer.js +307 -0
- package/rules/security/S020_no_eval_dynamic_code/symbol-based-analyzer.js +280 -0
- package/rules/security/S024_xpath_xxe_protection/symbol-based-analyzer.js +3 -3
- package/rules/security/S025_server_side_validation/symbol-based-analyzer.js +3 -4
- package/rules/security/S030_directory_browsing_protection/README.md +128 -0
- package/rules/security/S030_directory_browsing_protection/analyzer.js +264 -0
- package/rules/security/S030_directory_browsing_protection/config.json +63 -0
- package/rules/security/S030_directory_browsing_protection/regex-based-analyzer.js +483 -0
- package/rules/security/S030_directory_browsing_protection/symbol-based-analyzer.js +539 -0
- package/rules/security/S033_samesite_session_cookies/symbol-based-analyzer.js +8 -9
- package/rules/security/S037_cache_headers/README.md +128 -0
- package/rules/security/S037_cache_headers/analyzer.js +263 -0
- package/rules/security/S037_cache_headers/config.json +50 -0
- package/rules/security/S037_cache_headers/regex-based-analyzer.js +463 -0
- package/rules/security/S037_cache_headers/symbol-based-analyzer.js +546 -0
- package/rules/security/S038_no_version_headers/README.md +234 -0
- package/rules/security/S038_no_version_headers/analyzer.js +262 -0
- package/rules/security/S038_no_version_headers/config.json +49 -0
- package/rules/security/S038_no_version_headers/regex-based-analyzer.js +339 -0
- package/rules/security/S038_no_version_headers/symbol-based-analyzer.js +375 -0
- package/rules/security/S039_no_session_tokens_in_url/README.md +198 -0
- package/rules/security/S039_no_session_tokens_in_url/analyzer.js +262 -0
- package/rules/security/S039_no_session_tokens_in_url/config.json +92 -0
- package/rules/security/S039_no_session_tokens_in_url/regex-based-analyzer.js +337 -0
- package/rules/security/S039_no_session_tokens_in_url/symbol-based-analyzer.js +443 -0
- package/rules/security/S049_short_validity_tokens/analyzer.js +175 -0
- package/rules/security/S049_short_validity_tokens/config.json +124 -0
- package/rules/security/S049_short_validity_tokens/regex-based-analyzer.js +295 -0
- package/rules/security/S049_short_validity_tokens/symbol-based-analyzer.js +389 -0
- package/rules/security/S051_password_length_policy/analyzer.js +410 -0
- package/rules/security/S051_password_length_policy/config.json +83 -0
- package/rules/security/S052_weak_otp_entropy/analyzer.js +403 -0
- package/rules/security/S052_weak_otp_entropy/config.json +57 -0
- package/rules/security/S054_no_default_accounts/README.md +129 -0
- package/rules/security/S054_no_default_accounts/analyzer.js +792 -0
- package/rules/security/S054_no_default_accounts/config.json +101 -0
- package/rules/security/S056_log_injection_protection/analyzer.js +242 -0
- package/rules/security/S056_log_injection_protection/config.json +148 -0
- package/rules/security/S056_log_injection_protection/regex-based-analyzer.js +120 -0
- package/rules/security/S056_log_injection_protection/symbol-based-analyzer.js +246 -0
|
@@ -16,7 +16,7 @@ class FileTargetingService {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Get target files based on enhanced configuration
|
|
19
|
-
* ENHANCED: Uses metadata for intelligent file targeting
|
|
19
|
+
* ENHANCED: Uses metadata for intelligent file targeting with smart project-level optimization
|
|
20
20
|
*/
|
|
21
21
|
async getTargetFiles(inputPaths, config, cliOptions = {}) {
|
|
22
22
|
try {
|
|
@@ -32,11 +32,14 @@ class FileTargetingService {
|
|
|
32
32
|
|
|
33
33
|
let allFiles = [];
|
|
34
34
|
|
|
35
|
+
// Smart project-level optimization
|
|
36
|
+
const optimizedPaths = this.optimizeProjectPaths(inputPaths, cliOptions);
|
|
37
|
+
|
|
35
38
|
// Use enhanced targeting based on metadata
|
|
36
39
|
if (metadata?.shouldBypassProjectDiscovery) {
|
|
37
|
-
allFiles = await this.collectTargetedFiles(
|
|
40
|
+
allFiles = await this.collectTargetedFiles(optimizedPaths, config, cliOptions);
|
|
38
41
|
} else {
|
|
39
|
-
allFiles = await this.collectProjectFiles(
|
|
42
|
+
allFiles = await this.collectProjectFiles(optimizedPaths, config, cliOptions);
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
// Apply filtering logic
|
|
@@ -150,13 +153,84 @@ class FileTargetingService {
|
|
|
150
153
|
return allFiles;
|
|
151
154
|
}
|
|
152
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Optimize project paths to focus on source and test directories
|
|
158
|
+
* Prevents unnecessary scanning of entire project when smart targeting is possible
|
|
159
|
+
*/
|
|
160
|
+
optimizeProjectPaths(inputPaths, cliOptions = {}) {
|
|
161
|
+
const optimizedPaths = [];
|
|
162
|
+
|
|
163
|
+
for (const inputPath of inputPaths) {
|
|
164
|
+
// If targeting entire project directory, try to find source/test subdirectories
|
|
165
|
+
if (fs.existsSync(inputPath) && fs.statSync(inputPath).isDirectory()) {
|
|
166
|
+
const absoluteInputPath = path.resolve(inputPath);
|
|
167
|
+
const inputDirName = path.basename(absoluteInputPath);
|
|
168
|
+
|
|
169
|
+
// If user already specified a source directory (src, lib, app, packages, test, etc.),
|
|
170
|
+
// don't try to optimize further - use it as is
|
|
171
|
+
const sourceDirectoryNames = ['src', 'lib', 'app', 'packages', 'test', 'tests', '__tests__', 'spec', 'specs'];
|
|
172
|
+
if (sourceDirectoryNames.includes(inputDirName)) {
|
|
173
|
+
if (cliOptions.verbose) {
|
|
174
|
+
console.log(chalk.blue(`🎯 Direct targeting: Using specified source directory ${inputDirName}`));
|
|
175
|
+
}
|
|
176
|
+
optimizedPaths.push(inputPath);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Only optimize if this appears to be a project root directory
|
|
181
|
+
const projectOptimization = this.findProjectSourceDirs(inputPath, cliOptions);
|
|
182
|
+
if (projectOptimization.length > 0) {
|
|
183
|
+
if (cliOptions.verbose) {
|
|
184
|
+
console.log(chalk.blue(`🎯 Smart targeting: Found ${projectOptimization.length} source directories in ${path.basename(inputPath)}`));
|
|
185
|
+
}
|
|
186
|
+
optimizedPaths.push(...projectOptimization);
|
|
187
|
+
} else {
|
|
188
|
+
optimizedPaths.push(inputPath);
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
optimizedPaths.push(inputPath);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return optimizedPaths;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Find source directories in project to avoid scanning entire project
|
|
200
|
+
*/
|
|
201
|
+
findProjectSourceDirs(projectPath, cliOptions = {}) {
|
|
202
|
+
const sourceDirs = [];
|
|
203
|
+
const candidateDirs = ['src', 'lib', 'app', 'packages'];
|
|
204
|
+
const testDirs = ['test', 'tests', '__tests__', 'spec', 'specs'];
|
|
205
|
+
|
|
206
|
+
// Always include test directories if --include-tests flag is used
|
|
207
|
+
const dirsToCheck = cliOptions.includeTests ? [...candidateDirs, ...testDirs] : candidateDirs;
|
|
208
|
+
|
|
209
|
+
for (const dir of dirsToCheck) {
|
|
210
|
+
const dirPath = path.join(projectPath, dir);
|
|
211
|
+
if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
|
|
212
|
+
sourceDirs.push(dirPath);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return sourceDirs;
|
|
217
|
+
}
|
|
218
|
+
|
|
153
219
|
/**
|
|
154
220
|
* Check if directory should be skipped
|
|
221
|
+
* Enhanced with more comprehensive ignore patterns
|
|
222
|
+
* Enhanced with more comprehensive ignore patterns
|
|
155
223
|
*/
|
|
156
224
|
shouldSkipDirectory(dirName) {
|
|
157
225
|
const skipDirs = [
|
|
158
226
|
'node_modules', '.git', 'dist', 'build', 'coverage',
|
|
159
|
-
'.next', '.nuxt', 'vendor', 'target', 'generated'
|
|
227
|
+
'.next', '.nuxt', 'vendor', 'target', 'generated',
|
|
228
|
+
'.vscode', '.id',
|
|
229
|
+
'.vscode', '.idea', '.husky', '.github', '.yarn',
|
|
230
|
+
'out', 'public', 'static', 'assets', 'tmp', 'temp',
|
|
231
|
+
'cache', '.cache', 'logs', 'logea', '.husky', '.github', '.yarn',
|
|
232
|
+
'out', 'public', 'static', 'assets', 'tmp', 'temp',
|
|
233
|
+
'cache', '.cache', 'logs', 'log'
|
|
160
234
|
];
|
|
161
235
|
return skipDirs.includes(dirName);
|
|
162
236
|
}
|
|
@@ -278,10 +352,27 @@ class FileTargetingService {
|
|
|
278
352
|
if (debug) console.log(`🔍 [DEBUG] After include patterns ${langConfig.include}: ${langFiles.length} files`);
|
|
279
353
|
}
|
|
280
354
|
|
|
281
|
-
// Apply language-specific exclude patterns
|
|
355
|
+
// Apply language-specific exclude patterns (but respect --include-tests for test files)
|
|
282
356
|
if (langConfig.exclude && langConfig.exclude.length > 0) {
|
|
283
|
-
|
|
284
|
-
|
|
357
|
+
// Skip test-related exclude patterns if --include-tests is enabled
|
|
358
|
+
let effectiveExcludes = langConfig.exclude;
|
|
359
|
+
if (cliOptions.includeTests === true) {
|
|
360
|
+
// Remove test-related patterns completely
|
|
361
|
+
effectiveExcludes = langConfig.exclude.filter(pattern => {
|
|
362
|
+
const isTestPattern = pattern.includes('.test.') || pattern.includes('.spec.') ||
|
|
363
|
+
pattern.includes('/test/') || pattern.includes('/tests/') ||
|
|
364
|
+
pattern.includes('/__tests__/');
|
|
365
|
+
return !isTestPattern;
|
|
366
|
+
});
|
|
367
|
+
if (debug) console.log(`🔍 [DEBUG] --include-tests enabled, filtered excludes: ${effectiveExcludes}`);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (effectiveExcludes.length > 0) {
|
|
371
|
+
langFiles = this.applyExcludePatterns(langFiles, effectiveExcludes, debug);
|
|
372
|
+
if (debug) console.log(`🔍 [DEBUG] After exclude patterns ${effectiveExcludes}: ${langFiles.length} files`);
|
|
373
|
+
} else {
|
|
374
|
+
if (debug) console.log(`🔍 [DEBUG] All exclude patterns filtered out by --include-tests`);
|
|
375
|
+
}
|
|
285
376
|
}
|
|
286
377
|
|
|
287
378
|
languageFiles.push(...langFiles);
|
package/package.json
CHANGED