@sun-asterisk/sunlint 1.2.2 → 1.3.1

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 (124) hide show
  1. package/CHANGELOG.md +107 -1
  2. package/CONTRIBUTING.md +1654 -66
  3. package/README.md +19 -6
  4. package/config/ci-cd.json +54 -0
  5. package/config/development.json +56 -0
  6. package/config/engines/engines-enhanced.json +86 -0
  7. package/config/engines/semantic-config.json +114 -0
  8. package/config/eslint-rule-mapping.json +50 -38
  9. package/config/large-project.json +143 -0
  10. package/config/presets/all.json +0 -1
  11. package/config/release.json +70 -0
  12. package/config/rule-analysis-strategies.js +23 -4
  13. package/config/rules/S027-categories.json +122 -0
  14. package/config/rules/enhanced-rules-registry.json +2564 -0
  15. package/config/rules/rules-registry-generated.json +785 -837
  16. package/config/rules/rules-registry.json +13 -1
  17. package/core/adapters/sunlint-rule-adapter.js +25 -30
  18. package/core/analysis-orchestrator.js +42 -2
  19. package/core/categories.js +52 -0
  20. package/core/category-constants.js +39 -0
  21. package/core/cli-action-handler.js +53 -32
  22. package/core/cli-program.js +11 -3
  23. package/core/config-manager.js +111 -0
  24. package/core/config-merger.js +88 -0
  25. package/core/constants/categories.js +168 -0
  26. package/core/constants/defaults.js +165 -0
  27. package/core/constants/engines.js +185 -0
  28. package/core/constants/index.js +30 -0
  29. package/core/constants/rules.js +215 -0
  30. package/core/enhanced-rules-registry.js +3 -3
  31. package/core/file-targeting-service.js +128 -7
  32. package/core/interfaces/rule-plugin.interface.js +207 -0
  33. package/core/plugin-manager.js +448 -0
  34. package/core/rule-selection-service.js +42 -15
  35. package/core/semantic-engine.js +658 -0
  36. package/core/semantic-rule-base.js +433 -0
  37. package/core/unified-rule-registry.js +484 -0
  38. package/docs/COMMAND-EXAMPLES.md +134 -0
  39. package/docs/CONSTANTS-ARCHITECTURE.md +288 -0
  40. package/docs/LARGE-PROJECT-GUIDE.md +324 -0
  41. package/engines/core/base-engine.js +249 -0
  42. package/engines/engine-factory.js +275 -0
  43. package/engines/eslint-engine.js +171 -19
  44. package/engines/heuristic-engine.js +569 -78
  45. package/integrations/eslint/plugin/index.js +26 -28
  46. package/origin-rules/common-en.md +8 -8
  47. package/package.json +10 -6
  48. package/rules/common/C003_no_vague_abbreviations/analyzer.js +1 -1
  49. package/rules/common/C017_constructor_logic/analyzer.js +254 -17
  50. package/rules/common/C017_constructor_logic/semantic-analyzer.js +340 -0
  51. package/rules/common/C029_catch_block_logging/analyzer.js +17 -5
  52. package/rules/common/C033_separate_service_repository/README.md +78 -0
  53. package/rules/common/C033_separate_service_repository/analyzer.js +160 -0
  54. package/rules/common/C033_separate_service_repository/config.json +50 -0
  55. package/rules/common/C033_separate_service_repository/regex-based-analyzer.js +585 -0
  56. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +368 -0
  57. package/rules/common/C035_error_logging_context/STRATEGY.md +99 -0
  58. package/rules/common/C035_error_logging_context/analyzer.js +230 -0
  59. package/rules/common/C035_error_logging_context/config.json +54 -0
  60. package/rules/common/C035_error_logging_context/regex-based-analyzer.js +299 -0
  61. package/rules/common/C035_error_logging_context/symbol-based-analyzer.js +454 -0
  62. package/rules/common/C040_centralized_validation/analyzer.js +165 -0
  63. package/rules/common/C040_centralized_validation/config.json +46 -0
  64. package/rules/common/C040_centralized_validation/regex-based-analyzer.js +243 -0
  65. package/rules/common/C040_centralized_validation/symbol-based-analyzer.js +416 -0
  66. package/rules/common/C047_no_duplicate_retry_logic/c047-semantic-rule.js +278 -0
  67. package/rules/common/C047_no_duplicate_retry_logic/symbol-analyzer-enhanced.js +968 -0
  68. package/rules/common/C047_no_duplicate_retry_logic/symbol-config.json +71 -0
  69. package/rules/common/{C076_single_test_behavior → C072_single_test_behavior}/analyzer.js +6 -6
  70. package/rules/common/C076_explicit_function_types/README.md +30 -0
  71. package/rules/common/C076_explicit_function_types/analyzer.js +172 -0
  72. package/rules/common/C076_explicit_function_types/config.json +15 -0
  73. package/rules/common/C076_explicit_function_types/semantic-analyzer.js +341 -0
  74. package/rules/index.js +8 -0
  75. package/rules/parser/rule-parser.js +13 -2
  76. package/rules/security/S005_no_origin_auth/README.md +226 -0
  77. package/rules/security/S005_no_origin_auth/analyzer.js +184 -0
  78. package/rules/security/S005_no_origin_auth/ast-analyzer.js +406 -0
  79. package/rules/security/S005_no_origin_auth/config.json +85 -0
  80. package/rules/security/S006_no_plaintext_recovery_codes/README.md +139 -0
  81. package/rules/security/S006_no_plaintext_recovery_codes/analyzer.js +306 -0
  82. package/rules/security/S006_no_plaintext_recovery_codes/config.json +48 -0
  83. package/rules/security/S007_no_plaintext_otp/README.md +198 -0
  84. package/rules/security/S007_no_plaintext_otp/analyzer.js +406 -0
  85. package/rules/security/S007_no_plaintext_otp/config.json +79 -0
  86. package/rules/security/S007_no_plaintext_otp/semantic-analyzer.js +609 -0
  87. package/rules/security/S007_no_plaintext_otp/semantic-config.json +195 -0
  88. package/rules/security/S007_no_plaintext_otp/semantic-wrapper.js +280 -0
  89. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +180 -366
  90. package/rules/security/S027_no_hardcoded_secrets/categories.json +153 -0
  91. package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +250 -0
  92. package/scripts/category-manager.js +150 -0
  93. package/scripts/generate-rules-registry.js +88 -0
  94. package/scripts/migrate-rule-registry.js +157 -0
  95. package/scripts/prepare-release.sh +1 -1
  96. package/scripts/validate-system.js +48 -0
  97. package/.sunlint.json +0 -35
  98. package/config/README.md +0 -88
  99. package/config/engines/eslint-rule-mapping.json +0 -74
  100. package/config/schemas/sunlint-schema.json +0 -0
  101. package/config/testing/test-s005-working.ts +0 -22
  102. package/core/multi-rule-runner.js +0 -0
  103. package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
  104. package/docs/FUTURE_PACKAGES.md +0 -83
  105. package/docs/HEURISTIC_VS_AI.md +0 -113
  106. package/docs/PRODUCTION_DEPLOYMENT_ANALYSIS.md +0 -112
  107. package/docs/PRODUCTION_SIZE_IMPACT.md +0 -183
  108. package/docs/RELEASE_GUIDE.md +0 -230
  109. package/docs/STANDARDIZED-CATEGORY-FILTERING.md +0 -156
  110. package/engines/tree-sitter-parser.js +0 -0
  111. package/engines/universal-ast-engine.js +0 -0
  112. package/integrations/eslint/plugin/rules/common/c076-single-behavior-per-test.js +0 -254
  113. package/rules/common/C029_catch_block_logging/analyzer-backup.js +0 -426
  114. package/rules/common/C029_catch_block_logging/analyzer-fixed.js +0 -130
  115. package/rules/common/C029_catch_block_logging/analyzer-multi-tech.js +0 -487
  116. package/rules/common/C029_catch_block_logging/analyzer-simple.js +0 -110
  117. package/rules/common/C029_catch_block_logging/ast-analyzer-backup.js +0 -441
  118. package/rules/common/C029_catch_block_logging/ast-analyzer-new.js +0 -127
  119. package/rules/common/C029_catch_block_logging/ast-analyzer.js +0 -133
  120. package/rules/common/C029_catch_block_logging/cfg-analyzer.js +0 -408
  121. package/rules/common/C029_catch_block_logging/dataflow-analyzer.js +0 -454
  122. package/rules/common/C029_catch_block_logging/multi-language-ast-engine.js +0 -700
  123. package/rules/common/C029_catch_block_logging/pattern-learning-analyzer.js +0 -568
  124. package/rules/common/C029_catch_block_logging/semantic-analyzer.js +0 -459
