@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.
Files changed (50) hide show
  1. package/CHANGELOG.md +76 -1
  2. package/config/defaults/default.json +2 -1
  3. package/config/rule-analysis-strategies.js +20 -0
  4. package/config/rules/enhanced-rules-registry.json +230 -43
  5. package/core/analysis-orchestrator.js +9 -5
  6. package/core/file-targeting-service.js +83 -7
  7. package/core/performance-optimizer.js +8 -2
  8. package/package.json +1 -1
  9. package/rules/common/C065_one_behavior_per_test/analyzer.js +851 -0
  10. package/rules/common/C065_one_behavior_per_test/config.json +95 -0
  11. package/rules/common/C073_validate_required_config_on_startup/README.md +110 -0
  12. package/rules/common/C073_validate_required_config_on_startup/analyzer.js +770 -0
  13. package/rules/common/C073_validate_required_config_on_startup/config.json +46 -0
  14. package/rules/common/C073_validate_required_config_on_startup/symbol-based-analyzer.js +370 -0
  15. package/rules/security/S037_cache_headers/README.md +128 -0
  16. package/rules/security/S037_cache_headers/analyzer.js +263 -0
  17. package/rules/security/S037_cache_headers/config.json +50 -0
  18. package/rules/security/S037_cache_headers/regex-based-analyzer.js +463 -0
  19. package/rules/security/S037_cache_headers/symbol-based-analyzer.js +546 -0
  20. package/rules/security/S038_no_version_headers/README.md +234 -0
  21. package/rules/security/S038_no_version_headers/analyzer.js +262 -0
  22. package/rules/security/S038_no_version_headers/config.json +49 -0
  23. package/rules/security/S038_no_version_headers/regex-based-analyzer.js +339 -0
  24. package/rules/security/S038_no_version_headers/symbol-based-analyzer.js +375 -0
  25. package/rules/security/S039_no_session_tokens_in_url/README.md +198 -0
  26. package/rules/security/S039_no_session_tokens_in_url/analyzer.js +262 -0
  27. package/rules/security/S039_no_session_tokens_in_url/config.json +92 -0
  28. package/rules/security/S039_no_session_tokens_in_url/regex-based-analyzer.js +337 -0
  29. package/rules/security/S039_no_session_tokens_in_url/symbol-based-analyzer.js +436 -0
  30. package/rules/security/S049_short_validity_tokens/analyzer.js +175 -0
  31. package/rules/security/S049_short_validity_tokens/config.json +124 -0
  32. package/rules/security/S049_short_validity_tokens/regex-based-analyzer.js +295 -0
  33. package/rules/security/S049_short_validity_tokens/symbol-based-analyzer.js +389 -0
  34. package/rules/security/S051_password_length_policy/analyzer.js +410 -0
  35. package/rules/security/S051_password_length_policy/config.json +83 -0
  36. package/rules/security/S052_weak_otp_entropy/analyzer.js +403 -0
  37. package/rules/security/S052_weak_otp_entropy/config.json +57 -0
  38. package/rules/security/S054_no_default_accounts/README.md +129 -0
  39. package/rules/security/S054_no_default_accounts/analyzer.js +792 -0
  40. package/rules/security/S054_no_default_accounts/config.json +101 -0
  41. package/rules/security/S056_log_injection_protection/analyzer.js +242 -0
  42. package/rules/security/S056_log_injection_protection/config.json +148 -0
  43. package/rules/security/S056_log_injection_protection/regex-based-analyzer.js +120 -0
  44. package/rules/security/S056_log_injection_protection/symbol-based-analyzer.js +287 -0
  45. package/rules/security/S057_utc_logging/README.md +152 -0
  46. package/rules/security/S057_utc_logging/analyzer.js +457 -0
  47. package/rules/security/S057_utc_logging/config.json +105 -0
  48. package/rules/security/S058_no_ssrf/README.md +180 -0
  49. package/rules/security/S058_no_ssrf/analyzer.js +403 -0
  50. package/rules/security/S058_no_ssrf/config.json +125 -0
