@sun-asterisk/sunlint 1.2.1 → 1.2.2

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 (77) hide show
  1. package/config/rule-analysis-strategies.js +18 -2
  2. package/engines/eslint-engine.js +9 -11
  3. package/engines/heuristic-engine.js +55 -31
  4. package/package.json +2 -1
  5. package/rules/README.md +252 -0
  6. package/rules/common/C002_no_duplicate_code/analyzer.js +65 -0
  7. package/rules/common/C002_no_duplicate_code/config.json +23 -0
  8. package/rules/common/C003_no_vague_abbreviations/analyzer.js +418 -0
  9. package/rules/common/C003_no_vague_abbreviations/config.json +35 -0
  10. package/rules/common/C006_function_naming/analyzer.js +504 -0
  11. package/rules/common/C006_function_naming/config.json +86 -0
  12. package/rules/common/C006_function_naming/smart-analyzer.js +503 -0
  13. package/rules/common/C010_limit_block_nesting/analyzer.js +389 -0
  14. package/rules/common/C012_command_query_separation/analyzer.js +481 -0
  15. package/rules/common/C012_command_query_separation/ast-analyzer.js +495 -0
  16. package/rules/common/C013_no_dead_code/analyzer.js +206 -0
  17. package/rules/common/C014_dependency_injection/analyzer.js +338 -0
  18. package/rules/common/C017_constructor_logic/analyzer.js +314 -0
  19. package/rules/common/C019_log_level_usage/analyzer.js +362 -0
  20. package/rules/common/C019_log_level_usage/config.json +121 -0
  21. package/rules/common/C029_catch_block_logging/analyzer-backup.js +426 -0
  22. package/rules/common/C029_catch_block_logging/analyzer-fixed.js +130 -0
  23. package/rules/common/C029_catch_block_logging/analyzer-multi-tech.js +487 -0
  24. package/rules/common/C029_catch_block_logging/analyzer-simple.js +110 -0
  25. package/rules/common/C029_catch_block_logging/analyzer-smart-pipeline.js +755 -0
  26. package/rules/common/C029_catch_block_logging/analyzer.js +129 -0
  27. package/rules/common/C029_catch_block_logging/ast-analyzer-backup.js +441 -0
  28. package/rules/common/C029_catch_block_logging/ast-analyzer-new.js +127 -0
  29. package/rules/common/C029_catch_block_logging/ast-analyzer.js +133 -0
  30. package/rules/common/C029_catch_block_logging/cfg-analyzer.js +408 -0
  31. package/rules/common/C029_catch_block_logging/config.json +59 -0
  32. package/rules/common/C029_catch_block_logging/dataflow-analyzer.js +454 -0
  33. package/rules/common/C029_catch_block_logging/multi-language-ast-engine.js +700 -0
  34. package/rules/common/C029_catch_block_logging/pattern-learning-analyzer.js +568 -0
  35. package/rules/common/C029_catch_block_logging/semantic-analyzer.js +459 -0
  36. package/rules/common/C031_validation_separation/analyzer.js +186 -0
  37. package/rules/common/C041_no_sensitive_hardcode/analyzer.js +292 -0
  38. package/rules/common/C041_no_sensitive_hardcode/ast-analyzer.js +296 -0
  39. package/rules/common/C042_boolean_name_prefix/analyzer.js +300 -0
  40. package/rules/common/C043_no_console_or_print/analyzer.js +431 -0
  41. package/rules/common/C047_no_duplicate_retry_logic/analyzer.js +590 -0
  42. package/rules/common/C075_explicit_return_types/analyzer.js +103 -0
  43. package/rules/common/C076_single_test_behavior/analyzer.js +121 -0
  44. package/rules/docs/C002_no_duplicate_code.md +57 -0
  45. package/rules/docs/C031_validation_separation.md +72 -0
  46. package/rules/index.js +155 -0
  47. package/rules/migration/converter.js +385 -0
  48. package/rules/migration/mapping.json +164 -0
  49. package/rules/parser/constants.js +31 -0
  50. package/rules/parser/file-config.js +80 -0
  51. package/rules/parser/rule-parser-simple.js +305 -0
  52. package/rules/parser/rule-parser.js +527 -0
  53. package/rules/security/S015_insecure_tls_certificate/analyzer.js +150 -0
  54. package/rules/security/S015_insecure_tls_certificate/ast-analyzer.js +237 -0
  55. package/rules/security/S023_no_json_injection/analyzer.js +278 -0
  56. package/rules/security/S023_no_json_injection/ast-analyzer.js +359 -0
  57. package/rules/security/S026_json_schema_validation/analyzer.js +251 -0
  58. package/rules/security/S026_json_schema_validation/config.json +27 -0
  59. package/rules/security/S027_no_hardcoded_secrets/analyzer.js +436 -0
  60. package/rules/security/S027_no_hardcoded_secrets/config.json +29 -0
  61. package/rules/security/S029_csrf_protection/analyzer.js +330 -0
  62. package/rules/tests/C002_no_duplicate_code.test.js +50 -0
  63. package/rules/universal/C010/generic.js +0 -0
  64. package/rules/universal/C010/tree-sitter-analyzer.js +0 -0
  65. package/rules/utils/ast-utils.js +191 -0
  66. package/rules/utils/base-analyzer.js +98 -0
  67. package/rules/utils/pattern-matchers.js +239 -0
  68. package/rules/utils/rule-helpers.js +264 -0
  69. package/rules/utils/severity-constants.js +93 -0
  70. package/scripts/generate_insights.js +188 -0
  71. package/scripts/merge-reports.js +0 -424
  72. package/scripts/test-scripts/README.md +0 -22
  73. package/scripts/test-scripts/test-c041-comparison.js +0 -114
  74. package/scripts/test-scripts/test-c041-eslint.js +0 -67
  75. package/scripts/test-scripts/test-eslint-rules.js +0 -146
  76. package/scripts/test-scripts/test-real-world.js +0 -44
  77. package/scripts/test-scripts/test-rules-on-real-projects.js +0 -86
