@sun-asterisk/sunlint 1.3.26 → 1.3.28

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 (69) hide show
  1. package/config/rules/enhanced-rules-registry.json +101 -17
  2. package/config/rules/rules-registry-generated.json +22 -22
  3. package/origin-rules/security-en.md +351 -338
  4. package/package.json +1 -1
  5. package/rules/common/C003_no_vague_abbreviations/analyzer.js +73 -21
  6. package/rules/common/C017_constructor_logic/symbol-based-analyzer.js +206 -2
  7. package/rules/common/C024_no_scatter_hardcoded_constants/symbol-based-analyzer.js +553 -58
  8. package/rules/common/C029_catch_block_logging/analyzer.js +47 -12
  9. package/rules/common/C033_separate_service_repository/symbol-based-analyzer.js +35 -15
  10. package/rules/common/C041_no_sensitive_hardcode/symbol-based-analyzer.js +9 -5
  11. package/rules/security/S003_open_redirect_protection/README.md +371 -0
  12. package/rules/security/S003_open_redirect_protection/analyzer.js +135 -0
  13. package/rules/security/S003_open_redirect_protection/config.json +58 -0
  14. package/rules/security/S003_open_redirect_protection/symbol-based-analyzer.js +884 -0
  15. package/rules/security/S004_sensitive_data_logging/analyzer.js +135 -0
  16. package/rules/security/S004_sensitive_data_logging/config.json +62 -0
  17. package/rules/security/S004_sensitive_data_logging/symbol-based-analyzer.js +592 -0
  18. package/rules/security/S005_no_origin_auth/analyzer.js +97 -148
  19. package/rules/security/S005_no_origin_auth/config.json +28 -67
  20. package/rules/security/S005_no_origin_auth/symbol-based-analyzer.js +708 -0
  21. package/rules/security/S006_no_plaintext_recovery_codes/symbol-based-analyzer.js +170 -31
  22. package/rules/security/S010_no_insecure_encryption/analyzer.js +8 -2
  23. package/rules/security/S012_hardcoded_secrets/analyzer.js +149 -0
  24. package/rules/security/S012_hardcoded_secrets/config.json +75 -0
  25. package/rules/security/S012_hardcoded_secrets/symbol-based-analyzer.js +1204 -0
  26. package/rules/security/S013_tls_enforcement/symbol-based-analyzer.js +87 -0
  27. package/rules/security/S017_use_parameterized_queries/analyzer.js +11 -78
  28. package/rules/security/S017_use_parameterized_queries/symbol-based-analyzer.js +1146 -1
  29. package/rules/security/S019_smtp_injection_protection/analyzer.js +120 -0
  30. package/rules/security/S019_smtp_injection_protection/config.json +35 -0
  31. package/rules/security/S019_smtp_injection_protection/symbol-based-analyzer.js +687 -0
  32. package/rules/security/S020_no_eval_dynamic_code/analyzer.js +55 -130
  33. package/rules/security/S020_no_eval_dynamic_code/symbol-based-analyzer.js +4 -19
  34. package/rules/security/S022_escape_output_context/README.md +254 -0
  35. package/rules/security/S022_escape_output_context/analyzer.js +510 -0
  36. package/rules/security/S022_escape_output_context/config.json +229 -0
  37. package/rules/security/S023_no_json_injection/analyzer.js +15 -0
  38. package/rules/security/S023_no_json_injection/ast-analyzer.js +18 -3
  39. package/rules/security/S023_no_json_injection/config.json +133 -0
  40. package/rules/security/S024_xpath_xxe_protection/regex-based-analyzer.js +41 -0
  41. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +67 -8
  42. package/rules/security/S027_no_hardcoded_secrets/categorized-analyzer.js +29 -6
  43. package/rules/security/S029_csrf_protection/config.json +127 -0
  44. package/rules/security/S030_directory_browsing_protection/regex-based-analyzer.js +160 -28
  45. package/rules/security/S030_directory_browsing_protection/symbol-based-analyzer.js +81 -19
  46. package/rules/security/S031_secure_session_cookies/analyzer.js +20 -2
  47. package/rules/security/S031_secure_session_cookies/regex-based-analyzer.js +100 -0
  48. package/rules/security/S031_secure_session_cookies/symbol-based-analyzer.js +8 -1
  49. package/rules/security/S032_httponly_session_cookies/analyzer.js +2 -2
  50. package/rules/security/S032_httponly_session_cookies/regex-based-analyzer.js +115 -0
  51. package/rules/security/S032_httponly_session_cookies/symbol-based-analyzer.js +39 -10
  52. package/rules/security/S036_lfi_rfi_protection/analyzer.js +224 -0
  53. package/rules/security/S036_lfi_rfi_protection/config.json +20 -0
  54. package/rules/security/S040_session_fixation_protection/analyzer.js +153 -0
  55. package/rules/security/S040_session_fixation_protection/config.json +20 -0
  56. package/rules/security/S042_require_re_authentication_for_long_lived/README.md +83 -0
  57. package/rules/security/S042_require_re_authentication_for_long_lived/analyzer.js +153 -0
  58. package/rules/security/S042_require_re_authentication_for_long_lived/config.json +41 -0
  59. package/rules/security/S042_require_re_authentication_for_long_lived/symbol-based-analyzer.js +1139 -0
  60. package/rules/security/S043_password_changes_invalidate_all_sessions/README.md +107 -0
  61. package/rules/security/S043_password_changes_invalidate_all_sessions/analyzer.js +153 -0
  62. package/rules/security/S043_password_changes_invalidate_all_sessions/config.json +41 -0
  63. package/rules/security/S043_password_changes_invalidate_all_sessions/symbol-based-analyzer.js +541 -0
  64. package/docs/COMMAND-EXAMPLES.md +0 -390
  65. package/docs/FILE_LIMITS_COMPLETION_REPORT.md +0 -151
  66. package/docs/FOLDER_STRUCTURE.md +0 -59
  67. package/docs/SIMPLIFIED_USAGE_GUIDE.md +0 -208
  68. package/rules/security/S017_use_parameterized_queries/regex-based-analyzer.js +0 -541
  69. package/rules/security/S020_no_eval_dynamic_code/regex-based-analyzer.js +0 -307
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Rule S019: SMTP Injection Protection - Analyzer Wrapper
3
+ *
4
+ * This analyzer wraps the symbol-based analyzer to provide a consistent
5
+ * interface for the SunLint engine.
6
+ */
7
+ // Command: node cli.js --rule=S019 --input=examples/rule-test-fixtures/rules/S019_smtp_injection_protection --engine=heuristic
8
+
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+ const { Project } = require("ts-morph");
12
+ const S019SymbolBasedAnalyzer = require("./symbol-based-analyzer");
13
+
14
+ class S019Analyzer {
15
+ constructor(options = {}) {
16
+ this.ruleId = "S019";
17
+ this.semanticEngine = options.semanticEngine || null;
18
+ this.symbolAnalyzer = new S019SymbolBasedAnalyzer(this.semanticEngine);
19
+ }
20
+
21
+ /**
22
+ * Analyze multiple files
23
+ */
24
+ async analyze(files, language, options = {}) {
25
+ const violations = [];
26
+
27
+ for (const filePath of files) {
28
+ try {
29
+ const fileViolations = await this.analyzeFile(filePath, options);
30
+ violations.push(...fileViolations);
31
+ } catch (error) {
32
+ console.error(
33
+ `[S019] Error analyzing file ${filePath}:`,
34
+ error.message
35
+ );
36
+ }
37
+ }
38
+
39
+ return violations;
40
+ }
41
+
42
+ /**
43
+ * Analyze a single file
44
+ */
45
+ async analyzeFile(filePath, options = {}) {
46
+ // Skip files that shouldn't be analyzed
47
+ if (this.shouldSkipFile(filePath)) {
48
+ return [];
49
+ }
50
+
51
+ try {
52
+ // Check if file exists
53
+ if (!fs.existsSync(filePath)) {
54
+ return [];
55
+ }
56
+
57
+ const content = fs.readFileSync(filePath, "utf-8");
58
+
59
+ // Try to get source file from semantic engine
60
+ let sourceFile = this.semanticEngine?.project?.getSourceFile(filePath);
61
+
62
+ // If not available, create a temporary ts-morph source file
63
+ if (!sourceFile) {
64
+ const tempProject = new Project({
65
+ useInMemoryFileSystem: true,
66
+ compilerOptions: {
67
+ allowJs: true,
68
+ noLib: true,
69
+ target: 99, // ESNext
70
+ },
71
+ });
72
+
73
+ sourceFile = tempProject.createSourceFile(
74
+ path.basename(filePath),
75
+ content
76
+ );
77
+ }
78
+
79
+ // Run the symbol-based analyzer
80
+ const symbolViolations = await this.symbolAnalyzer.analyze(
81
+ sourceFile,
82
+ filePath
83
+ );
84
+
85
+ // Format violations to include file path
86
+ return symbolViolations.map((violation) => ({
87
+ ...violation,
88
+ filePath: filePath,
89
+ file: filePath,
90
+ }));
91
+ } catch (error) {
92
+ console.error(`[S019] Error processing ${filePath}:`, error.message);
93
+ return [];
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Check if file should be skipped
99
+ */
100
+ shouldSkipFile(filePath) {
101
+ const skipPatterns = [
102
+ "node_modules/",
103
+ "dist/",
104
+ "build/",
105
+ ".next/",
106
+ "coverage/",
107
+ "__tests__/",
108
+ "test/",
109
+ "tests/",
110
+ ".test.",
111
+ ".spec.",
112
+ ".min.js",
113
+ ".bundle.js",
114
+ ];
115
+
116
+ return skipPatterns.some((pattern) => filePath.includes(pattern));
117
+ }
118
+ }
119
+
120
+ module.exports = S019Analyzer;
@@ -0,0 +1,35 @@
1
+ {
2
+ "ruleId": "S019",
3
+ "name": "SMTP Injection Protection",
4
+ "description": "Detects potential SMTP/IMAP injection vulnerabilities by identifying unsanitized user input in email fields and direct SMTP protocol manipulation",
5
+ "category": "security",
6
+ "severity": "error",
7
+ "languages": ["typescript", "javascript"],
8
+ "tags": ["security", "owasp", "injection", "smtp", "email", "crlf"],
9
+ "enabled": true,
10
+ "fixable": false,
11
+ "engine": "heuristic",
12
+ "metadata": {
13
+ "owaspCategory": "A03:2021 - Injection",
14
+ "cweId": "CWE-93, CWE-144",
15
+ "impact": "High - Email spoofing, unauthorized email sending, header injection, spam",
16
+ "remediation": "Remove CRLF characters (\\r\\n) from user input before using in email fields. Use secure email service APIs (SendGrid, AWS SES, Mailgun) instead of direct SMTP manipulation. Validate email addresses with proper regex patterns.",
17
+ "references": [
18
+ "https://owasp.org/www-community/attacks/SMTP_Injection",
19
+ "https://cwe.mitre.org/data/definitions/93.html",
20
+ "https://cwe.mitre.org/data/definitions/144.html"
21
+ ],
22
+ "examples": {
23
+ "vulnerable": [
24
+ "sendMail({ to: req.body.email, subject: req.body.subject })",
25
+ "message.setSubject(userInput)",
26
+ "const headers = 'To: ' + req.query.recipient"
27
+ ],
28
+ "safe": [
29
+ "sendMail({ to: sanitize(req.body.email), subject: escape(req.body.subject) })",
30
+ "const cleanEmail = email.replace(/[\\r\\n]/g, '')",
31
+ "if (/^[a-zA-Z0-9@._-]+$/.test(email)) { sendMail({ to: email }) }"
32
+ ]
33
+ }
34
+ }
35
+ }