package/CHANGELOG.md CHANGED
@@ -2,7 +2,82 @@
2
2
 
3
3
  ---
4
4
 
5
- ## ๐Ÿ”ง **v1.3.6 - C067 False Positive Reduction (September 8, 2025)**
5
+ ## ๐Ÿงช **v1.3.8 - C065 Rule Enhancement & Advanced Context Analysis (October 1, 2025)**
6
+
7
+ **Release Date**: October 1, 2025
8
+ **Type**: Major Enhancement
9
+ **Branch**: `feature.sunlint.heuristic_rule_c065`
10
+
11
+ ### โœจ **Major Features**
12
+ - **ENHANCED**: C065 "One Behavior per Test" Rule with Advanced Context Analysis
13
+ - **New**: UI Workflow Detection for legitimate testing patterns
14
+ - **New**: UI Interaction Loop Detection (fireEvent iterations)
15
+ - **New**: Smart Control Flow Analysis with UI pattern exclusions
16
+ - **New**: Assertion context grouping for accurate behavior detection
17
+ - **ENHANCED**: File Targeting System with Smart Test Detection
18
+ - **Performance**: 98% file reduction (6873 โ†’ 112 files) with `--include-tests`
19
+ - **Accuracy**: Intelligent project targeting and language filter override
20
+ - **ENHANCED**: Debug Output Management
21
+ - **Clean**: Production-ready output with conditional debug logging
22
+ - **Detailed**: Comprehensive debug info available with `--verbose` flag
23
+
24
+ ### ๐Ÿ› **Critical Bug Fixes**
25
+ - **FIXED**: C065 Rule Registry and Configuration
26
+ - **Issue**: Rule loading from incorrect `rules/quality/` path
27
+ - **Solution**: Updated to correct `rules/common/` path with proper categorization
28
+ - **FIXED**: False Positive Control Flow Detection
29
+ - **Issue**: UI testing loops incorrectly flagged as violations
30
+ - **Solution**: Pattern recognition for legitimate UI element iteration
31
+ - **FIXED**: Test File Language Filtering
32
+ - **Issue**: Test files excluded by language patterns
33
+ - **Solution**: Override exclusions for `--include-tests` flag
34
+
35
+ ### ๐ŸŽฏ **Rule Accuracy Validation**
36
+ - **UI Loops**: `for (const checkbox of listCheckbox) { fireEvent.click(checkbox); }` โœ… No false positive
37
+ - **Button Iteration**: `for (const button of buttons) { fireEvent.click(button); }` โœ… No false positive
38
+ - **Business Logic**: Complex control flow with if/else statements โŒ Properly flagged
39
+ - **Multiple Behaviors**: Tests with multiple mock setups โŒ Properly flagged
40
+
41
+ ---
42
+
43
+ ## ๏ฟฝ **v1.3.7 - File Count Reporting & Performance Fixes (September 11, 2025)**
44
+
45
+ **Release Date**: September 11, 2025
46
+ **Type**: Bug Fix & Enhancement
47
+ **Branch**: `fix.sunlint.report`
48
+
49
+ ### ๐Ÿ› **Critical Bug Fixes**
50
+ - **FIXED**: File count reporting accuracy in summary
51
+ - **Issue**: Summary showed incorrect file counts when performance filtering applied
52
+ - **Before**: `Files loaded: 1322` but summary `Files: 1000` (misleading)
53
+ - **After**: Summary accurately reflects files actually analyzed
54
+ - **FIXED**: File count multiplication in batch processing
55
+ - **Issue**: Multiple batches incorrectly accumulated file counts
56
+ - **Before**: 1322 files โ†’ reported as 3000 files in batched analysis
57
+ - **After**: Consistent file count regardless of batch strategy
58
+
59
+ ### โšก **Performance Enhancements**
60
+ - **ENHANCED**: `--max-files=-1` unlimited file processing
61
+ - **Issue**: `-1` flag was ignored, still limited to 1000 files
62
+ - **Solution**: Proper unlimited file processing support
63
+ - **Usage**: `sunlint --max-files=-1` now analyzes all files without limits
64
+
65
+ ### ๐ŸŽฏ **Rule Improvements**
66
+ - **ENHANCED**: S057 UTC Logging rule precision (100% accuracy)
67
+ - Fixed false positive detection for `pino.stdTimeFunctions.isoTime`
68
+ - Added timezone indicator support: `'Z'`, `"Z"`, `+00:00`, `.l'Z'`
69
+ - Enhanced config variable tracing for complex logging setups
70
+ - Cleaned up test fixtures and moved to proper location
71
+
72
+ ### ๐Ÿ“Š **Validation Results**
73
+ - **File Processing**: `--max-files=-1` โ†’ 1322 files analyzed โœ…
74
+ - **Limited Analysis**: `--max-files=500` โ†’ 500 files analyzed โœ…
75
+ - **Batch Analysis**: Multi-rule analysis maintains accurate counts โœ…
76
+ - **S057 Precision**: 0 false positives on real projects โœ…
77
+
78
+ ---
79
+
80
+ ## ๏ฟฝ๐Ÿ”ง **v1.3.6 - C067 False Positive Reduction (September 8, 2025)**
6
81
 
