@sun-asterisk/sunlint 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +85 -0
- package/CONTRIBUTING.md +210 -1691
- package/README.md +5 -3
- package/config/rule-analysis-strategies.js +17 -1
- package/config/rules/enhanced-rules-registry.json +506 -1161
- package/config/rules/rules-registry-generated.json +1 -1
- package/core/analysis-orchestrator.js +167 -42
- package/core/auto-performance-manager.js +243 -0
- package/core/cli-action-handler.js +9 -1
- package/core/cli-program.js +19 -5
- package/core/constants/defaults.js +56 -0
- package/core/enhanced-rules-registry.js +2 -1
- package/core/performance-optimizer.js +271 -0
- package/core/semantic-engine.js +15 -3
- package/core/semantic-rule-base.js +4 -2
- package/docs/FILE_LIMITS_COMPLETION_REPORT.md +151 -0
- package/docs/FILE_LIMITS_EXPLANATION.md +190 -0
- package/docs/PERFORMANCE.md +311 -0
- package/docs/PERFORMANCE_MIGRATION_GUIDE.md +368 -0
- package/docs/PERFORMANCE_OPTIMIZATION_PLAN.md +255 -0
- package/docs/QUICK_FILE_LIMITS.md +64 -0
- package/docs/SIMPLIFIED_USAGE_GUIDE.md +208 -0
- package/engines/heuristic-engine.js +247 -9
- package/integrations/eslint/plugin/rules/common/c003-no-vague-abbreviations.js +59 -1
- package/integrations/eslint/plugin/rules/common/c006-function-name-verb-noun.js +26 -1
- package/integrations/eslint/plugin/rules/common/c030-use-custom-error-classes.js +54 -19
- package/origin-rules/common-en.md +11 -7
- package/package.json +2 -1
- package/rules/common/C002_no_duplicate_code/analyzer.js +334 -36
- package/rules/common/C003_no_vague_abbreviations/analyzer.js +220 -35
- package/rules/common/C006_function_naming/analyzer.js +29 -3
- package/rules/common/C010_limit_block_nesting/analyzer.js +181 -337
- package/rules/common/C010_limit_block_nesting/config.json +64 -0
- package/rules/common/C010_limit_block_nesting/regex-based-analyzer.js +379 -0
- package/rules/common/C010_limit_block_nesting/symbol-based-analyzer.js +231 -0
- package/rules/common/C013_no_dead_code/analyzer.js +75 -177
- package/rules/common/C013_no_dead_code/config.json +61 -0
- package/rules/common/C013_no_dead_code/regex-based-analyzer.js +345 -0
- package/rules/common/C013_no_dead_code/symbol-based-analyzer.js +640 -0
- package/rules/common/C014_dependency_injection/analyzer.js +48 -313
- package/rules/common/C014_dependency_injection/config.json +26 -0
- package/rules/common/C014_dependency_injection/symbol-based-analyzer.js +751 -0
- package/rules/common/C018_no_throw_generic_error/analyzer.js +232 -0
- package/rules/common/C018_no_throw_generic_error/config.json +50 -0
- package/rules/common/C018_no_throw_generic_error/regex-based-analyzer.js +387 -0
- package/rules/common/C018_no_throw_generic_error/symbol-based-analyzer.js +314 -0
- package/rules/common/C019_log_level_usage/analyzer.js +110 -317
- package/rules/common/C019_log_level_usage/pattern-analyzer.js +88 -0
- package/rules/common/C019_log_level_usage/system-log-analyzer.js +1267 -0
- package/rules/common/C023_no_duplicate_variable/analyzer.js +180 -0
- package/rules/common/C023_no_duplicate_variable/config.json +50 -0
- package/rules/common/C023_no_duplicate_variable/symbol-based-analyzer.js +158 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/analyzer.js +180 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/config.json +50 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/symbol-based-analyzer.js +181 -0
- package/rules/common/C030_use_custom_error_classes/analyzer.js +200 -0
- package/rules/common/C035_error_logging_context/analyzer.js +3 -1
- package/rules/common/C048_no_bypass_architectural_layers/analyzer.js +180 -0
- package/rules/common/C048_no_bypass_architectural_layers/config.json +50 -0
- package/rules/common/C048_no_bypass_architectural_layers/symbol-based-analyzer.js +235 -0
- package/rules/common/C052_parsing_or_data_transformation/analyzer.js +180 -0
- package/rules/common/C052_parsing_or_data_transformation/config.json +50 -0
- package/rules/common/C052_parsing_or_data_transformation/symbol-based-analyzer.js +132 -0
- package/rules/index.js +7 -1
- package/rules/security/S009_no_insecure_encryption/README.md +158 -0
- package/rules/security/S009_no_insecure_encryption/analyzer.js +319 -0
- package/rules/security/S009_no_insecure_encryption/config.json +55 -0
- package/rules/security/S010_no_insecure_encryption/README.md +224 -0
- package/rules/security/S010_no_insecure_encryption/analyzer.js +493 -0
- package/rules/security/S010_no_insecure_encryption/config.json +48 -0
- package/rules/security/S016_no_sensitive_querystring/STRATEGY.md +149 -0
- package/rules/security/S016_no_sensitive_querystring/analyzer.js +276 -0
- package/rules/security/S016_no_sensitive_querystring/config.json +127 -0
- package/rules/security/S016_no_sensitive_querystring/regex-based-analyzer.js +258 -0
- package/rules/security/S016_no_sensitive_querystring/symbol-based-analyzer.js +495 -0
- package/rules/security/S017_use_parameterized_queries/README.md +128 -0
- package/rules/security/S017_use_parameterized_queries/analyzer.js +286 -0
- package/rules/security/S017_use_parameterized_queries/config.json +109 -0
- package/rules/security/S017_use_parameterized_queries/regex-based-analyzer.js +541 -0
- package/rules/security/S017_use_parameterized_queries/symbol-based-analyzer.js +777 -0
- package/rules/security/S031_secure_session_cookies/README.md +127 -0
- package/rules/security/S031_secure_session_cookies/analyzer.js +245 -0
- package/rules/security/S031_secure_session_cookies/config.json +86 -0
- package/rules/security/S031_secure_session_cookies/regex-based-analyzer.js +196 -0
- package/rules/security/S031_secure_session_cookies/symbol-based-analyzer.js +1084 -0
- package/rules/security/S032_httponly_session_cookies/FRAMEWORK_SUPPORT.md +209 -0
- package/rules/security/S032_httponly_session_cookies/README.md +184 -0
- package/rules/security/S032_httponly_session_cookies/analyzer.js +282 -0
- package/rules/security/S032_httponly_session_cookies/config.json +96 -0
- package/rules/security/S032_httponly_session_cookies/regex-based-analyzer.js +715 -0
- package/rules/security/S032_httponly_session_cookies/symbol-based-analyzer.js +1348 -0
- package/rules/security/S033_samesite_session_cookies/README.md +227 -0
- package/rules/security/S033_samesite_session_cookies/analyzer.js +242 -0
- package/rules/security/S033_samesite_session_cookies/config.json +87 -0
- package/rules/security/S033_samesite_session_cookies/regex-based-analyzer.js +703 -0
- package/rules/security/S033_samesite_session_cookies/symbol-based-analyzer.js +732 -0
- package/rules/security/S034_host_prefix_session_cookies/README.md +204 -0
- package/rules/security/S034_host_prefix_session_cookies/analyzer.js +290 -0
- package/rules/security/S034_host_prefix_session_cookies/config.json +62 -0
- package/rules/security/S034_host_prefix_session_cookies/regex-based-analyzer.js +478 -0
- package/rules/security/S034_host_prefix_session_cookies/symbol-based-analyzer.js +277 -0
- package/rules/security/S035_path_session_cookies/README.md +257 -0
- package/rules/security/S035_path_session_cookies/analyzer.js +316 -0
- package/rules/security/S035_path_session_cookies/config.json +99 -0
- package/rules/security/S035_path_session_cookies/regex-based-analyzer.js +724 -0
- package/rules/security/S035_path_session_cookies/symbol-based-analyzer.js +373 -0
- package/rules/security/S048_no_current_password_in_reset/README.md +222 -0
- package/rules/security/S048_no_current_password_in_reset/analyzer.js +366 -0
- package/rules/security/S048_no_current_password_in_reset/config.json +48 -0
- package/rules/security/S055_content_type_validation/README.md +176 -0
- package/rules/security/S055_content_type_validation/analyzer.js +312 -0
- package/rules/security/S055_content_type_validation/config.json +48 -0
- package/rules/utils/rule-helpers.js +140 -1
- package/scripts/batch-processing-demo.js +334 -0
- package/scripts/consolidate-config.js +116 -0
- package/scripts/performance-test.js +541 -0
- package/scripts/quick-performance-test.js +108 -0
- package/config/rules/S027-categories.json +0 -122
- package/config/rules/rules-registry.json +0 -777
- package/rules/common/C006_function_naming/smart-analyzer.js +0 -503
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C018 Symbol-based Analyzer - Advanced Do not throw generic errors
|
|
3
|
+
* Purpose: Use AST + Symbol Resolution to analyze log content quality in catch blocks
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { SyntaxKind } = require('ts-morph');
|
|
7
|
+
|
|
8
|
+
class C018SymbolBasedAnalyzer {
|
|
9
|
+
constructor(semanticEngine = null) {
|
|
10
|
+
this.ruleId = 'C018';
|
|
11
|
+
this.ruleName = 'Error Always provide detailed messages and context. (Symbol-Based)';
|
|
12
|
+
this.semanticEngine = semanticEngine;
|
|
13
|
+
this.verbose = false;
|
|
14
|
+
|
|
15
|
+
// Sensitive data patterns to flag (more specific to avoid false positives)
|
|
16
|
+
this.sensitivePatterns = [
|
|
17
|
+
'password', 'passwd', 'pwd', 'pass',
|
|
18
|
+
'token', 'jwt', 'secret', 'privatekey', 'publickey', 'apikey', 'accesskey',
|
|
19
|
+
'ssn', 'social', 'creditcard', 'cardnumber', 'cvv', 'pin',
|
|
20
|
+
'authorization', 'bearer'
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Ensure error messages should explain what happened, why, and in what context
|
|
24
|
+
this.explanationPatterns = [
|
|
25
|
+
'because', 'due to', 'failed to', 'cannot', 'invalid', 'missing', 'not found',
|
|
26
|
+
];
|
|
27
|
+
this.guidancePatterns = [
|
|
28
|
+
'please', 'ensure', 'make sure', 'check', 'try', 'use',
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async initialize(semanticEngine = null) {
|
|
33
|
+
if (semanticEngine) {
|
|
34
|
+
this.semanticEngine = semanticEngine;
|
|
35
|
+
}
|
|
36
|
+
this.verbose = semanticEngine?.verbose || false;
|
|
37
|
+
|
|
38
|
+
if (process.env.SUNLINT_DEBUG) {
|
|
39
|
+
console.log(`🔧 [C018 Symbol-Based] Analyzer initialized, verbose: ${this.verbose}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async analyzeFileBasic(filePath, options = {}) {
|
|
44
|
+
// This is the main entry point called by the hybrid analyzer
|
|
45
|
+
return await this.analyzeFileWithSymbols(filePath, options);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async analyzeFileWithSymbols(filePath, options = {}) {
|
|
49
|
+
const violations = [];
|
|
50
|
+
|
|
51
|
+
// Enable verbose mode if requested
|
|
52
|
+
const verbose = options.verbose || this.verbose;
|
|
53
|
+
|
|
54
|
+
if (!this.semanticEngine?.project) {
|
|
55
|
+
if (verbose) {
|
|
56
|
+
console.warn('[C018 Symbol-Based] No semantic engine available, skipping analysis');
|
|
57
|
+
}
|
|
58
|
+
return violations;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (verbose) {
|
|
62
|
+
console.log(`🔍 [C018 Symbol-Based] Starting analysis for ${filePath}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const sourceFile = this.semanticEngine.project.getSourceFile(filePath);
|
|
67
|
+
if (!sourceFile) {
|
|
68
|
+
return violations;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Find all try-catch statements in the file
|
|
72
|
+
const tryCatchStatements = sourceFile.getDescendantsOfKind(SyntaxKind.TryStatement);
|
|
73
|
+
|
|
74
|
+
if (verbose) {
|
|
75
|
+
console.log(`🔍 [C018 Symbol-Based] Found ${tryCatchStatements.length} try-catch statements`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for (const tryStatement of tryCatchStatements) {
|
|
79
|
+
const catchClause = tryStatement.getCatchClause();
|
|
80
|
+
if (catchClause) {
|
|
81
|
+
const catchViolations = this.analyzeCatchBlock(catchClause, sourceFile, filePath, verbose);
|
|
82
|
+
violations.push(...catchViolations);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (verbose) {
|
|
87
|
+
console.log(`🔍 [C018 Symbol-Based] Total violations found: ${violations.length}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return violations;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (verbose) {
|
|
93
|
+
console.warn(`[C018 Symbol-Based] Analysis failed for ${filePath}:`, error.message);
|
|
94
|
+
}
|
|
95
|
+
return violations;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Analyze catch block for logging context violations
|
|
101
|
+
*/
|
|
102
|
+
analyzeCatchBlock(catchClause, sourceFile, filePath, verbose = false) {
|
|
103
|
+
const violations = [];
|
|
104
|
+
|
|
105
|
+
if (verbose) {
|
|
106
|
+
console.log(`🔍 [C018 Symbol-Based] Analyzing catch block in ${filePath}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Get catch parameter (e, error, err, etc.)
|
|
110
|
+
const catchParameter = catchClause.getVariableDeclaration();
|
|
111
|
+
const errorVarName = catchParameter?.getName() || 'e';
|
|
112
|
+
|
|
113
|
+
if (verbose) {
|
|
114
|
+
console.log(`🔍 [C018 Symbol-Based] Error variable name: ${errorVarName}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Find all log calls within catch block
|
|
118
|
+
const catchBlock = catchClause.getBlock();
|
|
119
|
+
const throwStatements = catchBlock.getDescendantsOfKind(SyntaxKind.ThrowStatement);
|
|
120
|
+
|
|
121
|
+
if (verbose) {
|
|
122
|
+
console.log(`🔍 [C018 Symbol-Based] Error variable name: ${errorVarName}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (throwStatements.length === 0) {
|
|
126
|
+
// No logging found - but this is C029's concern, not C018
|
|
127
|
+
// We only analyze existing logs for quality
|
|
128
|
+
return violations;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Analyze each log call for context quality
|
|
132
|
+
for (const throwStatement of throwStatements) {
|
|
133
|
+
if (verbose) {
|
|
134
|
+
console.log(`🔍 [C018 Symbol-Based] Analyzing throwStatement call: ${throwStatement.getText()}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const throwViolations = this.analyzeThrowCall(throwStatement, errorVarName, sourceFile, filePath, verbose);
|
|
138
|
+
violations.push(...throwViolations);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return violations;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Analyze individual log call for context quality
|
|
146
|
+
*/
|
|
147
|
+
analyzeThrowCall(throwStatement, errorVarName, sourceFile, filePath, verbose = false) {
|
|
148
|
+
const violations = [];
|
|
149
|
+
const lineNumber = throwStatement.getStartLineNumber();
|
|
150
|
+
const columnNumber = throwStatement.getStart() - throwStatement.getStartLinePos();
|
|
151
|
+
const exp = throwStatement.getExpression();
|
|
152
|
+
|
|
153
|
+
if (!exp) {
|
|
154
|
+
return violations; // No arguments to analyze;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Case: throw e (identifier)
|
|
158
|
+
if (exp.getKind() === SyntaxKind.Identifier) {
|
|
159
|
+
violations.push({
|
|
160
|
+
ruleId: this.ruleId,
|
|
161
|
+
severity: 'error',
|
|
162
|
+
message: 'Throwing caught error directly without context',
|
|
163
|
+
source: this.ruleId,
|
|
164
|
+
file: filePath,
|
|
165
|
+
line: lineNumber,
|
|
166
|
+
column: columnNumber,
|
|
167
|
+
description: `[SYMBOL-BASED] Caught error thrown directly without additional context. Use structured error objects.`,
|
|
168
|
+
suggestion: 'Use structured error objects with context instead of throwing caught errors directly',
|
|
169
|
+
category: 'error-handling'
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const args = [];
|
|
174
|
+
|
|
175
|
+
// Case: throw new Error("...")
|
|
176
|
+
if (exp.getKind() === SyntaxKind.NewExpression) {
|
|
177
|
+
const newExp = exp.asKind(SyntaxKind.NewExpression);
|
|
178
|
+
const arg = newExp.getArguments().map(arg => arg);
|
|
179
|
+
|
|
180
|
+
args.push(...arg);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const analysis = this.analyzeThrowArguments(args, errorVarName, verbose);
|
|
184
|
+
|
|
185
|
+
// Analyze throw structure and content
|
|
186
|
+
|
|
187
|
+
// Check for violations
|
|
188
|
+
if (!analysis.isStructured) {
|
|
189
|
+
violations.push({
|
|
190
|
+
ruleId: this.ruleId,
|
|
191
|
+
severity: 'warning',
|
|
192
|
+
message: 'Error logging should use structured format (object) instead of string concatenation',
|
|
193
|
+
source: this.ruleId,
|
|
194
|
+
file: filePath,
|
|
195
|
+
line: lineNumber,
|
|
196
|
+
column: columnNumber,
|
|
197
|
+
description: `[SYMBOL-BASED] Non-structured logging detected. Use object format for better parsing and monitoring.`,
|
|
198
|
+
suggestion: 'Use logger.error("message", { error: e.message, context: {...} }) instead of string concatenation',
|
|
199
|
+
category: 'error-handling'
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (analysis.hasSensitiveData) {
|
|
204
|
+
violations.push({
|
|
205
|
+
ruleId: this.ruleId,
|
|
206
|
+
severity: 'error',
|
|
207
|
+
message: 'Error logging contains potentially sensitive data',
|
|
208
|
+
source: this.ruleId,
|
|
209
|
+
file: filePath,
|
|
210
|
+
line: lineNumber,
|
|
211
|
+
column: columnNumber,
|
|
212
|
+
description: `[SYMBOL-BASED] Sensitive patterns detected: ${analysis.sensitivePatterns.join(', ')}. Mask or exclude sensitive data.`,
|
|
213
|
+
suggestion: 'Mask sensitive data: password.substring(0,2) + "***" or exclude entirely',
|
|
214
|
+
category: 'security'
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!analysis.hasExplanation) {
|
|
219
|
+
violations.push({
|
|
220
|
+
ruleId: this.ruleId,
|
|
221
|
+
severity: 'warning',
|
|
222
|
+
message: 'Error logging should explain what happened',
|
|
223
|
+
source: this.ruleId,
|
|
224
|
+
file: filePath,
|
|
225
|
+
line: lineNumber,
|
|
226
|
+
column: columnNumber,
|
|
227
|
+
description: `[SYMBOL-BASED] Error message should explain what happened, why, and in what context.`,
|
|
228
|
+
suggestion: 'Use structured error objects with context: { message: "Error occurred", context: "Request failed because todo something." } }',
|
|
229
|
+
category: 'error-handling'
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!analysis.hasGuidance) {
|
|
234
|
+
violations.push({
|
|
235
|
+
ruleId: this.ruleId,
|
|
236
|
+
severity: 'warning',
|
|
237
|
+
message: 'Error logging should provide guidance on what to do next',
|
|
238
|
+
source: this.ruleId,
|
|
239
|
+
file: filePath,
|
|
240
|
+
line: lineNumber,
|
|
241
|
+
column: columnNumber,
|
|
242
|
+
description: `[SYMBOL-BASED] Error message should provide guidance on what to do next.`,
|
|
243
|
+
suggestion: 'Use structured error objects with guidance: { message: "Error occurred", guidance: "Please check the input data and try again." }',
|
|
244
|
+
category: 'error-handling'
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return violations;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Analyze log arguments for structure, context, and sensitive data
|
|
253
|
+
*/
|
|
254
|
+
analyzeThrowArguments(args, errorVarName, verbose = false) {
|
|
255
|
+
const analysis = {
|
|
256
|
+
isStructured: false,
|
|
257
|
+
hasSensitiveData: false,
|
|
258
|
+
hasExplanation: false,
|
|
259
|
+
hasGuidance: false,
|
|
260
|
+
sensitivePatterns: []
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Check if any argument is an object (structured logging)
|
|
264
|
+
for (const arg of args) {
|
|
265
|
+
if (arg.getKind() === SyntaxKind.ObjectLiteralExpression) {
|
|
266
|
+
analysis.isStructured = true;
|
|
267
|
+
analysis.hasExplanation = true; // Assume structured logs have explanations
|
|
268
|
+
analysis.hasGuidance = true; // Assume structured logs have guidance
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// If not structured, check for string concatenation patterns
|
|
274
|
+
if (!analysis.isStructured) {
|
|
275
|
+
for (const arg of args) {
|
|
276
|
+
const argText = arg.getText().toLowerCase();
|
|
277
|
+
this.validateForSensitiveDataInText(argText, analysis);
|
|
278
|
+
this.validateErrorMessage(argText, analysis);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return analysis;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Check text for sensitive data patterns
|
|
287
|
+
*/
|
|
288
|
+
validateForSensitiveDataInText(text, analysis) {
|
|
289
|
+
for (const pattern of this.sensitivePatterns) {
|
|
290
|
+
if (text.includes(pattern)) {
|
|
291
|
+
analysis.hasSensitiveData = true;
|
|
292
|
+
analysis.sensitivePatterns.push(pattern);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
validateErrorMessage(text, analysis) {
|
|
298
|
+
// Rule 1: Explanation
|
|
299
|
+
for (const patternE of this.explanationPatterns) {
|
|
300
|
+
if (text.includes(patternE)) {
|
|
301
|
+
analysis.hasExplanation = true;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Rule 2: Guidance
|
|
306
|
+
for (const patternG of this.guidancePatterns) {
|
|
307
|
+
if (text.includes(patternG)) {
|
|
308
|
+
analysis.hasGuidance = true;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
module.exports = C018SymbolBasedAnalyzer;
|