@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,224 @@
|
|
|
1
|
+
# S010 - Must use cryptographically secure random number generators (CSPRNG)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Quy tắc này phát hiện việc sử dụng các hàm tạo số ngẫu nhiên không an toàn (như `Math.random()`) cho các mục đích bảo mật, có thể dẫn đến các lỗ hổng bảo mật nghiêm trọng do tính có thể dự đoán được.
|
|
5
|
+
|
|
6
|
+
## OWASP Classification
|
|
7
|
+
- **Category**: A02:2021 - Cryptographic Failures
|
|
8
|
+
- **CWE**: CWE-338 - Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)
|
|
9
|
+
- **Severity**: Error
|
|
10
|
+
- **Impact**: High (Predictable tokens, weak encryption keys, authentication bypass)
|
|
11
|
+
|
|
12
|
+
## Vấn đề
|
|
13
|
+
Khi sử dụng các hàm tạo số ngẫu nhiên không an toàn cho mục đích bảo mật:
|
|
14
|
+
|
|
15
|
+
1. **Tính dự đoán**: `Math.random()` và các hàm tương tự có thể được dự đoán bởi kẻ tấn công
|
|
16
|
+
2. **Weak entropy**: Không đủ entropy để tạo ra các giá trị thực sự ngẫu nhiên
|
|
17
|
+
3. **Seed attacks**: Có thể bị tấn công thông qua việc dự đoán seed
|
|
18
|
+
4. **Brute force**: Dễ dàng bị brute force do không gian giá trị hạn chế
|
|
19
|
+
|
|
20
|
+
## Các trường hợp vi phạm
|
|
21
|
+
|
|
22
|
+
### 1. Sử dụng Math.random() cho security tokens
|
|
23
|
+
```javascript
|
|
24
|
+
// ❌ Vi phạm - Math.random() không an toàn cho security
|
|
25
|
+
const sessionToken = Math.random().toString(36).substring(2);
|
|
26
|
+
const apiKey = Math.floor(Math.random() * 1000000);
|
|
27
|
+
const resetCode = Math.random().toString().substring(2, 8);
|
|
28
|
+
|
|
29
|
+
// ❌ Vi phạm - tạo password reset token
|
|
30
|
+
function generateResetToken() {
|
|
31
|
+
return Math.random().toString(36).substring(2, 15) +
|
|
32
|
+
Math.random().toString(36).substring(2, 15);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ❌ Vi phạm - tạo JWT secret
|
|
36
|
+
const jwtSecret = Math.random().toString(36);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Sử dụng timestamp cho random generation
|
|
40
|
+
```javascript
|
|
41
|
+
// ❌ Vi phạm - timestamp có thể dự đoán được
|
|
42
|
+
const userId = Date.now().toString();
|
|
43
|
+
const sessionId = new Date().getTime().toString();
|
|
44
|
+
const nonce = performance.now().toString();
|
|
45
|
+
|
|
46
|
+
// ❌ Vi phạm - kết hợp timestamp với Math.random()
|
|
47
|
+
const token = Date.now() + '-' + Math.random().toString(36);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3. Sử dụng cho mã hóa và authentication
|
|
51
|
+
```javascript
|
|
52
|
+
// ❌ Vi phạm - tạo encryption key không an toàn
|
|
53
|
+
const encryptionKey = Math.random().toString(36).repeat(3);
|
|
54
|
+
|
|
55
|
+
// ❌ Vi phạm - tạo salt cho password hashing
|
|
56
|
+
const salt = Math.random().toString(36).substring(2);
|
|
57
|
+
bcrypt.hash(password, salt); // Nguy hiểm!
|
|
58
|
+
|
|
59
|
+
// ❌ Vi phạm - tạo CSRF token
|
|
60
|
+
const csrfToken = Math.floor(Math.random() * 1000000000);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 4. Tạo unique identifiers không an toàn
|
|
64
|
+
```javascript
|
|
65
|
+
// ❌ Vi phạm - tạo user ID
|
|
66
|
+
const generateUserId = () => Math.random().toString(36).substring(2);
|
|
67
|
+
|
|
68
|
+
// ❌ Vi phạm - tạo file upload path
|
|
69
|
+
const uploadPath = `/uploads/${Math.random().toString(36)}/file.jpg`;
|
|
70
|
+
|
|
71
|
+
// ❌ Vi phạm - tạo temporary filename
|
|
72
|
+
const tempFile = `temp_${Date.now()}_${Math.random()}.tmp`;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Giải pháp an toàn
|
|
76
|
+
|
|
77
|
+
### 1. Sử dụng crypto.randomBytes()
|
|
78
|
+
```javascript
|
|
79
|
+
// ✅ An toàn - sử dụng crypto.randomBytes()
|
|
80
|
+
const crypto = require('crypto');
|
|
81
|
+
|
|
82
|
+
const sessionToken = crypto.randomBytes(32).toString('hex');
|
|
83
|
+
const apiKey = crypto.randomBytes(16).toString('base64');
|
|
84
|
+
const resetCode = crypto.randomBytes(3).toString('hex'); // 6 hex chars
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 2. Sử dụng crypto.randomUUID()
|
|
88
|
+
```javascript
|
|
89
|
+
// ✅ An toàn - sử dụng crypto.randomUUID()
|
|
90
|
+
const sessionId = crypto.randomUUID();
|
|
91
|
+
const userId = crypto.randomUUID();
|
|
92
|
+
const requestId = crypto.randomUUID();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 3. Sử dụng crypto.randomInt()
|
|
96
|
+
```javascript
|
|
97
|
+
// ✅ An toàn - sử dụng crypto.randomInt()
|
|
98
|
+
const otpCode = crypto.randomInt(100000, 999999); // 6-digit OTP
|
|
99
|
+
const randomPort = crypto.randomInt(3000, 9000);
|
|
100
|
+
const challengeNumber = crypto.randomInt(1, 1000000);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 4. Sử dụng cho mã hóa an toàn
|
|
104
|
+
```javascript
|
|
105
|
+
// ✅ An toàn - tạo encryption key
|
|
106
|
+
const encryptionKey = crypto.randomBytes(32); // 256-bit key
|
|
107
|
+
|
|
108
|
+
// ✅ An toàn - tạo salt cho password hashing
|
|
109
|
+
const saltRounds = 12;
|
|
110
|
+
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
|
111
|
+
|
|
112
|
+
// ✅ An toàn - tạo IV cho encryption
|
|
113
|
+
const iv = crypto.randomBytes(16);
|
|
114
|
+
const cipher = crypto.createCipher('aes-256-cbc', key, iv);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 5. Sử dụng thư viện an toàn
|
|
118
|
+
```javascript
|
|
119
|
+
// ✅ An toàn - sử dụng nanoid
|
|
120
|
+
const { nanoid } = require('nanoid');
|
|
121
|
+
const id = nanoid(); // URL-safe, secure ID
|
|
122
|
+
|
|
123
|
+
// ✅ An toàn - sử dụng uuid v4
|
|
124
|
+
const { v4: uuidv4 } = require('uuid');
|
|
125
|
+
const userId = uuidv4();
|
|
126
|
+
|
|
127
|
+
// ✅ An toàn - sử dụng secure-random
|
|
128
|
+
const secureRandom = require('secure-random');
|
|
129
|
+
const randomBytes = secureRandom(32, { type: 'Buffer' });
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 6. Express.js session security
|
|
133
|
+
```javascript
|
|
134
|
+
// ✅ An toàn - cấu hình Express session
|
|
135
|
+
const session = require('express-session');
|
|
136
|
+
|
|
137
|
+
app.use(session({
|
|
138
|
+
genid: () => crypto.randomUUID(), // Secure session ID
|
|
139
|
+
secret: crypto.randomBytes(64).toString('hex'), // Secure secret
|
|
140
|
+
resave: false,
|
|
141
|
+
saveUninitialized: false,
|
|
142
|
+
cookie: {
|
|
143
|
+
secure: true, // HTTPS only
|
|
144
|
+
httpOnly: true,
|
|
145
|
+
maxAge: 1800000 // 30 minutes
|
|
146
|
+
}
|
|
147
|
+
}));
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 7. JWT token generation
|
|
151
|
+
```javascript
|
|
152
|
+
// ✅ An toàn - tạo JWT với secure secret
|
|
153
|
+
const jwtSecret = crypto.randomBytes(64).toString('hex');
|
|
154
|
+
|
|
155
|
+
const token = jwt.sign(
|
|
156
|
+
{ userId, exp: Math.floor(Date.now() / 1000) + 3600 },
|
|
157
|
+
jwtSecret,
|
|
158
|
+
{ algorithm: 'HS256' }
|
|
159
|
+
);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Phương pháp phát hiện
|
|
163
|
+
|
|
164
|
+
Rule này sử dụng heuristic analysis để phát hiện:
|
|
165
|
+
|
|
166
|
+
1. **Pattern matching**: Tìm kiếm các pattern như `Math.random()`, `Date.now()`, `performance.now()`
|
|
167
|
+
2. **Context analysis**: Phân tích ngữ cảnh để xác định có phải mục đích bảo mật không
|
|
168
|
+
3. **Function analysis**: Kiểm tra tên function có chứa từ khóa bảo mật
|
|
169
|
+
4. **Variable analysis**: Phân tích tên biến có liên quan đến bảo mật
|
|
170
|
+
5. **Surrounding context**: Kiểm tra các dòng xung quanh để xác định context
|
|
171
|
+
|
|
172
|
+
## Cấu hình
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"S010": {
|
|
177
|
+
"enabled": true,
|
|
178
|
+
"severity": "error",
|
|
179
|
+
"excludePatterns": [
|
|
180
|
+
"test/**",
|
|
181
|
+
"**/*.test.js",
|
|
182
|
+
"**/*.spec.js",
|
|
183
|
+
"**/demo/**",
|
|
184
|
+
"**/examples/**"
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Best Practices
|
|
191
|
+
|
|
192
|
+
1. **Luôn sử dụng CSPRNG**: Sử dụng `crypto.randomBytes()`, `crypto.randomUUID()`, `crypto.randomInt()` cho mục đích bảo mật
|
|
193
|
+
2. **Đủ entropy**: Đảm bảo đủ entropy cho các giá trị random (ít nhất 128 bits cho tokens)
|
|
194
|
+
3. **Secure storage**: Lưu trữ các giá trị random một cách an toàn
|
|
195
|
+
4. **Time-limited**: Sử dụng expiration time cho các tokens
|
|
196
|
+
5. **Proper seeding**: Đảm bảo CSPRNG được seed đúng cách
|
|
197
|
+
6. **Regular rotation**: Thường xuyên rotate các keys và secrets
|
|
198
|
+
|
|
199
|
+
## Các trường hợp ngoại lệ
|
|
200
|
+
|
|
201
|
+
Rule này sẽ KHÔNG báo lỗi trong các trường hợp sau:
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
// ✅ Không báo lỗi - sử dụng cho UI/animation
|
|
205
|
+
const animationDelay = Math.random() * 1000;
|
|
206
|
+
const chartColor = `hsl(${Math.random() * 360}, 50%, 50%)`;
|
|
207
|
+
|
|
208
|
+
// ✅ Không báo lỗi - game logic
|
|
209
|
+
const diceRoll = Math.floor(Math.random() * 6) + 1;
|
|
210
|
+
const enemySpawn = Math.random() < 0.3;
|
|
211
|
+
|
|
212
|
+
// ✅ Không báo lỗi - demo/test data
|
|
213
|
+
const mockData = Array.from({length: 10}, () => ({
|
|
214
|
+
value: Math.random() * 100
|
|
215
|
+
}));
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Tài liệu tham khảo
|
|
219
|
+
|
|
220
|
+
- [OWASP A02:2021 - Cryptographic Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures/)
|
|
221
|
+
- [CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator](https://cwe.mitre.org/data/definitions/338.html)
|
|
222
|
+
- [Node.js Crypto Documentation](https://nodejs.org/api/crypto.html)
|
|
223
|
+
- [NIST Guidelines for Random Number Generation](https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final)
|
|
224
|
+
- [Secure Random Number Generation Best Practices](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html)
|