7
82
  **Release Date**: September 8, 2025
8
83
  **Type**: Bug Fix & Improvement
@@ -3,7 +3,8 @@
3
3
  "C006": true,
4
4
  "C019": true,
5
5
  "C032": true,
6
- "C045": true
6
+ "C045": true,
7
+ "S054": true
7
8
  },
8
9
  "categories": ["quality", "security"],
9
10
  "integration": {
@@ -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
 
@@ -736,7 +736,13 @@
736
736
  "config": "./rules/security/S025_server_side_validation/config.json",
737
737
  "version": "1.0.0",
738
738
  "status": "stable",
739
- "tags": ["security", "validation", "server-side", "owasp", "input-validation"],
739
+ "tags": [
740
+ "security",
741
+ "validation",
742
+ "server-side",
743
+ "owasp",
744
+ "input-validation"
745
+ ],
740
746
  "strategy": {
741
747
  "preferred": "ast",
742
748
  "fallbacks": ["ast", "regex"],
@@ -927,40 +933,71 @@
927
933
  "tags": ["security", "file-inclusion", "path-traversal"]
928
934
  },
929
935
  "S037": {
930
- "name": "Require Anti Cache Headers",
931
- "description": "Require anti-cache headers for sensitive content",
936
+ "name": "Configure comprehensive cache headers to prevent sensitive data leakage",
937
+ "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
938
  "category": "security",
933
939
  "severity": "warning",
934
940
  "languages": ["typescript", "javascript"],
935
- "analyzer": "eslint",
936
- "eslintRule": "custom/typescript_s037",
941
+ "analyzer": "./rules/security/S037_cache_headers/analyzer.js",
942
+ "config": "./rules/security/S037_cache_headers/config.json",
937
943
  "version": "1.0.0",
938
- "status": "stable",
939
- "tags": ["security", "caching", "headers"]
944
+ "status": "experimental",
945
+ "tags": ["security", "caching", "headers", "privacy"],
946
+ "strategy": {
947
+ "preferred": "ast",
948
+ "fallbacks": ["ast", "regex"],
949
+ "accuracy": { "ast": 90, "regex": 75 }
950
+ },
951
+ "engineMappings": {
952
+ "heuristic": ["rules/security/S037_cache_headers/analyzer.js"]
953
+ }
940
954
  },
941
955
  "S038": {
942
- "name": "No Version Disclosure",
943
- "description": "Prevent version information disclosure",
956
+ "name": "Do not expose version information in response headers",
957
+ "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
958
  "category": "security",
945
959
  "severity": "warning",
946
960
  "languages": ["typescript", "javascript"],
947
- "analyzer": "eslint",
948
- "eslintRule": "custom/typescript_s038",
961
+ "analyzer": "./rules/security/S038_no_version_headers/analyzer.js",
962
+ "config": "./rules/security/S038_no_version_headers/config.json",
949
963
  "version": "1.0.0",
950
- "status": "stable",
951
- "tags": ["security", "information-disclosure", "version"]
964
+ "status": "experimental",
965
+ "tags": ["security", "information-disclosure", "version", "headers"],
966
+ "strategy": {
967
+ "preferred": "ast",
968
+ "fallbacks": ["ast", "regex"],
969
+ "accuracy": { "ast": 90, "regex": 75 }
970
+ },
971
+ "engineMappings": {
972
+ "heuristic": ["rules/security/S038_no_version_headers/analyzer.js"]
973
+ }
952
974
  },
953
975
  "S039": {
954
- "name": "No Session Token in URL",
955
- "description": "Prevent session tokens in URL parameters",
976
+ "name": "Do not pass Session Tokens via URL parameters",
977
+ "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
978
  "category": "security",
957
- "severity": "error",
979
+ "severity": "warning",
958
980
  "languages": ["typescript", "javascript"],
959
- "analyzer": "eslint",
960
- "eslintRule": "custom/typescript_s039",
981
+ "analyzer": "./rules/security/S039_no_session_tokens_in_url/analyzer.js",
982
+ "config": "./rules/security/S039_no_session_tokens_in_url/config.json",
961
983
  "version": "1.0.0",
962
- "status": "stable",
963
- "tags": ["security", "session", "url"]
984
+ "status": "experimental",
985
+ "tags": [
986
+ "security",
987
+ "session-tokens",
988
+ "url-parameters",
989
+ "authentication"
990
+ ],
991
+ "strategy": {
992
+ "preferred": "ast",
993
+ "fallbacks": ["ast", "regex"],
994
+ "accuracy": { "ast": 85, "regex": 70 }
995
+ },
996
+ "engineMappings": {
997
+ "heuristic": [
998
+ "rules/security/S039_no_session_tokens_in_url/analyzer.js"
999
+ ]
1000
+ }
964
1001
  },
965
1002
  "S041": {
966
1003
  "name": "Require Session Invalidate on Logout",
@@ -1058,6 +1095,36 @@
1058
1095
  "status": "stable",
1059
1096
  "tags": ["security", "password", "recovery"]
1060
1097
  },
1098
+ "S049": {
1099
+ "name": "Authentication tokens should have short validity periods",
1100
+ "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.",
1101
+ "category": "security",
1102
+ "severity": "error",
1103
+ "languages": ["typescript", "javascript"],
1104
+ "analyzer": "./rules/security/S049_short_validity_tokens/analyzer.js",
1105
+ "config": "./rules/security/S049_short_validity_tokens/config.json",
1106
+ "version": "1.0.0",
1107
+ "status": "stable",
1108
+ "tags": [
1109
+ "security",
1110
+ "authentication",
1111
+ "tokens",
1112
+ "jwt",
1113
+ "session",
1114
+ "owasp"
1115
+ ],
1116
+ "strategy": {
1117
+ "preferred": "ast",
1118
+ "fallbacks": ["ast", "regex"],
1119
+ "accuracy": {
1120
+ "ast": 90,
1121
+ "regex": 75
1122
+ }
1123
+ },
1124
+ "engineMappings": {
1125
+ "heuristic": ["rules/security/S049_short_validity_tokens/analyzer.js"]
1126
+ }
1127
+ },
1061
1128
  "S050": {
1062
1129
  "name": "Session Token Weak Hash",
1063
1130
  "description": "Prevent weak hashing for session tokens",
@@ -1070,29 +1137,71 @@
1070
1137
  "status": "stable",
1071
1138
  "tags": ["security", "session", "hashing"]
1072
1139
  },
1140
+ "S051": {
1141
+ "name": "Password length policy enforcement (12-64 chars recommended, reject >128)",
1142
+ "description": "Enforce strong password length policies with multi-signal detection. Prevent weak validators, missing limits, and FE/BE mismatches.",
1143
+ "category": "security",
1144
+ "severity": "error",
1145
+ "languages": ["typescript", "javascript"],
1146
+ "analyzer": "./rules/security/S051_password_length_policy/analyzer.js",
1147
+ "config": "./rules/security/S051_password_length_policy/config.json",
1148
+ "eslintRule": "custom/typescript_s051",
1149
+ "version": "1.0.0",
1150
+ "status": "stable",
1151
+ "tags": ["security", "password", "validation", "length", "policy"],
1152
+ "engineMappings": {
1153
+ "eslint": ["custom/typescript_s051"],
1154
+ "heuristic": ["./rules/security/S051_password_length_policy/analyzer.js"]
1155
+ }
1156
+ },
1157
+ "C065": {
1158
+ "name": "One Behavior per Test (AAA Pattern)",
1159
+ "description": "Enforce single behavior testing - each test should verify exactly one action/behavior with clear Arrange-Act-Assert structure",
1160
+ "category": "common",
1161
+ "severity": "warning",
1162
+ "languages": ["typescript", "javascript", "java", "csharp", "swift", "kotlin", "python"],
1163
+ "analyzer": "./rules/common/C065_one_behavior_per_test/analyzer.js",
1164
+ "config": "./rules/common/C065_one_behavior_per_test/config.json",
1165
+ "version": "1.0.0",
1166
+ "status": "stable",
1167
+ "tags": ["testing", "aaa", "behavior", "maintainability", "clarity"],
1168
+ "engineMappings": {
1169
+ "heuristic": ["./rules/common/C065_one_behavior_per_test/analyzer.js"]
1170
+ }
1171
+ },
1073
1172
  "S052": {
1074
- "name": "Secure Random Authentication Code",
1075
- "description": "Require secure random number generation for authentication codes",
1173
+ "name": "OTP must have โ‰ฅ20-bit entropy (โ‰ฅ6 digits) and use CSPRNG",
1174
+ "description": "Prevent guessable OTP by enforcing CSPRNG and minimal entropy. Ban non-crypto RNG and too-short codes.",
1076
1175
  "category": "security",
1077
1176
  "severity": "error",
1078
1177
  "languages": ["typescript", "javascript"],
1079
- "analyzer": "eslint",
1178
+ "analyzer": "./rules/security/S052_weak_otp_entropy/analyzer.js",
1179
+ "config": "./rules/security/S052_weak_otp_entropy/config.json",
1080
1180
  "eslintRule": "custom/typescript_s052",
1081
1181
  "version": "1.0.0",
1082
1182
  "status": "stable",
1083
- "tags": ["security", "random", "authentication"]
1183
+ "tags": ["security", "otp", "entropy", "csprng"],
1184
+ "engines": {
1185
+ "eslint": ["custom/typescript_s052"],
1186
+ "heuristic": ["./rules/security/S052_weak_otp_entropy/analyzer.js"]
1187
+ }
1084
1188
  },
1085
1189
  "S054": {
1086
- "name": "Verification Default Account",
1087
- "description": "Verify and secure default accounts",
1190
+ "name": "Disallow Default/Built-in Accounts (admin/root/sa/...)",
1191
+ "description": "Prevent use of default or shared accounts. Enforce per-user identities, initial password change, and disabling well-known built-ins.",
1088
1192
  "category": "security",
1089
1193
  "severity": "error",
1090
- "languages": ["typescript", "javascript"],
1091
- "analyzer": "eslint",
1194
+ "languages": ["typescript", "javascript", "sql", "terraform", "yaml", "dockerfile", "all"],
1195
+ "analyzer": "./rules/security/S054_no_default_accounts/analyzer.js",
1196
+ "config": "./rules/security/S054_no_default_accounts/config.json",
1092
1197
  "eslintRule": "custom/typescript_s054",
1093
1198
  "version": "1.0.0",
1094
1199
  "status": "stable",
1095
- "tags": ["security", "accounts", "default"]
1200
+ "tags": ["security", "accounts", "default", "authentication", "authorization"],
1201
+ "engines": {
1202
+ "eslint": ["custom/typescript_s054"],
1203
+ "heuristic": ["./rules/security/S054_no_default_accounts/analyzer.js"]
1204
+ }
1096
1205
  },
1097
1206
  "S055": {
1098
1207
  "name": "REST Content-Type Verification",
@@ -1106,29 +1215,62 @@
1106
1215
  "status": "stable",
1107
1216
  "tags": ["security", "rest", "content-type"]
1108
1217
  },
1218
+ "S056": {
1219
+ "name": "Protect against Log Injection attacks",
1220
+ "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.",
1221
+ "category": "security",
1222
+ "severity": "error",
1223
+ "languages": ["typescript", "javascript"],
1224
+ "analyzer": "./rules/security/S056_log_injection_protection/analyzer.js",
1225
+ "config": "./rules/security/S056_log_injection_protection/config.json",
1226
+ "version": "1.0.0",
1227
+ "status": "stable",
1228
+ "tags": ["security", "logging", "injection", "owasp", "crlf"],
1229
+ "strategy": {
1230
+ "preferred": "ast",
1231
+ "fallbacks": ["ast", "regex"],
1232
+ "accuracy": {
1233
+ "ast": 95,
1234
+ "regex": 85
1235
+ }
1236
+ },
1237
+ "engineMappings": {
1238
+ "heuristic": [
1239
+ "rules/security/S056_log_injection_protection/analyzer.js"
1240
+ ]
1241
+ }
1242
+ },
1109
1243
  "S057": {
1110
- "name": "UTC Logging",
1111
- "description": "Enforce UTC usage in time formatting and logging",
1244
+ "name": "Log with UTC Timestamps",
1245
+ "description": "Ensure all logs use synchronized UTC time with ISO 8601/RFC3339 format to avoid timezone discrepancies across systems",
1112
1246
  "category": "security",
1113
1247
  "severity": "warning",
1114
1248
  "languages": ["typescript", "javascript"],
1115
- "analyzer": "eslint",
1116
- "eslintRule": "custom/typescript_s057",
1249
+ "analyzer": "./rules/security/S057_utc_logging/analyzer.js",
1250
+ "config": "./rules/security/S057_utc_logging/config.json",
1117
1251
  "version": "1.0.0",
1118
1252
  "status": "stable",
1119
- "tags": ["security", "logging", "timezone"]
1253
+ "tags": ["security", "logging", "timezone", "utc"],
1254
+ "engineMappings": {
1255
+ "eslint": ["custom/typescript_s057"],
1256
+ "heuristic": ["./rules/security/S057_utc_logging/analyzer.js"]
1257
+ }
1120
1258
  },
1121
1259
  "S058": {
1122
- "name": "No SSRF",
1123
- "description": "Detect SSRF vulnerabilities via unvalidated user-controlled URLs",
1260
+ "name": "No SSRF (Server-Side Request Forgery)",
1261
+ "description": "Prevent SSRF attacks by validating URLs from user input before making HTTP requests",
1124
1262
  "category": "security",
1125
1263
  "severity": "error",
1126
1264
  "languages": ["typescript", "javascript"],
1127
- "analyzer": "eslint",
1128
- "eslintRule": "custom/typescript_s058",
1265
+ "analyzer": "./rules/security/S058_no_ssrf/analyzer.js",
1266
+ "config": "./rules/security/S058_no_ssrf/config.json",
1129
1267
  "version": "1.0.0",
1130
1268
  "status": "stable",
1131
- "tags": ["security", "ssrf", "url-validation"]
1269
+ "tags": ["security", "ssrf", "url-validation", "http-requests"],
1270
+ "engineMappings": {
1271
+ "heuristic": ["./rules/security/S058_no_ssrf/analyzer.js"],
1272
+ "eslint": ["custom/typescript_s058"]
1273
+ }
1132
1274
  },
1133
1275
  "C002": {
1134
1276
  "id": "C002",
@@ -1345,7 +1487,13 @@
1345
1487
  "config": "./rules/common/C067_no_hardcoded_config/config.json",
1346
1488
  "version": "1.0.0",
1347
1489
  "status": "stable",
1348
- "tags": ["configuration", "hardcode", "environment", "maintainability", "security"],
1490
+ "tags": [
1491
+ "configuration",
1492
+ "hardcode",
1493
+ "environment",
1494
+ "maintainability",
1495
+ "security"
1496
+ ],
1349
1497
  "strategy": {
1350
1498
  "preferred": "ast",
1351
1499
  "fallbacks": ["ast"],
@@ -1367,7 +1515,13 @@
1367
1515
  "config": "../rules/common/C070_no_real_time_tests/config.json",
1368
1516
  "version": "1.0.0",
1369
1517
  "status": "stable",
1370
- "tags": ["testing", "flaky-tests", "timing", "fake-timers", "reliability"],
1518
+ "tags": [
1519
+ "testing",
1520
+ "flaky-tests",
1521
+ "timing",
1522
+ "fake-timers",
1523
+ "reliability"
1524
+ ],
1371
1525
  "strategy": {
1372
1526
  "preferred": "ast",
1373
1527
  "fallbacks": ["regex"],
@@ -1377,7 +1531,9 @@
1377
1531
  }
1378
1532
  },
1379
1533
  "engineMappings": {
1380
- "heuristic": ["../rules/common/C070_no_real_time_tests/regex-analyzer.js"]
1534
+ "heuristic": [
1535
+ "../rules/common/C070_no_real_time_tests/regex-analyzer.js"
1536
+ ]
1381
1537
  }
1382
1538
  },
1383
1539
  "C072": {
@@ -1400,6 +1556,33 @@
1400
1556
  "accuracy": {}
1401
1557
  }
1402
1558
  },
