@sun-asterisk/sunlint 1.3.6 → 1.3.8
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 +76 -1
- package/config/defaults/default.json +2 -1
- package/config/rule-analysis-strategies.js +20 -0
- package/config/rules/enhanced-rules-registry.json +230 -43
- package/core/analysis-orchestrator.js +9 -5
- package/core/file-targeting-service.js +83 -7
- package/core/performance-optimizer.js +8 -2
- 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/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/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 +436 -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 +287 -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
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ruleId": "C065",
|
|
3
|
+
"name": "One Behavior per Test (AAA Pattern)",
|
|
4
|
+
"description": "Each test case should focus on testing a single behavior to improve clarity and maintainability",
|
|
5
|
+
"category": "common",
|
|
6
|
+
"severity": "warn",
|
|
7
|
+
"languages": ["typescript", "javascript", "java", "csharp", "swift", "kotlin"],
|
|
8
|
+
"options": {
|
|
9
|
+
"assertApis": {
|
|
10
|
+
"javascript": ["expect\\(", "assert\\.", "should\\.", "chai\\.expect"],
|
|
11
|
+
"typescript": ["expect\\(", "assert\\.", "should\\.", "chai\\.expect"],
|
|
12
|
+
"java": ["assertThat\\(", "assertEquals\\(", "assertTrue\\(", "assertFalse\\(", "assertNull\\(", "assertNotNull\\("],
|
|
13
|
+
"csharp": ["Assert\\.", "Xunit\\.Assert", "NUnit\\.Framework\\.Assert"],
|
|
14
|
+
"swift": ["XCTAssert", "XCTAssertEqual", "XCTAssertTrue", "XCTAssertFalse"],
|
|
15
|
+
"kotlin": ["assertThat\\(", "assertEquals\\(", "assertTrue\\(", "assertFalse\\("]
|
|
16
|
+
},
|
|
17
|
+
"actHeuristics": {
|
|
18
|
+
"common": ["sut\\.", "\\.create\\(", "\\.update\\(", "\\.delete\\(", "\\.save\\(", "\\.execute\\(", "\\.handle\\(", "\\.run\\(", "\\.call\\(", "\\.process\\(", "service\\.", "repository\\.", "await\\s+\\w+\\."],
|
|
19
|
+
"javascript": ["\\.mockReturnValue\\(", "\\.mockResolvedValue\\(", "render\\(", "fireEvent\\.(click|submit|keyPress|keyDown|keyUp)", "userService\\.", "api\\.", "fetch\\(", "user\\.click\\(", "user\\.type\\(", "user\\.clear\\("],
|
|
20
|
+
"typescript": ["\\.mockReturnValue\\(", "\\.mockResolvedValue\\(", "render\\(", "fireEvent\\.(click|submit|keyPress|keyDown|keyUp)", "userService\\.", "api\\.", "fetch\\(", "user\\.click\\(", "user\\.type\\(", "user\\.clear\\("],
|
|
21
|
+
"java": ["\\.when\\(", "\\.thenReturn\\(", "\\.doReturn\\(", "\\.verify\\("],
|
|
22
|
+
"csharp": ["\\.Setup\\(", "\\.Returns\\(", "\\.Verify\\("],
|
|
23
|
+
"swift": ["given\\(", "when\\(", "then\\("],
|
|
24
|
+
"kotlin": ["every\\s*\\{", "verify\\s*\\{"]
|
|
25
|
+
},
|
|
26
|
+
"controlFlow": ["\\bif\\s*\\(", "\\bswitch\\s*\\(", "\\bfor\\s*\\(", "\\bwhile\\s*\\(", "\\btry\\s*\\{"],
|
|
27
|
+
"testPatterns": {
|
|
28
|
+
"javascript": ["\\bit\\s*\\(", "\\btest\\s*\\(", "\\bdescribe\\s*\\("],
|
|
29
|
+
"typescript": ["\\bit\\s*\\(", "\\btest\\s*\\(", "\\bdescribe\\s*\\("],
|
|
30
|
+
"java": ["@Test", "@ParameterizedTest"],
|
|
31
|
+
"csharp": ["\\[Test\\]", "\\[Fact\\]", "\\[Theory\\]"],
|
|
32
|
+
"swift": ["func\\s+test", "XCTestCase"],
|
|
33
|
+
"kotlin": ["@Test", "fun\\s+test"]
|
|
34
|
+
},
|
|
35
|
+
"parameterizedHints": ["test\\.each", "describe\\.each", "@ParameterizedTest", "where\\s*:", "\\[TestCase"],
|
|
36
|
+
"thresholds": {
|
|
37
|
+
"maxActsPerTest": 3,
|
|
38
|
+
"maxUnrelatedExpects": 2,
|
|
39
|
+
"maxControlFlowStatements": 0,
|
|
40
|
+
"maxTestMethodsPerFunction": 1
|
|
41
|
+
},
|
|
42
|
+
"flags": {
|
|
43
|
+
"flagControlFlowInTest": true,
|
|
44
|
+
"treatSnapshotAsSingleAssert": true,
|
|
45
|
+
"allowMultipleAssertsForSameObject": true,
|
|
46
|
+
"allowSetupAssertions": true,
|
|
47
|
+
"allowMultipleUIActions": true
|
|
48
|
+
},
|
|
49
|
+
"whitelist": {
|
|
50
|
+
"setupMethods": ["beforeEach", "setUp", "before", "Given"],
|
|
51
|
+
"teardownMethods": ["afterEach", "tearDown", "after"],
|
|
52
|
+
"helperMethods": ["helper", "util", "mock", "stub", "spy"]
|
|
53
|
+
},
|
|
54
|
+
"allowlist": {
|
|
55
|
+
"paths": ["test/", "tests/", "__tests__/", "spec/", "specs/", "*.test.*", "*.spec.*"],
|
|
56
|
+
"filePatterns": ["\\.test\\.", "\\.spec\\.", "Test\\.java$", "Tests\\.cs$", "Test\\.swift$", "Test\\.kt$"],
|
|
57
|
+
"formInteractionSequences": [
|
|
58
|
+
"fireEvent\\.change.*fireEvent\\.blur",
|
|
59
|
+
"fireEvent\\.change.*fireEvent\\.focus",
|
|
60
|
+
"user\\.type.*user\\.tab",
|
|
61
|
+
"user\\.type.*user\\.clear",
|
|
62
|
+
"render.*fireEvent\\.change.*fireEvent\\.blur"
|
|
63
|
+
],
|
|
64
|
+
"uiInteractionWorkflows": [
|
|
65
|
+
"fireEvent\\.click.*expect\\(",
|
|
66
|
+
"fireEvent\\.click.*fireEvent\\.click",
|
|
67
|
+
"render.*fireEvent\\.click.*expect\\(",
|
|
68
|
+
"getByRole.*fireEvent\\.click.*expect\\(",
|
|
69
|
+
"queryByText.*fireEvent\\.click",
|
|
70
|
+
"user\\.click.*expect\\(",
|
|
71
|
+
"user\\.click.*user\\.click"
|
|
72
|
+
],
|
|
73
|
+
"setupActionPatterns": [
|
|
74
|
+
"render\\(",
|
|
75
|
+
"fireEvent\\.(change|blur|focus|mouseEnter|mouseLeave)",
|
|
76
|
+
"user\\.(hover|focus|tab|clear)",
|
|
77
|
+
"\\.mockReturnValue\\(",
|
|
78
|
+
"\\.mockResolvedValue\\("
|
|
79
|
+
],
|
|
80
|
+
"uiSetupPatterns": [
|
|
81
|
+
"getByRole\\(",
|
|
82
|
+
"queryByText\\(",
|
|
83
|
+
"queryAllByText\\(",
|
|
84
|
+
"getByText\\(",
|
|
85
|
+
"findByRole\\(",
|
|
86
|
+
"act\\(.*render"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"overrideExclude": {
|
|
90
|
+
"enabled": true,
|
|
91
|
+
"reason": "C065 needs to analyze test files that are typically excluded by project configs",
|
|
92
|
+
"removePatterns": ["**/*.test.*", "**/*.spec.*", "src/**/*.test.{ts,tsx}", "src/**/*.spec.{ts,tsx}"]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -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)
|