@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
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
## ๐ง **v1.3.9 - File Targeting Regression Fix (October 2, 2025)**
|
|
6
|
+
|
|
7
|
+
**Release Date**: October 2, 2025
|
|
8
|
+
**Type**: Bug Fix
|
|
9
|
+
**Branch**: `feature.sunlint.heuristic_rule_c065`
|
|
10
|
+
|
|
11
|
+
### ๐ **Critical Bug Fixes**
|
|
12
|
+
- **FIXED**: File targeting regression where user-specified source directories were incorrectly optimized
|
|
13
|
+
- **Issue**: When using `--input=examples/project-samples/replace-fe/src`, file count dropped from 2.2K to 254 files
|
|
14
|
+
- **Root Cause**: `optimizeProjectPaths` function incorrectly treated user-specified source directories as project roots
|
|
15
|
+
- **Solution**: Added source directory detection logic to bypass optimization for `src`, `lib`, `app`, `packages`, `test` directories
|
|
16
|
+
- **Impact**: Full file coverage restored - all 1507 .tsx files now properly included
|
|
17
|
+
|
|
18
|
+
### โก **Performance Improvements**
|
|
19
|
+
- **ENHANCED**: File targeting logic with smart source directory detection
|
|
20
|
+
- **OPTIMIZED**: Direct targeting for user-specified source paths
|
|
21
|
+
|
|
22
|
+
### ๐ **Technical Details**
|
|
23
|
+
- Modified `file-targeting-service.js` `optimizeProjectPaths` function
|
|
24
|
+
- Added `sourceDirectoryNames` array for known source directory patterns
|
|
25
|
+
- Implemented basename checking to detect when users specify source directories directly
|
|
26
|
+
- Maintained backward compatibility with existing project structure detection
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## ๐งช **v1.3.8 - C065 Rule Enhancement & Advanced Context Analysis (October 1, 2025)**
|
|
31
|
+
|
|
32
|
+
**Release Date**: October 1, 2025
|
|
33
|
+
**Type**: Major Enhancement
|
|
34
|
+
**Branch**: `feature.sunlint.heuristic_rule_c065`
|
|
35
|
+
|
|
36
|
+
### โจ **Major Features**
|
|
37
|
+
- **ENHANCED**: C065 "One Behavior per Test" Rule with Advanced Context Analysis
|
|
38
|
+
- **New**: UI Workflow Detection for legitimate testing patterns
|
|
39
|
+
- **New**: UI Interaction Loop Detection (fireEvent iterations)
|
|
40
|
+
- **New**: Smart Control Flow Analysis with UI pattern exclusions
|
|
41
|
+
- **New**: Assertion context grouping for accurate behavior detection
|
|
42
|
+
- **ENHANCED**: File Targeting System with Smart Test Detection
|
|
43
|
+
- **Performance**: 98% file reduction (6873 โ 112 files) with `--include-tests`
|
|
44
|
+
- **Accuracy**: Intelligent project targeting and language filter override
|
|
45
|
+
- **ENHANCED**: Debug Output Management
|
|
46
|
+
- **Clean**: Production-ready output with conditional debug logging
|
|
47
|
+
- **Detailed**: Comprehensive debug info available with `--verbose` flag
|
|
48
|
+
|
|
49
|
+
### ๐ **Critical Bug Fixes**
|
|
50
|
+
- **FIXED**: C065 Rule Registry and Configuration
|
|
51
|
+
- **Issue**: Rule loading from incorrect `rules/quality/` path
|
|
52
|
+
- **Solution**: Updated to correct `rules/common/` path with proper categorization
|
|
53
|
+
- **FIXED**: False Positive Control Flow Detection
|
|
54
|
+
- **Issue**: UI testing loops incorrectly flagged as violations
|
|
55
|
+
- **Solution**: Pattern recognition for legitimate UI element iteration
|
|
56
|
+
- **FIXED**: Test File Language Filtering
|
|
57
|
+
- **Issue**: Test files excluded by language patterns
|
|
58
|
+
- **Solution**: Override exclusions for `--include-tests` flag
|
|
59
|
+
|
|
60
|
+
### ๐ฏ **Rule Accuracy Validation**
|
|
61
|
+
- **UI Loops**: `for (const checkbox of listCheckbox) { fireEvent.click(checkbox); }` โ
No false positive
|
|
62
|
+
- **Button Iteration**: `for (const button of buttons) { fireEvent.click(button); }` โ
No false positive
|
|
63
|
+
- **Business Logic**: Complex control flow with if/else statements โ Properly flagged
|
|
64
|
+
- **Multiple Behaviors**: Tests with multiple mock setups โ Properly flagged
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
5
68
|
## ๏ฟฝ **v1.3.7 - File Count Reporting & Performance Fixes (September 11, 2025)**
|
|
6
69
|
|
|
7
70
|
**Release Date**: September 11, 2025
|
|
@@ -41,6 +41,26 @@ module.exports = {
|
|
|
41
41
|
reason: 'JSON injection detection requires AST context analysis',
|
|
42
42
|
methods: ['ast', 'regex'],
|
|
43
43
|
accuracy: { ast: 95, regex: 60 }
|
|
44
|
+
},
|
|
45
|
+
'S054': {
|
|
46
|
+
reason: 'Default account detection in code, SQL, and config files',
|
|
47
|
+
methods: ['regex', 'ast'],
|
|
48
|
+
accuracy: { regex: 85, ast: 90 }
|
|
49
|
+
},
|
|
50
|
+
'S052': {
|
|
51
|
+
reason: 'OTP entropy analysis requires hybrid approach for RNG detection and context awareness',
|
|
52
|
+
methods: ['regex', 'ast'],
|
|
53
|
+
accuracy: { regex: 80, ast: 90 }
|
|
54
|
+
},
|
|
55
|
+
'S051': {
|
|
56
|
+
reason: 'Password length policy requires multi-signal context detection and cross-file validation',
|
|
57
|
+
methods: ['regex', 'ast'],
|
|
58
|
+
accuracy: { regex: 85, ast: 92 }
|
|
59
|
+
},
|
|
60
|
+
'C065': {
|
|
61
|
+
reason: 'Test behavior analysis requires hybrid heuristic + AST context for multiple assertions and control flow detection',
|
|
62
|
+
methods: ['regex', 'ast'],
|
|
63
|
+
accuracy: { regex: 85, ast: 92 }
|
|
44
64
|
}
|
|
45
65
|
},
|
|
46
66
|
|
|
@@ -660,16 +660,51 @@
|
|
|
660
660
|
"tags": ["security", "email", "injection"]
|
|
661
661
|
},
|
|
662
662
|
"S020": {
|
|
663
|
-
"name": "
|
|
664
|
-
"description": "
|
|
663
|
+
"name": "Avoid using eval() or executing dynamic code",
|
|
664
|
+
"description": "Avoid using eval() or executing dynamic code as it can lead to code injection vulnerabilities and compromise application security.",
|
|
665
665
|
"category": "security",
|
|
666
666
|
"severity": "error",
|
|
667
667
|
"languages": ["typescript", "javascript"],
|
|
668
|
-
"analyzer": "
|
|
669
|
-
"
|
|
668
|
+
"analyzer": "./rules/security/S020_no_eval_dynamic_code/analyzer.js",
|
|
669
|
+
"config": "./rules/security/S020_no_eval_dynamic_code/config.json",
|
|
670
670
|
"version": "1.0.0",
|
|
671
|
-
"status": "
|
|
672
|
-
"tags": ["security", "eval", "dynamic-execution"]
|
|
671
|
+
"status": "experimental",
|
|
672
|
+
"tags": ["security", "eval", "dynamic-execution", "code-injection"],
|
|
673
|
+
"strategy": {
|
|
674
|
+
"preferred": "ast",
|
|
675
|
+
"fallbacks": ["ast", "regex"],
|
|
676
|
+
"accuracy": { "ast": 95, "regex": 85 }
|
|
677
|
+
},
|
|
678
|
+
"engineMappings": {
|
|
679
|
+
"heuristic": ["rules/security/S020_no_eval_dynamic_code/analyzer.js"]
|
|
680
|
+
}
|
|
681
|
+
},
|
|
682
|
+
"S030": {
|
|
683
|
+
"name": "Disable directory browsing and protect sensitive metadata files",
|
|
684
|
+
"description": "Disable directory browsing and protect sensitive metadata files (.git/, .env, config files, etc.) to prevent information disclosure and potential security vulnerabilities.",
|
|
685
|
+
"category": "security",
|
|
686
|
+
"severity": "error",
|
|
687
|
+
"languages": ["typescript", "javascript"],
|
|
688
|
+
"analyzer": "./rules/security/S030_directory_browsing_protection/analyzer.js",
|
|
689
|
+
"config": "./rules/security/S030_directory_browsing_protection/config.json",
|
|
690
|
+
"version": "1.0.0",
|
|
691
|
+
"status": "experimental",
|
|
692
|
+
"tags": [
|
|
693
|
+
"security",
|
|
694
|
+
"directory-browsing",
|
|
695
|
+
"information-disclosure",
|
|
696
|
+
"metadata-protection"
|
|
697
|
+
],
|
|
698
|
+
"strategy": {
|
|
699
|
+
"preferred": "ast",
|
|
700
|
+
"fallbacks": ["ast", "regex"],
|
|
701
|
+
"accuracy": { "ast": 90, "regex": 75 }
|
|
702
|
+
},
|
|
703
|
+
"engineMappings": {
|
|
704
|
+
"heuristic": [
|
|
705
|
+
"rules/security/S030_directory_browsing_protection/analyzer.js"
|
|
706
|
+
]
|
|
707
|
+
}
|
|
673
708
|
},
|
|
674
709
|
"S022": {
|
|
675
710
|
"name": "Output Encoding Required",
|
|
@@ -736,7 +771,13 @@
|
|
|
736
771
|
"config": "./rules/security/S025_server_side_validation/config.json",
|
|
737
772
|
"version": "1.0.0",
|
|
738
773
|
"status": "stable",
|
|
739
|
-
"tags": [
|
|
774
|
+
"tags": [
|
|
775
|
+
"security",
|
|
776
|
+
"validation",
|
|
777
|
+
"server-side",
|
|
778
|
+
"owasp",
|
|
779
|
+
"input-validation"
|
|
780
|
+
],
|
|
740
781
|
"strategy": {
|
|
741
782
|
"preferred": "ast",
|
|
742
783
|
"fallbacks": ["ast", "regex"],
|
|
@@ -785,18 +826,6 @@
|
|
|
785
826
|
"status": "stable",
|
|
786
827
|
"tags": ["security", "csrf", "protection"]
|
|
787
828
|
},
|
|
788
|
-
"S030": {
|
|
789
|
-
"name": "No Directory Browsing",
|
|
790
|
-
"description": "Prevent directory browsing vulnerabilities",
|
|
791
|
-
"category": "security",
|
|
792
|
-
"severity": "error",
|
|
793
|
-
"languages": ["typescript", "javascript"],
|
|
794
|
-
"analyzer": "eslint",
|
|
795
|
-
"eslintRule": "custom/typescript_s030",
|
|
796
|
-
"version": "1.0.0",
|
|
797
|
-
"status": "stable",
|
|
798
|
-
"tags": ["security", "directory-browsing", "information-disclosure"]
|
|
799
|
-
},
|
|
800
829
|
"S031": {
|
|
801
830
|
"name": "Set Secure flag for Session Cookies",
|
|
802
831
|
"description": "Set Secure flag for Session Cookies to protect via HTTPS. This ensures cookies are only transmitted over secure connections, preventing interception.",
|
|
@@ -927,40 +956,71 @@
|
|
|
927
956
|
"tags": ["security", "file-inclusion", "path-traversal"]
|
|
928
957
|
},
|
|
929
958
|
"S037": {
|
|
930
|
-
"name": "
|
|
931
|
-
"description": "
|
|
959
|
+
"name": "Configure comprehensive cache headers to prevent sensitive data leakage",
|
|
960
|
+
"description": "Configure comprehensive cache headers (Cache-Control: no-store, no-cache, must-revalidate, Pragma: no-cache, Expires: 0) for sensitive responses to avoid caching sensitive data in browsers or intermediaries.",
|
|
932
961
|
"category": "security",
|
|
933
962
|
"severity": "warning",
|
|
934
963
|
"languages": ["typescript", "javascript"],
|
|
935
|
-
"analyzer": "
|
|
936
|
-
"
|
|
964
|
+
"analyzer": "./rules/security/S037_cache_headers/analyzer.js",
|
|
965
|
+
"config": "./rules/security/S037_cache_headers/config.json",
|
|
937
966
|
"version": "1.0.0",
|
|
938
|
-
"status": "
|
|
939
|
-
"tags": ["security", "caching", "headers"]
|
|
967
|
+
"status": "experimental",
|
|
968
|
+
"tags": ["security", "caching", "headers", "privacy"],
|
|
969
|
+
"strategy": {
|
|
970
|
+
"preferred": "ast",
|
|
971
|
+
"fallbacks": ["ast", "regex"],
|
|
972
|
+
"accuracy": { "ast": 90, "regex": 75 }
|
|
973
|
+
},
|
|
974
|
+
"engineMappings": {
|
|
975
|
+
"heuristic": ["rules/security/S037_cache_headers/analyzer.js"]
|
|
976
|
+
}
|
|
940
977
|
},
|
|
941
978
|
"S038": {
|
|
942
|
-
"name": "
|
|
943
|
-
"description": "Prevent version information disclosure",
|
|
979
|
+
"name": "Do not expose version information in response headers",
|
|
980
|
+
"description": "Prevent exposure of server version information through response headers (Server, X-Powered-By, X-AspNet-Version, etc.) to reduce information disclosure and potential attack vectors.",
|
|
944
981
|
"category": "security",
|
|
945
982
|
"severity": "warning",
|
|
946
983
|
"languages": ["typescript", "javascript"],
|
|
947
|
-
"analyzer": "
|
|
948
|
-
"
|
|
984
|
+
"analyzer": "./rules/security/S038_no_version_headers/analyzer.js",
|
|
985
|
+
"config": "./rules/security/S038_no_version_headers/config.json",
|
|
949
986
|
"version": "1.0.0",
|
|
950
|
-
"status": "
|
|
951
|
-
"tags": ["security", "information-disclosure", "version"]
|
|
987
|
+
"status": "experimental",
|
|
988
|
+
"tags": ["security", "information-disclosure", "version", "headers"],
|
|
989
|
+
"strategy": {
|
|
990
|
+
"preferred": "ast",
|
|
991
|
+
"fallbacks": ["ast", "regex"],
|
|
992
|
+
"accuracy": { "ast": 90, "regex": 75 }
|
|
993
|
+
},
|
|
994
|
+
"engineMappings": {
|
|
995
|
+
"heuristic": ["rules/security/S038_no_version_headers/analyzer.js"]
|
|
996
|
+
}
|
|
952
997
|
},
|
|
953
998
|
"S039": {
|
|
954
|
-
"name": "
|
|
955
|
-
"description": "
|
|
999
|
+
"name": "Do not pass Session Tokens via URL parameters",
|
|
1000
|
+
"description": "Detects when session tokens, authentication tokens, JWT tokens, or other sensitive authentication data are passed as URL parameters instead of secure headers or request body. URL parameters are logged in web server logs, browser history, and can be exposed in referrer headers.",
|
|
956
1001
|
"category": "security",
|
|
957
|
-
"severity": "
|
|
1002
|
+
"severity": "warning",
|
|
958
1003
|
"languages": ["typescript", "javascript"],
|
|
959
|
-
"analyzer": "
|
|
960
|
-
"
|
|
1004
|
+
"analyzer": "./rules/security/S039_no_session_tokens_in_url/analyzer.js",
|
|
1005
|
+
"config": "./rules/security/S039_no_session_tokens_in_url/config.json",
|
|
961
1006
|
"version": "1.0.0",
|
|
962
|
-
"status": "
|
|
963
|
-
"tags": [
|
|
1007
|
+
"status": "experimental",
|
|
1008
|
+
"tags": [
|
|
1009
|
+
"security",
|
|
1010
|
+
"session-tokens",
|
|
1011
|
+
"url-parameters",
|
|
1012
|
+
"authentication"
|
|
1013
|
+
],
|
|
1014
|
+
"strategy": {
|
|
1015
|
+
"preferred": "ast",
|
|
1016
|
+
"fallbacks": ["ast", "regex"],
|
|
1017
|
+
"accuracy": { "ast": 85, "regex": 70 }
|
|
1018
|
+
},
|
|
1019
|
+
"engineMappings": {
|
|
1020
|
+
"heuristic": [
|
|
1021
|
+
"rules/security/S039_no_session_tokens_in_url/analyzer.js"
|
|
1022
|
+
]
|
|
1023
|
+
}
|
|
964
1024
|
},
|
|
965
1025
|
"S041": {
|
|
966
1026
|
"name": "Require Session Invalidate on Logout",
|
|
@@ -1058,6 +1118,36 @@
|
|
|
1058
1118
|
"status": "stable",
|
|
1059
1119
|
"tags": ["security", "password", "recovery"]
|
|
1060
1120
|
},
|
|
1121
|
+
"S049": {
|
|
1122
|
+
"name": "Authentication tokens should have short validity periods",
|
|
1123
|
+
"description": "Authentication tokens (JWT, session tokens, etc.) should have appropriately short validity periods to minimize the risk of token compromise. Long-lived tokens increase the attack surface and potential impact of token theft.",
|
|
1124
|
+
"category": "security",
|
|
1125
|
+
"severity": "error",
|
|
1126
|
+
"languages": ["typescript", "javascript"],
|
|
1127
|
+
"analyzer": "./rules/security/S049_short_validity_tokens/analyzer.js",
|
|
1128
|
+
"config": "./rules/security/S049_short_validity_tokens/config.json",
|
|
1129
|
+
"version": "1.0.0",
|
|
1130
|
+
"status": "stable",
|
|
1131
|
+
"tags": [
|
|
1132
|
+
"security",
|
|
1133
|
+
"authentication",
|
|
1134
|
+
"tokens",
|
|
1135
|
+
"jwt",
|
|
1136
|
+
"session",
|
|
1137
|
+
"owasp"
|
|
1138
|
+
],
|
|
1139
|
+
"strategy": {
|
|
1140
|
+
"preferred": "ast",
|
|
1141
|
+
"fallbacks": ["ast", "regex"],
|
|
1142
|
+
"accuracy": {
|
|
1143
|
+
"ast": 90,
|
|
1144
|
+
"regex": 75
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
"engineMappings": {
|
|
1148
|
+
"heuristic": ["rules/security/S049_short_validity_tokens/analyzer.js"]
|
|
1149
|
+
}
|
|
1150
|
+
},
|
|
1061
1151
|
"S050": {
|
|
1062
1152
|
"name": "Session Token Weak Hash",
|
|
1063
1153
|
"description": "Prevent weak hashing for session tokens",
|
|
@@ -1070,29 +1160,87 @@
|
|
|
1070
1160
|
"status": "stable",
|
|
1071
1161
|
"tags": ["security", "session", "hashing"]
|
|
1072
1162
|
},
|
|
1163
|
+
"S051": {
|
|
1164
|
+
"name": "Password length policy enforcement (12-64 chars recommended, reject >128)",
|
|
1165
|
+
"description": "Enforce strong password length policies with multi-signal detection. Prevent weak validators, missing limits, and FE/BE mismatches.",
|
|
1166
|
+
"category": "security",
|
|
1167
|
+
"severity": "error",
|
|
1168
|
+
"languages": ["typescript", "javascript"],
|
|
1169
|
+
"analyzer": "./rules/security/S051_password_length_policy/analyzer.js",
|
|
1170
|
+
"config": "./rules/security/S051_password_length_policy/config.json",
|
|
1171
|
+
"eslintRule": "custom/typescript_s051",
|
|
1172
|
+
"version": "1.0.0",
|
|
1173
|
+
"status": "stable",
|
|
1174
|
+
"tags": ["security", "password", "validation", "length", "policy"],
|
|
1175
|
+
"engineMappings": {
|
|
1176
|
+
"eslint": ["custom/typescript_s051"],
|
|
1177
|
+
"heuristic": [
|
|
1178
|
+
"./rules/security/S051_password_length_policy/analyzer.js"
|
|
1179
|
+
]
|
|
1180
|
+
}
|
|
1181
|
+
},
|
|
1182
|
+
"C065": {
|
|
1183
|
+
"name": "One Behavior per Test (AAA Pattern)",
|
|
1184
|
+
"description": "Enforce single behavior testing - each test should verify exactly one action/behavior with clear Arrange-Act-Assert structure",
|
|
1185
|
+
"category": "common",
|
|
1186
|
+
"severity": "warning",
|
|
1187
|
+
"languages": ["typescript", "javascript", "java", "csharp", "swift", "kotlin", "python"],
|
|
1188
|
+
"analyzer": "./rules/common/C065_one_behavior_per_test/analyzer.js",
|
|
1189
|
+
"config": "./rules/common/C065_one_behavior_per_test/config.json",
|
|
1190
|
+
"version": "1.0.0",
|
|
1191
|
+
"status": "stable",
|
|
1192
|
+
"tags": ["testing", "aaa", "behavior", "maintainability", "clarity"],
|
|
1193
|
+
"engineMappings": {
|
|
1194
|
+
"heuristic": ["./rules/common/C065_one_behavior_per_test/analyzer.js"]
|
|
1195
|
+
}
|
|
1196
|
+
},
|
|
1073
1197
|
"S052": {
|
|
1074
|
-
"name": "
|
|
1075
|
-
"description": "
|
|
1198
|
+
"name": "OTP must have โฅ20-bit entropy (โฅ6 digits) and use CSPRNG",
|
|
1199
|
+
"description": "Prevent guessable OTP by enforcing CSPRNG and minimal entropy. Ban non-crypto RNG and too-short codes.",
|
|
1076
1200
|
"category": "security",
|
|
1077
1201
|
"severity": "error",
|
|
1078
1202
|
"languages": ["typescript", "javascript"],
|
|
1079
|
-
"analyzer": "
|
|
1203
|
+
"analyzer": "./rules/security/S052_weak_otp_entropy/analyzer.js",
|
|
1204
|
+
"config": "./rules/security/S052_weak_otp_entropy/config.json",
|
|
1080
1205
|
"eslintRule": "custom/typescript_s052",
|
|
1081
1206
|
"version": "1.0.0",
|
|
1082
1207
|
"status": "stable",
|
|
1083
|
-
"tags": ["security", "
|
|
1208
|
+
"tags": ["security", "otp", "entropy", "csprng"],
|
|
1209
|
+
"engines": {
|
|
1210
|
+
"eslint": ["custom/typescript_s052"],
|
|
1211
|
+
"heuristic": ["./rules/security/S052_weak_otp_entropy/analyzer.js"]
|
|
1212
|
+
}
|
|
1084
1213
|
},
|
|
1085
1214
|
"S054": {
|
|
1086
|
-
"name": "
|
|
1087
|
-
"description": "
|
|
1215
|
+
"name": "Disallow Default/Built-in Accounts (admin/root/sa/...)",
|
|
1216
|
+
"description": "Prevent use of default or shared accounts. Enforce per-user identities, initial password change, and disabling well-known built-ins.",
|
|
1088
1217
|
"category": "security",
|
|
1089
1218
|
"severity": "error",
|
|
1090
|
-
"languages": [
|
|
1091
|
-
|
|
1219
|
+
"languages": [
|
|
1220
|
+
"typescript",
|
|
1221
|
+
"javascript",
|
|
1222
|
+
"sql",
|
|
1223
|
+
"terraform",
|
|
1224
|
+
"yaml",
|
|
1225
|
+
"dockerfile",
|
|
1226
|
+
"all"
|
|
1227
|
+
],
|
|
1228
|
+
"analyzer": "./rules/security/S054_no_default_accounts/analyzer.js",
|
|
1229
|
+
"config": "./rules/security/S054_no_default_accounts/config.json",
|
|
1092
1230
|
"eslintRule": "custom/typescript_s054",
|
|
1093
1231
|
"version": "1.0.0",
|
|
1094
1232
|
"status": "stable",
|
|
1095
|
-
"tags": [
|
|
1233
|
+
"tags": [
|
|
1234
|
+
"security",
|
|
1235
|
+
"accounts",
|
|
1236
|
+
"default",
|
|
1237
|
+
"authentication",
|
|
1238
|
+
"authorization"
|
|
1239
|
+
],
|
|
1240
|
+
"engines": {
|
|
1241
|
+
"eslint": ["custom/typescript_s054"],
|
|
1242
|
+
"heuristic": ["./rules/security/S054_no_default_accounts/analyzer.js"]
|
|
1243
|
+
}
|
|
1096
1244
|
},
|
|
1097
1245
|
"S055": {
|
|
1098
1246
|
"name": "REST Content-Type Verification",
|
|
@@ -1106,6 +1254,31 @@
|
|
|
1106
1254
|
"status": "stable",
|
|
1107
1255
|
"tags": ["security", "rest", "content-type"]
|
|
1108
1256
|
},
|
|
1257
|
+
"S056": {
|
|
1258
|
+
"name": "Protect against Log Injection attacks",
|
|
1259
|
+
"description": "Protect against Log Injection attacks. Log injection occurs when user-controlled data is written to log files without proper sanitization, potentially allowing attackers to manipulate log entries, inject malicious content, or exploit log processing systems.",
|
|
1260
|
+
"category": "security",
|
|
1261
|
+
"severity": "error",
|
|
1262
|
+
"languages": ["typescript", "javascript"],
|
|
1263
|
+
"analyzer": "./rules/security/S056_log_injection_protection/analyzer.js",
|
|
1264
|
+
"config": "./rules/security/S056_log_injection_protection/config.json",
|
|
1265
|
+
"version": "1.0.0",
|
|
1266
|
+
"status": "stable",
|
|
1267
|
+
"tags": ["security", "logging", "injection", "owasp", "crlf"],
|
|
1268
|
+
"strategy": {
|
|
1269
|
+
"preferred": "ast",
|
|
1270
|
+
"fallbacks": ["ast", "regex"],
|
|
1271
|
+
"accuracy": {
|
|
1272
|
+
"ast": 95,
|
|
1273
|
+
"regex": 85
|
|
1274
|
+
}
|
|
1275
|
+
},
|
|
1276
|
+
"engineMappings": {
|
|
1277
|
+
"heuristic": [
|
|
1278
|
+
"rules/security/S056_log_injection_protection/analyzer.js"
|
|
1279
|
+
]
|
|
1280
|
+
}
|
|
1281
|
+
},
|
|
1109
1282
|
"S057": {
|
|
1110
1283
|
"name": "Log with UTC Timestamps",
|
|
1111
1284
|
"description": "Ensure all logs use synchronized UTC time with ISO 8601/RFC3339 format to avoid timezone discrepancies across systems",
|
|
@@ -1353,7 +1526,13 @@
|
|
|
1353
1526
|
"config": "./rules/common/C067_no_hardcoded_config/config.json",
|
|
1354
1527
|
"version": "1.0.0",
|
|
1355
1528
|
"status": "stable",
|
|
1356
|
-
"tags": [
|
|
1529
|
+
"tags": [
|
|
1530
|
+
"configuration",
|
|
1531
|
+
"hardcode",
|
|
1532
|
+
"environment",
|
|
1533
|
+
"maintainability",
|
|
1534
|
+
"security"
|
|
1535
|
+
],
|
|
1357
1536
|
"strategy": {
|
|
1358
1537
|
"preferred": "ast",
|
|
1359
1538
|
"fallbacks": ["ast"],
|
|
@@ -1375,7 +1554,13 @@
|
|
|
1375
1554
|
"config": "../rules/common/C070_no_real_time_tests/config.json",
|
|
1376
1555
|
"version": "1.0.0",
|
|
1377
1556
|
"status": "stable",
|
|
1378
|
-
"tags": [
|
|
1557
|
+
"tags": [
|
|
1558
|
+
"testing",
|
|
1559
|
+
"flaky-tests",
|
|
1560
|
+
"timing",
|
|
1561
|
+
"fake-timers",
|
|
1562
|
+
"reliability"
|
|
1563
|
+
],
|
|
1379
1564
|
"strategy": {
|
|
1380
1565
|
"preferred": "ast",
|
|
1381
1566
|
"fallbacks": ["regex"],
|
|
@@ -1385,7 +1570,9 @@
|
|
|
1385
1570
|
}
|
|
1386
1571
|
},
|
|
1387
1572
|
"engineMappings": {
|
|
1388
|
-
"heuristic": [
|
|
1573
|
+
"heuristic": [
|
|
1574
|
+
"../rules/common/C070_no_real_time_tests/regex-analyzer.js"
|
|
1575
|
+
]
|
|
1389
1576
|
}
|
|
1390
1577
|
},
|
|
1391
1578
|
"C072": {
|
|
@@ -1419,8 +1606,12 @@
|
|
|
1419
1606
|
"status": "stable",
|
|
1420
1607
|
"tags": ["configuration", "validation", "startup", "fail-fast"],
|
|
1421
1608
|
"engineMappings": {
|
|
1422
|
-
"heuristic": [
|
|
1423
|
-
|
|
1609
|
+
"heuristic": [
|
|
1610
|
+
"rules/common/C073_validate_required_config_on_startup/analyzer.js"
|
|
1611
|
+
],
|
|
1612
|
+
"semantic": [
|
|
1613
|
+
"rules/common/C073_validate_required_config_on_startup/symbol-based-analyzer.js"
|
|
1614
|
+
]
|
|
1424
1615
|
},
|
|
1425
1616
|
"strategy": {
|
|
1426
1617
|
"preferred": "semantic",
|
|
@@ -1837,6 +2028,7 @@
|
|
|
1837
2028
|
"C047",
|
|
1838
2029
|
"C048",
|
|
1839
2030
|
"C052",
|
|
2031
|
+
"C065",
|
|
1840
2032
|
"C072",
|
|
1841
2033
|
"C073",
|
|
1842
2034
|
"C075",
|
|
@@ -1906,9 +2098,11 @@
|
|
|
1906
2098
|
"S047",
|
|
1907
2099
|
"S048",
|
|
1908
2100
|
"S050",
|
|
2101
|
+
"S051",
|
|
1909
2102
|
"S052",
|
|
1910
2103
|
"S054",
|
|
1911
2104
|
"S055",
|
|
2105
|
+
"S056",
|
|
1912
2106
|
"S057",
|
|
1913
2107
|
"S058"
|
|
1914
2108
|
],
|
|
@@ -2003,7 +2197,7 @@
|
|
|
2003
2197
|
"lastUpdated": "2025-08-25",
|
|
2004
2198
|
"totalRules": 98,
|
|
2005
2199
|
"qualityRules": 33,
|
|
2006
|
-
"securityRules":
|
|
2200
|
+
"securityRules": 51,
|
|
2007
2201
|
"stableRules": 45,
|
|
2008
2202
|
"experimentalRules": 1,
|
|
2009
2203
|
"supportedLanguages": 4,
|