@@ -221,8 +221,12 @@ class RuleParser {
221
221
  // Process lines with keywords
222
222
  processKeywordLine(line, rule, state) {
223
223
  if (this.containsKeyword(line, "OBJECTIVE")) {
224
- rule.description = this.extractValueAfterKeyword(line, "OBJECTIVE")
225
- this.resetParsingState(state)
224
+ state.currentSection = "objective"
225
+ const objectiveText = this.extractValueAfterKeyword(line, "OBJECTIVE")
226
+ if (objectiveText) {
227
+ rule.description = objectiveText
228
+ }
229
+ this.resetParsingFlags(state)
226
230
  } else if (this.containsKeyword(line, "DETAILS")) {
227
231
  state.currentSection = "details"
228
232
  const detailText = this.extractValueAfterKeyword(line, "DETAILS")
@@ -279,6 +283,13 @@ class RuleParser {
279
283
  state.currentSection = null
280
284
  state.currentConfigType = this.extractConfigType(line)
281
285
  console.log(`Found config section in rule ${rule.id}: ${line} (type: ${state.currentConfigType})`)
286
+ } else if (state.currentSection === "objective" && line.trim() && !line.trim().startsWith("**") && !line.trim().startsWith("-")) {
287
+ // Continue reading objective content on next lines
288
+ if (rule.description) {
289
+ rule.description += " " + line.trim()
290
+ } else {
291
+ rule.description = line.trim()
292
+ }
282
293
  } else if (state.currentSection === "details" && line.trim() && !line.trim().startsWith("**")) {
283
294
  rule.details.push(line.trim())
284
295
  }
@@ -0,0 +1,226 @@
1
+ # S005: No Origin Header Authentication
2
+
3
+ ## Tổng quan
4
+
5
+ Rule S005 phát hiện việc sử dụng Origin header cho authentication hoặc access control. Origin header có thể bị giả mạo (spoofed) và không an toàn để sử dụng làm cơ chế xác thực.
6
+
7
+ ## Mô tả
8
+
9
+ Origin header trong HTTP request chỉ ra domain nào đã gửi request. Tuy nhiên, header này có thể dễ dàng bị giả mạo bởi attacker và không nên được sử dụng làm cơ chế authentication hoặc authorization.
10
+
11
+ ## Tại sao quan trọng?
12
+
13
+ - **Bảo mật**: Origin header có thể bị spoofed, dẫn đến bypass authentication
14
+ - **Reliability**: Không phải tất cả browser đều gửi Origin header
15
+ - **Standards**: Không tuân thủ best practices về web security
16
+
17
+ ## Các pattern được phát hiện
18
+
19
+ ### ❌ Không hợp lệ
20
+
21
+ ```javascript
22
+ // 1. Sử dụng Origin header trực tiếp cho authentication
23
+ function authenticate(req, res, next) {
24
+ const origin = req.headers.origin;
25
+ if (origin === 'https://trusted.com') {
26
+ req.authenticated = true;
27
+ next();
28
+ } else {
29
+ res.status(401).json({ error: 'Unauthorized' });
30
+ }
31
+ }
32
+
33
+ // 2. Middleware sử dụng Origin cho access control
34
+ app.use('/api', (req, res, next) => {
35
+ if (req.get('origin') === 'https://admin.example.com') {
36
+ req.isAdmin = true;
37
+ }
38
+ next();
39
+ });
40
+
41
+ // 3. Conditional authentication dựa trên Origin
42
+ function checkAccess(req, res) {
43
+ if (req.headers.origin && req.headers.origin.includes('admin')) {
44
+ return res.json({ access: 'granted', token: generateToken() });
45
+ }
46
+ return res.status(403).json({ error: 'Access denied' });
47
+ }
48
+
49
+ // 4. CORS configuration mixed với authentication
50
+ app.use(cors({
51
+ origin: function(origin, callback) {
52
+ if (adminOrigins.includes(origin)) {
53
+ callback(null, { credentials: true, authenticated: true });
54
+ } else {
55
+ callback(null, false);
56
+ }
57
+ }
58
+ }));
59
+ ```
60
+
61
+ ### ✅ Hợp lệ
62
+
63
+ ```javascript
64
+ // 1. JWT token authentication
65
+ function authenticate(req, res, next) {
66
+ const token = req.headers.authorization;
67
+ jwt.verify(token, secret, (err, decoded) => {
68
+ if (err) return res.status(401).json({ error: 'Invalid token' });
69
+ req.user = decoded;
70
+ next();
71
+ });
72
+ }
73
+
74
+ // 2. Origin header chỉ để logging
75
+ function logRequest(req) {
76
+ console.log('Request from origin:', req.headers.origin);
77
+ logger.info(`Origin: ${req.get('origin')}`);
78
+ }
79
+
80
+ // 3. CORS configuration đúng (không mixing với auth)
81
+ app.use(cors({
82
+ origin: ['https://example.com', 'https://app.example.com'],
83
+ credentials: true
84
+ }));
85
+
86
+ // 4. Origin cho CORS preflight handling
87
+ function handlePreflight(req, res) {
88
+ const origin = req.headers.origin;
89
+ if (allowedOrigins.includes(origin)) {
90
+ res.setHeader('Access-Control-Allow-Origin', origin);
91
+ }
92
+ res.end();
93
+ }
94
+ ```
95
+
96
+ ## Các loại vi phạm
97
+
98
+ | Type | Severity | Mô tả |
99
+ |------|----------|--------|
100
+ | `origin_header_auth` | error | Trực tiếp sử dụng req.headers.origin cho authentication |
101
+ | `origin_header_method` | error | Sử dụng req.get('origin') cho authentication |
102
+ | `conditional_origin_auth` | error | Conditional logic dựa trên Origin cho authentication |
103
+ | `middleware_origin_auth` | error | Middleware authentication dựa trên Origin |
104
+ | `cors_origin_auth` | warning | CORS configuration mixing với authentication |
105
+ | `express_origin_auth` | error | Express routes sử dụng Origin cho authentication |
106
+
107
+ ## Cách khắc phục
108
+
109
+ ### 1. Sử dụng JWT Tokens
110
+
111
+ ```javascript
112
+ // Thay vì
113
+ if (req.headers.origin === 'trusted.com') {
114
+ req.authenticated = true;
115
+ }
116
+
117
+ // Sử dụng
118
+ const token = req.headers.authorization?.replace('Bearer ', '');
119
+ const decoded = jwt.verify(token, process.env.JWT_SECRET);
120
+ req.user = decoded;
121
+ ```
122
+
123
+ ### 2. Session-based Authentication
124
+
125
+ ```javascript
126
+ // Thay vì
127
+ if (req.get('origin') === 'admin.com') {
128
+ req.isAdmin = true;
129
+ }
130
+
131
+ // Sử dụng
132
+ if (req.session && req.session.user && req.session.user.role === 'admin') {
133
+ req.isAdmin = true;
134
+ }
135
+ ```
136
+
137
+ ### 3. API Key Authentication
138
+
139
+ ```javascript
140
+ // Thay vì
141
+ const origin = req.headers.origin;
142
+ if (trustedOrigins.includes(origin)) {
143
+ next();
144
+ }
145
+
146
+ // Sử dụng
147
+ const apiKey = req.headers['x-api-key'];
148
+ if (validateApiKey(apiKey)) {
149
+ next();
150
+ }
151
+ ```
152
+
153
+ ### 4. Proper CORS Configuration
154
+
155
+ ```javascript
156
+ // Đúng: CORS không làm authentication
157
+ app.use(cors({
158
+ origin: function(origin, callback) {
159
+ if (!origin || allowedOrigins.includes(origin)) {
160
+ callback(null, true);
161
+ } else {
162
+ callback(new Error('Not allowed by CORS'));
163
+ }
164
+ },
165
+ credentials: true
166
+ }));
167
+
168
+ // Authentication riêng biệt
169
+ app.use('/api', authenticateToken);
170
+ ```
171
+
172
+ ## Configuration
173
+
174
+ Rule có thể được cấu hình trong `config.json`:
175
+
176
+ ```json
177
+ {
178
+ "checkAuthContext": true,
179
+ "checkMiddleware": true,
180
+ "checkConditionals": true,
181
+ "checkCORSMixing": true,
182
+ "contextDepth": 3,
183
+ "ignoreComments": true
184
+ }
185
+ ```
186
+
187
+ ## Technology Stack
188
+
189
+ - **AST Analysis**: Babel parser với TypeScript/JavaScript support
190
+ - **Fallback**: Regex patterns cho edge cases
191
+ - **Accuracy**: 95% với AST, 85% với regex
192
+ - **Languages**: TypeScript, JavaScript
193
+
194
+ ## Testing
195
+
196
+ Rule được test với:
197
+ - Valid code patterns (không có violations)
198
+ - Invalid authentication patterns (có violations)
199
+ - Edge cases và syntax errors
200
+ - Context detection scenarios
201
+
202
+ ## Best Practices
203
+
204
+ 1. **Luôn sử dụng proper authentication mechanisms**:
205
+ - JWT tokens
206
+ - Session-based auth
207
+ - API keys
208
+ - OAuth 2.0
209
+
210
+ 2. **Tách biệt CORS và Authentication**:
211
+ - CORS chỉ để control resource sharing
212
+ - Authentication để verify identity
213
+
214
+ 3. **Origin header chỉ dùng cho**:
215
+ - Logging và monitoring
216
+ - CORS preflight handling
217
+ - Analytics (không sensitive)
218
+
219
+ 4. **Không bao giờ trust Origin header cho security decisions**
220
+
221
+ ## Tài liệu tham khảo
222
+
223
+ - [OWASP: CORS Origin Header Scrutiny](https://owasp.org/www-community/vulnerabilities/CORS_OriginHeaderScrutiny)
224
+ - [MDN: Origin Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)
225
+ - [Auth0: JWT Best Practices](https://auth0.com/docs/secure/tokens/json-web-tokens)
226
+ - [OWASP: Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Hybrid analyzer for S005 - No Origin Header Authentication
3
+ * Uses AST analysis with regex fallback for comprehensive coverage
4
+ * Detects usage of Origin header for authentication/access control
5
+ */
6
+
7
+ const S005ASTAnalyzer = require('./ast-analyzer');
8
+
9
+ class S005Analyzer {
10
+ constructor() {
11
+ this.ruleId = 'S005';
12
+ this.ruleName = 'No Origin Header Authentication';
13
+ this.description = 'Do not use Origin header for authentication or access control';
14
+ this.astAnalyzer = new S005ASTAnalyzer();
15
+ }
16
+
17
+ async analyze(files, language, options = {}) {
18
+ const violations = [];
19
+
20
+ if (options.verbose) {
21
+ console.log(`🔍 Running S005 analysis on ${files.length} files...`);
22
+ }
23
+
24
+ // Use AST analysis as primary method
25
+ const astViolations = await this.astAnalyzer.analyze(files, language, options);
26
+ violations.push(...astViolations);
27
+
28
+ // Add regex-based patterns for edge cases AST might miss
29
+ for (const filePath of files) {
30
+ try {
31
+ const content = require('fs').readFileSync(filePath, 'utf8');
32
+ const regexViolations = this.analyzeWithRegexPatterns(content, filePath, options);
33
+
34
+ // Filter out duplicates (same line, same type)
35
+ const filteredRegexViolations = regexViolations.filter(regexViolation =>
36
+ !astViolations.some(astViolation =>
37
+ astViolation.line === regexViolation.line &&
38
+ astViolation.filePath === regexViolation.filePath
39
+ )
40
+ );
41
+
42
+ violations.push(...filteredRegexViolations);
43
+ } catch (error) {
44
+ if (options.verbose) {
45
+ console.warn(`⚠️ S005 regex analysis failed for ${filePath}: ${error.message}`);
46
+ }
47
+ }
48
+ }
49
+
50
+ if (options.verbose && violations.length > 0) {
51
+ console.log(`📊 S005 found ${violations.length} violations`);
52
+ }
53
+
54
+ return violations;
55
+ }
56
+
57
+ analyzeWithRegexPatterns(content, filePath, options = {}) {
58
+ const violations = [];
59
+ const lines = content.split('\n');
60
+
61
+ lines.forEach((line, index) => {
62
+ const lineNumber = index + 1;
63
+
64
+ // Pattern 1: Direct origin header access for authentication
65
+ // req.headers.origin, req.get('origin'), req.header('origin')
66
+ const originHeaderPattern = /(?:req\.headers\.origin|req\.get\s*\(\s*['"`]origin['"`]\s*\)|req\.header\s*\(\s*['"`]origin['"`]\s*\)|headers\[['"`]origin['"`]\])/i;
67
+ if (originHeaderPattern.test(line)) {
68
+ // Check if this line is used for authentication/authorization
69
+ const authContextPattern = /(?:auth|login|verify|check|validate|permission|access|allow|deny|secure|token|session)/i;
70
+ if (authContextPattern.test(line) || this.isInAuthContext(lines, index)) {
71
+ violations.push({
72
+ ruleId: this.ruleId,
73
+ severity: 'error',
74
+ message: 'Origin header should not be used for authentication. Origin can be spoofed and is not secure for access control.',
75
+ line: lineNumber,
76
+ column: line.search(originHeaderPattern) + 1,
77
+ filePath: filePath,
78
+ type: 'origin_header_auth'
79
+ });
80
+ }
81
+ }
82
+
83
+ // Pattern 2: Origin-based CORS validation for authentication
84
+ const corsOriginAuthPattern = /(?:cors|origin).*(?:auth|login|permission|access|allow|token)/i;
85
+ if (corsOriginAuthPattern.test(line) && !line.includes('//') && !line.includes('*')) {
86
+ violations.push({
87
+ ruleId: this.ruleId,
88
+ severity: 'warning',
89
+ message: 'CORS origin validation should not replace proper authentication mechanisms.',
90
+ line: lineNumber,
91
+ column: line.search(corsOriginAuthPattern) + 1,
92
+ filePath: filePath,
93
+ type: 'cors_origin_auth'
94
+ });
95
+ }
96
+
97
+ // Pattern 3: Origin header in conditional authentication logic
98
+ const conditionalAuthPattern = /if\s*\([^)]*origin[^)]*\)\s*\{[^}]*(?:auth|login|token|permission|access)/i;
99
+ if (conditionalAuthPattern.test(line)) {
100
+ violations.push({
101
+ ruleId: this.ruleId,
102
+ severity: 'error',
103
+ message: 'Conditional authentication based on Origin header is insecure. Use proper authentication tokens.',
104
+ line: lineNumber,
105
+ column: line.search(/origin/i) + 1,
106
+ filePath: filePath,
107
+ type: 'conditional_origin_auth'
108
+ });
109
+ }
110
+
111
+ // Pattern 4: Origin in middleware authentication
112
+ const middlewarePattern = /(middleware|auth|guard).*origin.*(?:next\(\)|return|allow|permit)/i;
113
+ if (middlewarePattern.test(line)) {
114
+ violations.push({
115
+ ruleId: this.ruleId,
116
+ severity: 'error',
117
+ message: 'Authentication middleware should not rely on Origin header. Use proper authentication mechanisms.',
118
+ line: lineNumber,
119
+ column: line.search(/origin/i) + 1,
120
+ filePath: filePath,
121
+ type: 'middleware_origin_auth'
122
+ });
123
+ }
124
+
125
+ // Pattern 5: Origin header whitelisting for access control
126
+ const whitelistPattern = /(?:whitelist|allowlist|allowed.*origins?).*(?:auth|access|permission)/i;
127
+ if (whitelistPattern.test(line) && /origin/i.test(line)) {
128
+ violations.push({
129
+ ruleId: this.ruleId,
130
+ severity: 'warning',
131
+ message: 'Origin whitelisting should complement, not replace, proper authentication and authorization.',
132
+ line: lineNumber,
133
+ column: line.search(/origin/i) + 1,
134
+ filePath: filePath,
135
+ type: 'origin_whitelist_auth'
136
+ });
137
+ }
138
+
139
+ // Pattern 6: Express.js specific patterns
140
+ const expressPattern = /(?:app\.use|router\.).*origin.*(?:auth|protect|secure)/i;
141
+ if (expressPattern.test(line)) {
142
+ violations.push({
143
+ ruleId: this.ruleId,
144
+ severity: 'error',
145
+ message: 'Express routes should not use Origin header for authentication or authorization.',
146
+ line: lineNumber,
147
+ column: line.search(/origin/i) + 1,
148
+ filePath: filePath,
149
+ type: 'express_origin_auth'
150
+ });
151
+ }
152
+ });
153
+
154
+ return violations;
155
+ }
156
+
157
+ /**
158
+ * Check if the current line is within an authentication context
159
+ * by looking at surrounding lines
160
+ */
161
+ isInAuthContext(lines, currentIndex) {
162
+ const contextRange = 3; // Check 3 lines before and after
163
+ const startIndex = Math.max(0, currentIndex - contextRange);
164
+ const endIndex = Math.min(lines.length - 1, currentIndex + contextRange);
165
+
166
+ const authKeywords = [
167
+ 'authenticate', 'authorize', 'login', 'logout', 'auth',
168
+ 'permission', 'access', 'token', 'session', 'user',
169
+ 'verify', 'validate', 'check', 'guard', 'protect',
170
+ 'middleware', 'passport', 'jwt', 'bearer'
171
+ ];
172
+
173
+ for (let i = startIndex; i <= endIndex; i++) {
174
+ const line = lines[i].toLowerCase();
175
+ if (authKeywords.some(keyword => line.includes(keyword))) {
176
+ return true;
177
+ }
178
+ }
179
+
180
+ return false;
181
+ }
182
+ }
183
+
184
+ module.exports = S005Analyzer;