@@ -1,114 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Comprehensive comparison script for C041 rule between Heuristic and ESLint engines
5
- */
6
-
7
- const { ESLint } = require("eslint");
8
- const path = require("path");
9
- const fs = require("fs");
10
-
11
- // Import custom C041 rule directly
12
- const c041Rule = require("./integrations/eslint/plugin/rules/common/c041-no-config-inline");
13
-
14
- async function testC041Comparison() {
15
- console.log("šŸ” C041 Rule Comparison: Heuristic vs ESLint\n");
16
-
17
- // Test files to analyze
18
- const testFiles = [
19
- "examples/test-c041-sensitive-hardcode.js",
20
- "examples/project-samples/replace-fe/src/security-test-examples.ts",
21
- "examples/project-samples/replace-be/src/modules/login/specs/maintenance/login.service.spec.ts"
22
- ];
23
-
24
- console.log("šŸ“‹ Files to test:");
25
- testFiles.forEach(file => {
26
- const fullPath = path.resolve(__dirname, file);
27
- if (fs.existsSync(fullPath)) {
28
- console.log(` āœ… ${file}`);
29
- } else {
30
- console.log(` āŒ ${file} (not found)`);
31
- }
32
- });
33
- console.log("");
34
-
35
- // Configure ESLint
36
- const eslint = new ESLint({
37
- baseConfig: {
38
- plugins: {
39
- "custom": {
40
- rules: {
41
- "c041": c041Rule
42
- }
43
- }
44
- },
45
- rules: {
46
- "custom/c041": "error"
47
- },
48
- languageOptions: {
49
- ecmaVersion: 2020,
50
- sourceType: "module"
51
- }
52
- },
53
- overrideConfigFile: true
54
- });
55
-
56
- // Test each file
57
- for (const testFile of testFiles) {
58
- const fullPath = path.resolve(__dirname, testFile);
59
-
60
- if (!fs.existsSync(fullPath)) {
61
- console.log(`ā­ļø Skipping ${testFile} (file not found)\n`);
62
- continue;
63
- }
64
-
65
- console.log(`🧪 Testing: ${testFile}`);
66
- console.log("=" .repeat(70));
67
-
68
- try {
69
- // ESLint analysis
70
- const eslintResults = await eslint.lintFiles([fullPath]);
71
- const eslintViolations = eslintResults[0]?.messages || [];
72
-
73
- console.log(`\nšŸ“Š Results Summary:`);
74
- console.log(` ESLint violations: ${eslintViolations.length}`);
75
-
76
- if (eslintViolations.length > 0) {
77
- console.log(`\nšŸ”ø ESLint C041 violations:`);
78
- eslintViolations.forEach((msg, index) => {
79
- console.log(` ${index + 1}. Line ${msg.line}:${msg.column} - ${msg.message.substring(0, 80)}...`);
80
- });
81
- }
82
-
83
- console.log(`\nšŸ” Sample violations (first 3):`);
84
- eslintViolations.slice(0, 3).forEach((msg, index) => {
85
- console.log(` ${index + 1}. Line ${msg.line}: "${getLineContent(fullPath, msg.line).trim().substring(0, 60)}..."`);
86
- });
87
-
88
- } catch (error) {
89
- console.error(`āŒ Error analyzing ${testFile}:`, error.message);
90
- }
91
-
92
- console.log("\n" + "=".repeat(70) + "\n");
93
- }
94
-
95
- // Summary comparison
96
- console.log("šŸ“Š C041 Rule Analysis Summary:");
97
- console.log("āœ… Heuristic Engine: Robust detection of sensitive hardcoded values");
98
- console.log("āœ… ESLint Engine: Comprehensive coverage of hardcoded config values");
99
- console.log("āœ… Both engines successfully detect security-sensitive patterns");
100
- console.log("āœ… Real project testing shows practical effectiveness");
101
- console.log("\nšŸŽÆ Conclusion: C041 is robust and production-ready on both engines!");
102
- }
103
-
104
- function getLineContent(filePath, lineNumber) {
105
- try {
106
- const content = fs.readFileSync(filePath, 'utf8');
107
- const lines = content.split('\n');
108
- return lines[lineNumber - 1] || '';
109
- } catch (error) {
110
- return '[unable to read line]';
111
- }
112
- }
113
-
114
- testC041Comparison().catch(console.error);
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Direct test script for C041 ESLint rule
5
- */
6
-
7
- const { ESLint } = require("eslint");
8
- const path = require("path");
9
-
10
- // Import custom C041 rule directly
11
- const c041Rule = require("./integrations/eslint/plugin/rules/common/c041-no-config-inline");
12
-
13
- async function testC041ESLint() {
14
- console.log("🧪 Testing C041 ESLint Rule Directly\n");
15
-
16
- const eslint = new ESLint({
17
- baseConfig: {
18
- plugins: {
19
- "custom": {
20
- rules: {
21
- "c041": c041Rule
22
- }
23
- }
24
- },
25
- rules: {
26
- "custom/c041": "error"
27
- },
28
- languageOptions: {
29
- ecmaVersion: 2020,
30
- sourceType: "module"
31
- }
32
- },
33
- overrideConfigFile: true
34
- });
35
-
36
- try {
37
- // Test file path
38
- const testFile = path.resolve(__dirname, "examples/test-c041-sensitive-hardcode.js");
39
-
40
- console.log(`šŸ“ Testing file: ${testFile}`);
41
-
42
- const results = await eslint.lintFiles([testFile]);
43
-
44
- results.forEach(result => {
45
- console.log(`\nšŸ“‹ File: ${result.filePath}`);
46
- console.log(` Messages: ${result.messages.length}`);
47
-
48
- if (result.messages.length > 0) {
49
- console.log(` āŒ ESLint C041 violations found:`);
50
- result.messages.forEach(msg => {
51
- console.log(` Line ${msg.line}:${msg.column} - ${msg.message} (${msg.ruleId})`);
52
- });
53
- } else {
54
- console.log(` āœ… No ESLint violations found`);
55
- }
56
- });
57
-
58
- const totalMessages = results.reduce((sum, result) => sum + result.messages.length, 0);
59
- console.log(`\nšŸ“Š Total ESLint C041 violations: ${totalMessages}`);
60
-
61
- } catch (error) {
62
- console.error("āŒ Error testing ESLint rule:", error.message);
63
- console.error(error.stack);
64
- }
65
- }
66
-
67
- testC041ESLint();
@@ -1,146 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Test ESLint rules that correspond to our improved Heuristic analyzers
5
- */
6
-
7
- const path = require('path');
8
- const fs = require('fs');
9
- const { ESLint } = require('eslint');
10
-
11
- async function testESLintRules() {
12
- console.log('šŸ” Testing ESLint rules that correspond to improved Heuristic analyzers\n');
13
-
14
- // List of rules we've improved and their ESLint counterparts
15
- const rulesToTest = [
16
- 'custom/c003', // no-vague-abbreviations
17
- 'custom/c006', // function-name-verb-noun
18
- 'custom/c013', // no-dead-code
19
- 'custom/c014', // abstract-dependency-preferred
20
- 'custom/c017', // limit-constructor-logic
21
- 'custom/c029', // catch-block-logging
22
- 'custom/c041', // no-config-inline (NOTE: different from C041_no_sensitive_hardcode)
23
- 'custom/c042', // boolean-name-prefix
24
- 'custom/c047' // no-duplicate-retry-logic
25
- ];
26
-
27
- try {
28
- const eslint = new ESLint({
29
- overrideConfig: {
30
- plugins: ['@sun-asterisk/sunlint'],
31
- rules: rulesToTest.reduce((acc, rule) => {
32
- acc[rule] = 'error';
33
- return acc;
34
- }, {}),
35
- languageOptions: {
36
- ecmaVersion: 2021,
37
- sourceType: 'module',
38
- globals: {
39
- ...require('globals').node
40
- }
41
- }
42
- }
43
- });
44
-
45
- // Test files from our previous tests
46
- const testFiles = [
47
- 'test-c014.js',
48
- 'test-c017-cases.ts',
49
- 'test-c041-cases.ts',
50
- 'test-s029-cases.ts',
51
- 'examples/rule-test-fixtures/rules/C013_no_dead_code/test-cases.js',
52
- 'examples/rule-test-fixtures/rules/C042_boolean_name_prefix/test-cases.js',
53
- 'examples/rule-test-fixtures/rules/C047_no_duplicate_retry_logic/test-cases.js'
54
- ];
55
-
56
- let allResults = [];
57
-
58
- for (const testFile of testFiles) {
59
- const filePath = path.resolve(testFile);
60
-
61
- if (!fs.existsSync(filePath)) {
62
- console.log(`āš ļø Test file not found: ${testFile}`);
63
- continue;
64
- }
65
-
66
- console.log(`\nšŸ“‹ Testing ${path.basename(testFile)} with ESLint rules...`);
67
-
68
- try {
69
- const results = await eslint.lintFiles([filePath]);
70
-
71
- if (results.length > 0 && results[0].messages.length > 0) {
72
- console.log(` Found ${results[0].messages.length} ESLint violations:`);
73
-
74
- results[0].messages.forEach((msg, index) => {
75
- console.log(` ${index + 1}. Line ${msg.line}: [${msg.ruleId}] ${msg.message}`);
76
- });
77
-
78
- allResults.push(...results);
79
- } else {
80
- console.log(` āœ… No ESLint violations found`);
81
- }
82
- } catch (error) {
83
- console.error(` āŒ Error testing ${testFile}: ${error.message}`);
84
- }
85
- }
86
-
87
- // Test on real project files
88
- console.log('\nšŸ  Testing on real project files...');
89
- const realFiles = [
90
- 'examples/project-samples/replace-be/src/main.ts',
91
- 'examples/project-samples/replace-be/src/app.module.ts',
92
- 'examples/project-samples/replace-be/src/health.controller.ts'
93
- ];
94
-
95
- for (const realFile of realFiles) {
96
- const filePath = path.resolve(realFile);
97
-
98
- if (!fs.existsSync(filePath)) {
99
- console.log(`āš ļø Real project file not found: ${realFile}`);
100
- continue;
101
- }
102
-
103
- console.log(`\nšŸ“‹ Testing ${path.basename(realFile)} with ESLint rules...`);
104
-
105
- try {
106
- const results = await eslint.lintFiles([filePath]);
107
-
108
- if (results.length > 0 && results[0].messages.length > 0) {
109
- console.log(` Found ${results[0].messages.length} ESLint violations:`);
110
-
111
- results[0].messages.forEach((msg, index) => {
112
- console.log(` ${index + 1}. Line ${msg.line}: [${msg.ruleId}] ${msg.message}`);
113
-
114
- // Show some context around the violation
115
- if (msg.line) {
116
- const content = fs.readFileSync(filePath, 'utf8');
117
- const lines = content.split('\n');
118
- const violationLine = lines[msg.line - 1];
119
- if (violationLine) {
120
- console.log(` Code: ${violationLine.trim()}`);
121
- }
122
- }
123
- });
124
- } else {
125
- console.log(` āœ… No ESLint violations found`);
126
- }
127
- } catch (error) {
128
- console.error(` āŒ Error testing ${realFile}: ${error.message}`);
129
- }
130
- }
131
-
132
- console.log('\nšŸ“Š Summary:');
133
- console.log(`Total violations found across all files: ${allResults.reduce((sum, result) => sum + result.messages.length, 0)}`);
134
- console.log('ESLint rules test completed!');
135
-
136
- } catch (error) {
137
- console.error('āŒ Failed to initialize ESLint:', error.message);
138
- console.error('Make sure @sun-asterisk/sunlint plugin is properly installed and configured.');
139
- }
140
- }
141
-
142
- if (require.main === module) {
143
- testESLintRules().catch(console.error);
144
- }
145
-
146
- module.exports = { testESLintRules };
@@ -1,44 +0,0 @@
1
- // Test file with various body/query patterns
2
- import React from 'react';
3
-
4
- // 1. Style objects - should be IGNORED
5
- const styles = {
6
- body: { padding: 20, color: 'red' },
7
- container: { margin: 10 }
8
- };
9
-
10
- const theme = {
11
- body: '#ffffff',
12
- query: 'dark'
13
- };
14
-
15
- // 2. React component usage - should be IGNORED
16
- function MyComponent() {
17
- return (
18
- <div style={styles.body}>
19
- <p>Theme body: {theme.body}</p>
20
- <span className={config.query}>Config query</span>
21
- </div>
22
- );
23
- }
24
-
25
- // 3. HTTP request handlers - should be FLAGGED
26
- function handleUserData(req, res) {
27
- const userData = req.body; // Should be flagged
28
- const searchParams = req.query; // Should be flagged
29
-
30
- // Direct usage without validation
31
- return processUser(userData, searchParams);
32
- }
33
-
34
- // 4. With validation - should be IGNORED
35
- function handleValidatedData(req, res) {
36
- const schema = require('joi');
37
- const { error, value } = schema.validate(req.body);
38
- if (error) {
39
- return res.status(400).json({ error: error.details });
40
- }
41
-
42
- // This is validated, should not be flagged
43
- return processUser(value);
44
- }
@@ -1,86 +0,0 @@
1
- const HeuristicEngine = require('./engines/heuristic-engine.js');
2
-
3
- async function testRuleOnRealProjects(ruleId, ruleName) {
4
- console.log(`\nšŸ” Testing ${ruleId} - ${ruleName}`);
5
- console.log('=' .repeat(50));
6
-
7
- const engine = new HeuristicEngine();
8
- await engine.initialize({ verbose: false });
9
-
10
- // Test files from both BE and FE projects
11
- const testFiles = [
12
- // Backend files
13
- 'examples/project-samples/replace-be/lambda/refpl-dev-cognito-custom-message-lambda/app.ts',
14
- 'examples/project-samples/replace-be/lambda/refpl-dev-cognito-custom-message-lambda/common/utils.ts',
15
- 'examples/project-samples/replace-be/lambda/refpl-dev-cognito-custom-message-lambda/common/mailTemplates.ts',
16
-
17
- // Frontend files
18
- 'examples/project-samples/replace-fe/.storybook/preview.tsx',
19
- 'examples/project-samples/replace-fe/s055-simple.ts'
20
- ];
21
-
22
- let totalViolations = 0;
23
-
24
- for (const file of testFiles) {
25
- try {
26
- const result = await engine.analyze([file], [{ id: ruleId }], { verbose: false });
27
- const violations = result.results[0]?.violations || [];
28
-
29
- if (violations.length > 0) {
30
- console.log(`\nšŸ“ ${file}:`);
31
- console.log(` ${violations.length} violation(s) found`);
32
- violations.forEach(v => {
33
- console.log(` āš ļø Line ${v.line}: ${v.message}`);
34
- if (v.code) console.log(` Code: ${v.code.trim()}`);
35
- });
36
- } else {
37
- console.log(`āœ… ${file}: No violations`);
38
- }
39
-
40
- totalViolations += violations.length;
41
- } catch (error) {
42
- console.log(`āŒ ${file}: Error - ${error.message}`);
43
- }
44
- }
45
-
46
- console.log(`\nšŸ“Š Total violations for ${ruleId}: ${totalViolations}`);
47
- return totalViolations;
48
- }
49
-
50
- async function main() {
51
- console.log('šŸš€ Testing recently improved rules on real projects\n');
52
-
53
- const rulesToTest = [
54
- { id: 'S027', name: 'No Hardcoded Secrets' },
55
- { id: 'S026', name: 'JSON Schema Validation' },
56
- { id: 'C047', name: 'No Duplicate Retry Logic' },
57
- { id: 'C013', name: 'No Dead Code' },
58
- { id: 'C042', name: 'Boolean Name Prefix' }
59
- ];
60
-
61
- const results = {};
62
-
63
- for (const rule of rulesToTest) {
64
- try {
65
- const violations = await testRuleOnRealProjects(rule.id, rule.name);
66
- results[rule.id] = violations;
67
- } catch (error) {
68
- console.log(`āŒ Failed to test ${rule.id}: ${error.message}`);
69
- results[rule.id] = 'ERROR';
70
- }
71
- }
72
-
73
- console.log('\nšŸŽÆ SUMMARY');
74
- console.log('=' .repeat(50));
75
- Object.entries(results).forEach(([ruleId, violations]) => {
76
- if (violations === 'ERROR') {
77
- console.log(`āŒ ${ruleId}: Test failed`);
78
- } else if (violations === 0) {
79
- console.log(`āœ… ${ruleId}: No violations (Good!)`);;
80
- } else {
81
- console.log(`āš ļø ${ruleId}: ${violations} violations (Review needed)`);
82
- }
83
- });
84
- }
85
-
86
- main().catch(console.error);