@sun-asterisk/sunlint 1.3.6 → 1.3.7
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 +38 -1
- package/config/rules/enhanced-rules-registry.json +42 -10
- package/core/analysis-orchestrator.js +9 -5
- package/core/performance-optimizer.js +8 -2
- package/package.json +1 -1
- package/rules/common/C073_validate_required_config_on_startup/README.md +110 -0
- package/rules/common/C073_validate_required_config_on_startup/analyzer.js +770 -0
- package/rules/common/C073_validate_required_config_on_startup/config.json +46 -0
- package/rules/common/C073_validate_required_config_on_startup/symbol-based-analyzer.js +370 -0
- package/rules/security/S057_utc_logging/README.md +152 -0
- package/rules/security/S057_utc_logging/analyzer.js +457 -0
- package/rules/security/S057_utc_logging/config.json +105 -0
- package/rules/security/S058_no_ssrf/README.md +180 -0
- package/rules/security/S058_no_ssrf/analyzer.js +403 -0
- package/rules/security/S058_no_ssrf/config.json +125 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## � **v1.3.7 - File Count Reporting & Performance Fixes (September 11, 2025)**
|
|
6
|
+
|
|
7
|
+
**Release Date**: September 11, 2025
|
|
8
|
+
**Type**: Bug Fix & Enhancement
|
|
9
|
+
**Branch**: `fix.sunlint.report`
|
|
10
|
+
|
|
11
|
+
### 🐛 **Critical Bug Fixes**
|
|
12
|
+
- **FIXED**: File count reporting accuracy in summary
|
|
13
|
+
- **Issue**: Summary showed incorrect file counts when performance filtering applied
|
|
14
|
+
- **Before**: `Files loaded: 1322` but summary `Files: 1000` (misleading)
|
|
15
|
+
- **After**: Summary accurately reflects files actually analyzed
|
|
16
|
+
- **FIXED**: File count multiplication in batch processing
|
|
17
|
+
- **Issue**: Multiple batches incorrectly accumulated file counts
|
|
18
|
+
- **Before**: 1322 files → reported as 3000 files in batched analysis
|
|
19
|
+
- **After**: Consistent file count regardless of batch strategy
|
|
20
|
+
|
|
21
|
+
### ⚡ **Performance Enhancements**
|
|
22
|
+
- **ENHANCED**: `--max-files=-1` unlimited file processing
|
|
23
|
+
- **Issue**: `-1` flag was ignored, still limited to 1000 files
|
|
24
|
+
- **Solution**: Proper unlimited file processing support
|
|
25
|
+
- **Usage**: `sunlint --max-files=-1` now analyzes all files without limits
|
|
26
|
+
|
|
27
|
+
### 🎯 **Rule Improvements**
|
|
28
|
+
- **ENHANCED**: S057 UTC Logging rule precision (100% accuracy)
|
|
29
|
+
- Fixed false positive detection for `pino.stdTimeFunctions.isoTime`
|
|
30
|
+
- Added timezone indicator support: `'Z'`, `"Z"`, `+00:00`, `.l'Z'`
|
|
31
|
+
- Enhanced config variable tracing for complex logging setups
|
|
32
|
+
- Cleaned up test fixtures and moved to proper location
|
|
33
|
+
|
|
34
|
+
### 📊 **Validation Results**
|
|
35
|
+
- **File Processing**: `--max-files=-1` → 1322 files analyzed ✅
|
|
36
|
+
- **Limited Analysis**: `--max-files=500` → 500 files analyzed ✅
|
|
37
|
+
- **Batch Analysis**: Multi-rule analysis maintains accurate counts ✅
|
|
38
|
+
- **S057 Precision**: 0 false positives on real projects ✅
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## �🔧 **v1.3.6 - C067 False Positive Reduction (September 8, 2025)**
|
|
6
43
|
|
|
7
44
|
**Release Date**: September 8, 2025
|
|
8
45
|
**Type**: Bug Fix & Improvement
|
|
@@ -1107,28 +1107,36 @@
|
|
|
1107
1107
|
"tags": ["security", "rest", "content-type"]
|
|
1108
1108
|
},
|
|
1109
1109
|
"S057": {
|
|
1110
|
-
"name": "UTC
|
|
1111
|
-
"description": "
|
|
1110
|
+
"name": "Log with UTC Timestamps",
|
|
1111
|
+
"description": "Ensure all logs use synchronized UTC time with ISO 8601/RFC3339 format to avoid timezone discrepancies across systems",
|
|
1112
1112
|
"category": "security",
|
|
1113
1113
|
"severity": "warning",
|
|
1114
1114
|
"languages": ["typescript", "javascript"],
|
|
1115
|
-
"analyzer": "
|
|
1116
|
-
"
|
|
1115
|
+
"analyzer": "./rules/security/S057_utc_logging/analyzer.js",
|
|
1116
|
+
"config": "./rules/security/S057_utc_logging/config.json",
|
|
1117
1117
|
"version": "1.0.0",
|
|
1118
1118
|
"status": "stable",
|
|
1119
|
-
"tags": ["security", "logging", "timezone"]
|
|
1119
|
+
"tags": ["security", "logging", "timezone", "utc"],
|
|
1120
|
+
"engineMappings": {
|
|
1121
|
+
"eslint": ["custom/typescript_s057"],
|
|
1122
|
+
"heuristic": ["./rules/security/S057_utc_logging/analyzer.js"]
|
|
1123
|
+
}
|
|
1120
1124
|
},
|
|
1121
1125
|
"S058": {
|
|
1122
|
-
"name": "No SSRF",
|
|
1123
|
-
"description": "
|
|
1126
|
+
"name": "No SSRF (Server-Side Request Forgery)",
|
|
1127
|
+
"description": "Prevent SSRF attacks by validating URLs from user input before making HTTP requests",
|
|
1124
1128
|
"category": "security",
|
|
1125
1129
|
"severity": "error",
|
|
1126
1130
|
"languages": ["typescript", "javascript"],
|
|
1127
|
-
"analyzer": "
|
|
1128
|
-
"
|
|
1131
|
+
"analyzer": "./rules/security/S058_no_ssrf/analyzer.js",
|
|
1132
|
+
"config": "./rules/security/S058_no_ssrf/config.json",
|
|
1129
1133
|
"version": "1.0.0",
|
|
1130
1134
|
"status": "stable",
|
|
1131
|
-
"tags": ["security", "ssrf", "url-validation"]
|
|
1135
|
+
"tags": ["security", "ssrf", "url-validation", "http-requests"],
|
|
1136
|
+
"engineMappings": {
|
|
1137
|
+
"heuristic": ["./rules/security/S058_no_ssrf/analyzer.js"],
|
|
1138
|
+
"eslint": ["custom/typescript_s058"]
|
|
1139
|
+
}
|
|
1132
1140
|
},
|
|
1133
1141
|
"C002": {
|
|
1134
1142
|
"id": "C002",
|
|
@@ -1400,6 +1408,29 @@
|
|
|
1400
1408
|
"accuracy": {}
|
|
1401
1409
|
}
|
|
1402
1410
|
},
|
|
1411
|
+
"C073": {
|
|
1412
|
+
"id": "C073",
|
|
1413
|
+
"name": "Validate Required Configuration on Startup",
|
|
1414
|
+
"description": "C073 - Validate mandatory configuration at startup and fail fast on invalid/missing values",
|
|
1415
|
+
"category": "configuration",
|
|
1416
|
+
"severity": "error",
|
|
1417
|
+
"languages": ["typescript", "javascript", "java", "go"],
|
|
1418
|
+
"version": "1.0.0",
|
|
1419
|
+
"status": "stable",
|
|
1420
|
+
"tags": ["configuration", "validation", "startup", "fail-fast"],
|
|
1421
|
+
"engineMappings": {
|
|
1422
|
+
"heuristic": ["rules/common/C073_validate_required_config_on_startup/analyzer.js"],
|
|
1423
|
+
"semantic": ["rules/common/C073_validate_required_config_on_startup/symbol-based-analyzer.js"]
|
|
1424
|
+
},
|
|
1425
|
+
"strategy": {
|
|
1426
|
+
"preferred": "semantic",
|
|
1427
|
+
"fallbacks": ["heuristic"],
|
|
1428
|
+
"accuracy": {
|
|
1429
|
+
"semantic": 0.9,
|
|
1430
|
+
"heuristic": 0.7
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
},
|
|
1403
1434
|
"C075": {
|
|
1404
1435
|
"id": "C075",
|
|
1405
1436
|
"name": "Rule C075",
|
|
@@ -1807,6 +1838,7 @@
|
|
|
1807
1838
|
"C048",
|
|
1808
1839
|
"C052",
|
|
1809
1840
|
"C072",
|
|
1841
|
+
"C073",
|
|
1810
1842
|
"C075",
|
|
1811
1843
|
"T002",
|
|
1812
1844
|
"T003",
|
|
@@ -264,7 +264,7 @@ class AnalysisOrchestrator {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
// Merge results and add performance metrics
|
|
267
|
-
const mergedResults = this.mergeEngineResults(results, options);
|
|
267
|
+
const mergedResults = this.mergeEngineResults(results, options, optimizedFiles.length);
|
|
268
268
|
mergedResults.performance = performanceMetrics;
|
|
269
269
|
|
|
270
270
|
return mergedResults;
|
|
@@ -523,7 +523,7 @@ class AnalysisOrchestrator {
|
|
|
523
523
|
* @param {Object} options - Analysis options
|
|
524
524
|
* @returns {Object} Merged results
|
|
525
525
|
*/
|
|
526
|
-
mergeEngineResults(engineResults, options) {
|
|
526
|
+
mergeEngineResults(engineResults, options, actualFilesCount = 0) {
|
|
527
527
|
const mergedResults = {
|
|
528
528
|
results: [],
|
|
529
529
|
summary: {
|
|
@@ -568,15 +568,19 @@ class AnalysisOrchestrator {
|
|
|
568
568
|
// Accumulate engine statistics across batches
|
|
569
569
|
mergedResults.summary.engines[engineName].rules.push(...(engineResult.rules || []));
|
|
570
570
|
mergedResults.summary.engines[engineName].violations += violationCount;
|
|
571
|
-
|
|
571
|
+
// Don't accumulate filesAnalyzed for each batch - use actual unique file count
|
|
572
|
+
if (!mergedResults.summary.engines[engineName].filesSet) {
|
|
573
|
+
mergedResults.summary.engines[engineName].files = actualFilesCount;
|
|
574
|
+
mergedResults.summary.engines[engineName].filesSet = true;
|
|
575
|
+
}
|
|
572
576
|
mergedResults.summary.engines[engineName].batches += 1;
|
|
573
577
|
|
|
574
578
|
mergedResults.summary.totalViolations += violationCount;
|
|
575
|
-
mergedResults.summary.totalFiles += engineResult.filesAnalyzed || 0;
|
|
576
579
|
}
|
|
577
580
|
|
|
578
|
-
// Update unique engine count
|
|
581
|
+
// Update unique engine count and correct total files count
|
|
579
582
|
mergedResults.summary.totalEngines = uniqueEngines.size;
|
|
583
|
+
mergedResults.summary.totalFiles = actualFilesCount;
|
|
580
584
|
|
|
581
585
|
return mergedResults;
|
|
582
586
|
}
|
|
@@ -26,6 +26,12 @@ class PerformanceOptimizer {
|
|
|
26
26
|
...DEFAULT_PERFORMANCE,
|
|
27
27
|
...config
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
// Override maxTotalFiles if provided in config
|
|
31
|
+
if (config.maxFiles !== undefined) {
|
|
32
|
+
this.fileSizeLimits.maxTotalFiles = config.maxFiles;
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
this.initialized = true;
|
|
30
36
|
}
|
|
31
37
|
|
|
@@ -106,8 +112,8 @@ class PerformanceOptimizer {
|
|
|
106
112
|
break;
|
|
107
113
|
}
|
|
108
114
|
|
|
109
|
-
// Check file count limit
|
|
110
|
-
if (filtered.length >= this.fileSizeLimits.maxTotalFiles) {
|
|
115
|
+
// Check file count limit (skip if unlimited -1)
|
|
116
|
+
if (this.fileSizeLimits.maxTotalFiles > 0 && filtered.length >= this.fileSizeLimits.maxTotalFiles) {
|
|
111
117
|
if (this.config.verbose) {
|
|
112
118
|
console.log(`⚠️ Reached file count limit: ${this.fileSizeLimits.maxTotalFiles} files`);
|
|
113
119
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# C073 - Validate Required Configuration on Startup
|
|
2
|
+
|
|
3
|
+
## Mục tiêu
|
|
4
|
+
Tránh lỗi runtime không rõ nguyên nhân do thiếu hoặc sai cấu hình. Đảm bảo ứng dụng dừng sớm (fail fast) nếu thiếu cấu hình quan trọng.
|
|
5
|
+
|
|
6
|
+
## Mô tả
|
|
7
|
+
Rule này kiểm tra việc validate cấu hình bắt buộc ngay khi ứng dụng khởi động và yêu cầu hệ thống fail fast nếu có vấn đề với cấu hình.
|
|
8
|
+
|
|
9
|
+
## Các điều kiện kiểm tra
|
|
10
|
+
|
|
11
|
+
### 1. Schema Validation hoặc Explicit Checks
|
|
12
|
+
- Tất cả cấu hình bắt buộc phải được validate bằng schema libraries (zod, joi, yup, etc.) hoặc explicit checks
|
|
13
|
+
- Không được truy cập `process.env` mà không có validation
|
|
14
|
+
|
|
15
|
+
### 2. Fail Fast Behavior
|
|
16
|
+
- Khi phát hiện cấu hình thiếu hoặc không hợp lệ, ứng dụng phải dừng ngay lập tức
|
|
17
|
+
- Sử dụng `process.exit(1)`, `throw Error`, hoặc tương tự
|
|
18
|
+
|
|
19
|
+
### 3. Centralized Configuration
|
|
20
|
+
- Hạn chế việc truy cập environment variables rải rác trong code
|
|
21
|
+
- Tập trung xử lý cấu hình trong các module chuyên dụng
|
|
22
|
+
|
|
23
|
+
### 4. No Dangerous Defaults
|
|
24
|
+
- Không sử dụng default values nguy hiểm như empty string, localhost URLs
|
|
25
|
+
- Flag các pattern như `|| ''`, `|| 0`, `|| 'http://localhost'`
|
|
26
|
+
|
|
27
|
+
### 5. Startup Connectivity Checks
|
|
28
|
+
- Với database hoặc external services, cần có connectivity check khi startup
|
|
29
|
+
- Test kết nối trước khi application bắt đầu phục vụ requests
|
|
30
|
+
|
|
31
|
+
## Ví dụ
|
|
32
|
+
|
|
33
|
+
### ❌ Không đúng
|
|
34
|
+
```typescript
|
|
35
|
+
// Không có validation, dangerous defaults
|
|
36
|
+
const config = {
|
|
37
|
+
apiKey: process.env.API_KEY || 'default-key',
|
|
38
|
+
dbUrl: process.env.DATABASE_URL || '',
|
|
39
|
+
port: process.env.PORT || 3000
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function startServer() {
|
|
43
|
+
const server = createServer();
|
|
44
|
+
server.listen(config.port); // Có thể fail runtime nếu config sai
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### ✅ Đúng
|
|
49
|
+
```typescript
|
|
50
|
+
import { z } from 'zod';
|
|
51
|
+
|
|
52
|
+
const configSchema = z.object({
|
|
53
|
+
API_KEY: z.string().min(1, 'API_KEY is required'),
|
|
54
|
+
DATABASE_URL: z.string().url('DATABASE_URL must be valid URL'),
|
|
55
|
+
PORT: z.string().transform(val => parseInt(val, 10))
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
function validateConfig() {
|
|
59
|
+
try {
|
|
60
|
+
return configSchema.parse(process.env);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('Configuration validation failed:', error.message);
|
|
63
|
+
process.exit(1); // Fail fast
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const config = validateConfig();
|
|
68
|
+
|
|
69
|
+
async function checkDatabaseConnection() {
|
|
70
|
+
try {
|
|
71
|
+
const connection = await connectToDatabase(config.DATABASE_URL);
|
|
72
|
+
await connection.ping();
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error('Database connection failed:', error.message);
|
|
75
|
+
process.exit(1); // Fail fast on connectivity issues
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Cấu hình
|
|
81
|
+
|
|
82
|
+
### Schema Validation Libraries
|
|
83
|
+
- **TypeScript/JavaScript**: zod, joi, yup, envalid, dotenv-safe, class-validator
|
|
84
|
+
- **Java**: @ConfigurationProperties, @Validated, jakarta.validation, hibernate.validator
|
|
85
|
+
- **Go**: envconfig, viper
|
|
86
|
+
|
|
87
|
+
### Fail Fast Mechanisms
|
|
88
|
+
- **TypeScript/JavaScript**: `throw new Error()`, `process.exit(1)`
|
|
89
|
+
- **Java**: `throw new RuntimeException()`, `SpringApplication.exit()`, `System.exit(1)`
|
|
90
|
+
- **Go**: `log.Fatal()`, `panic()`, `os.Exit(1)`
|
|
91
|
+
|
|
92
|
+
### Policy Options
|
|
93
|
+
- `requireSchemaOrExplicitChecks`: Bắt buộc có validation
|
|
94
|
+
- `requireFailFast`: Bắt buộc có fail fast mechanism
|
|
95
|
+
- `forbidEnvReadsOutsideConfig`: Hạn chế env access ngoài config modules
|
|
96
|
+
- `flagDangerousDefaults`: Cảnh báo về dangerous default values
|
|
97
|
+
- `requireStartupConnectivityChecks`: Yêu cầu connectivity check
|
|
98
|
+
|
|
99
|
+
## Mức độ nghiêm trọng
|
|
100
|
+
**Error** - Rule này có thể ngăn chặn các lỗi runtime nghiêm trọng và khó debug.
|
|
101
|
+
|
|
102
|
+
## Ngôn ngữ hỗ trợ
|
|
103
|
+
- TypeScript/JavaScript
|
|
104
|
+
- Java
|
|
105
|
+
- Go
|
|
106
|
+
|
|
107
|
+
## Tham khảo
|
|
108
|
+
- [Fail Fast Principle](https://en.wikipedia.org/wiki/Fail-fast)
|
|
109
|
+
- [Configuration Validation Best Practices](https://12factor.net/config)
|
|
110
|
+
- [Schema Validation Libraries](https://github.com/colinhacks/zod)
|