1559
+ "C073": {
1560
+ "id": "C073",
1561
+ "name": "Validate Required Configuration on Startup",
1562
+ "description": "C073 - Validate mandatory configuration at startup and fail fast on invalid/missing values",
1563
+ "category": "configuration",
1564
+ "severity": "error",
1565
+ "languages": ["typescript", "javascript", "java", "go"],
1566
+ "version": "1.0.0",
1567
+ "status": "stable",
1568
+ "tags": ["configuration", "validation", "startup", "fail-fast"],
1569
+ "engineMappings": {
1570
+ "heuristic": [
1571
+ "rules/common/C073_validate_required_config_on_startup/analyzer.js"
1572
+ ],
1573
+ "semantic": [
1574
+ "rules/common/C073_validate_required_config_on_startup/symbol-based-analyzer.js"
1575
+ ]
1576
+ },
1577
+ "strategy": {
1578
+ "preferred": "semantic",
1579
+ "fallbacks": ["heuristic"],
1580
+ "accuracy": {
1581
+ "semantic": 0.9,
1582
+ "heuristic": 0.7
1583
+ }
1584
+ }
1585
+ },
1403
1586
  "C075": {
1404
1587
  "id": "C075",
1405
1588
  "name": "Rule C075",
@@ -1806,7 +1989,9 @@
1806
1989
  "C047",
1807
1990
  "C048",
1808
1991
  "C052",
1992
+ "C065",
1809
1993
  "C072",
1994
+ "C073",
1810
1995
  "C075",
1811
1996
  "T002",
1812
1997
  "T003",
@@ -1874,9 +2059,11 @@
1874
2059
  "S047",
1875
2060
  "S048",
1876
2061
  "S050",
2062
+ "S051",
1877
2063
  "S052",
1878
2064
  "S054",
1879
2065
  "S055",
2066
+ "S056",
1880
2067
  "S057",
1881
2068
  "S058"
1882
2069
  ],
@@ -1971,7 +2158,7 @@
1971
2158
  "lastUpdated": "2025-08-25",
1972
2159
  "totalRules": 98,
1973
2160
  "qualityRules": 33,
1974
- "securityRules": 50,
2161
+ "securityRules": 51,
1975
2162
  "stableRules": 45,
1976
2163
  "experimentalRules": 1,
1977
2164
  "supportedLanguages": 4,
@@ -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
- mergedResults.summary.engines[engineName].files += engineResult.filesAnalyzed || 0;
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
  }