@sun-asterisk/sunlint 1.3.33 → 1.3.34
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/config/released-rules.json +62 -0
- package/config/rules/enhanced-rules-registry.json +2315 -1354
- package/core/adapters/dart-analyzer.js +658 -0
- package/core/adapters/index.js +102 -0
- package/core/adapters/sunlint-rule-adapter.js +0 -2
- package/core/adapters/typescript-analyzer.js +277 -0
- package/core/analysis-orchestrator.js +168 -40
- package/core/cli-action-handler.js +6 -19
- package/core/config-merger.js +24 -14
- package/core/constants/defaults.js +1 -2
- package/core/github-annotate-service.js +141 -89
- package/core/github-step-summary-generator.js +8 -8
- package/core/interfaces/language-analyzer.interface.js +393 -0
- package/core/output-service.js +15 -14
- package/core/rule-selection-service.js +77 -27
- package/core/semantic-engine-manager.js +375 -0
- package/core/semantic-engine.js +4 -57
- package/core/unified-rule-registry.js +52 -11
- package/docs/DART_RULE_EXECUTION_FLOW.md +745 -0
- package/docs/DART_SUPPORT_IMPLEMENTATION.md +245 -0
- package/docs/SUNLINT_ARCHITECTURE.md +692 -0
- package/docs/skills/CREATE_DART_RULE.md +909 -0
- package/engines/eslint-engine.js +2 -8
- package/engines/heuristic-engine.js +234 -38
- package/package.json +1 -1
- package/rules/common/C002_no_duplicate_code/config.json +12 -20
- package/rules/common/C002_no_duplicate_code/dart/analyzer.js +53 -0
- package/rules/common/C002_no_duplicate_code/index.js +93 -0
- package/rules/common/C003_no_vague_abbreviations/config.json +1 -1
- package/rules/common/C003_no_vague_abbreviations/dart/analyzer.js +54 -0
- package/rules/common/C003_no_vague_abbreviations/index.js +93 -0
- package/rules/common/C006_function_naming/dart/analyzer.js +40 -0
- package/rules/common/C006_function_naming/index.js +86 -0
- package/rules/common/C008_variable_declaration_locality/dart/analyzer.js +32 -0
- package/rules/common/C008_variable_declaration_locality/index.js +86 -0
- package/rules/common/C010_limit_block_nesting/dart/analyzer.js +32 -0
- package/rules/common/C010_limit_block_nesting/index.js +86 -0
- package/rules/common/C012_command_query_separation/config.json +61 -0
- package/rules/common/C012_command_query_separation/dart/analyzer.js +32 -0
- package/rules/common/C012_command_query_separation/index.js +86 -0
- package/rules/common/C013_no_dead_code/dart/analyzer.js +32 -0
- package/rules/common/C013_no_dead_code/index.js +86 -0
- package/rules/common/C014_dependency_injection/dart/analyzer.js +32 -0
- package/rules/common/C014_dependency_injection/index.js +86 -0
- package/rules/common/C017_constructor_logic/dart/analyzer.js +32 -0
- package/rules/common/C017_constructor_logic/index.js +86 -0
- package/rules/common/C018_no_throw_generic_error/dart/analyzer.js +32 -0
- package/rules/common/C018_no_throw_generic_error/index.js +86 -0
- package/rules/common/C019_log_level_usage/dart/analyzer.js +32 -0
- package/rules/common/C019_log_level_usage/index.js +86 -0
- package/rules/common/C019_log_level_usage/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
- package/rules/common/C020_unused_imports/dart/analyzer.js +32 -0
- package/rules/common/C020_unused_imports/index.js +86 -0
- package/rules/common/C020_unused_imports/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
- package/rules/common/C021_import_organization/config.json +29 -9
- package/rules/common/C021_import_organization/dart/analyzer.js +40 -0
- package/rules/common/C021_import_organization/index.js +83 -0
- package/rules/common/C021_import_organization/{ts-morph-analyzer.js → typescript/ts-morph-analyzer.js} +0 -1
- package/rules/common/C023_no_duplicate_variable/config.json +7 -2
- package/rules/common/C023_no_duplicate_variable/dart/analyzer.js +40 -0
- package/rules/common/C023_no_duplicate_variable/index.js +83 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/config.json +7 -2
- package/rules/common/C024_no_scatter_hardcoded_constants/dart/analyzer.js +40 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/index.js +83 -0
- package/rules/common/C024_no_scatter_hardcoded_constants/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -1
- package/rules/common/C029_catch_block_logging/config.json +15 -5
- package/rules/common/C029_catch_block_logging/dart/analyzer.js +40 -0
- package/rules/common/C029_catch_block_logging/index.js +83 -0
- package/rules/common/C030_use_custom_error_classes/config.json +28 -0
- package/rules/common/C030_use_custom_error_classes/dart/analyzer.js +40 -0
- package/rules/common/C030_use_custom_error_classes/index.js +83 -0
- package/rules/common/C031_validation_separation/config.json +28 -0
- package/rules/common/C031_validation_separation/dart/analyzer.js +40 -0
- package/rules/common/C031_validation_separation/index.js +83 -0
- package/rules/common/C033_separate_service_repository/config.json +8 -3
- package/rules/common/C033_separate_service_repository/dart/analyzer.js +40 -0
- package/rules/common/C033_separate_service_repository/index.js +83 -0
- package/rules/common/C035_error_logging_context/config.json +34 -12
- package/rules/common/C035_error_logging_context/dart/analyzer.js +40 -0
- package/rules/common/C035_error_logging_context/index.js +83 -0
- package/rules/common/C040_centralized_validation/config.json +37 -8
- package/rules/common/C040_centralized_validation/dart/analyzer.js +40 -0
- package/rules/common/C040_centralized_validation/index.js +83 -0
- package/rules/common/C041_no_sensitive_hardcode/config.json +7 -2
- package/rules/common/C041_no_sensitive_hardcode/dart/analyzer.js +40 -0
- package/rules/common/C041_no_sensitive_hardcode/index.js +83 -0
- package/rules/common/C042_boolean_name_prefix/config.json +28 -0
- package/rules/common/C042_boolean_name_prefix/dart/analyzer.js +40 -0
- package/rules/common/C042_boolean_name_prefix/index.js +83 -0
- package/rules/common/C043_no_console_or_print/config.json +28 -0
- package/rules/common/C043_no_console_or_print/dart/analyzer.js +40 -0
- package/rules/common/C043_no_console_or_print/index.js +83 -0
- package/rules/common/C047_no_duplicate_retry_logic/config.json +28 -0
- package/rules/common/C047_no_duplicate_retry_logic/dart/analyzer.js +40 -0
- package/rules/common/C047_no_duplicate_retry_logic/index.js +83 -0
- package/rules/common/C048_no_bypass_architectural_layers/config.json +7 -2
- package/rules/common/C048_no_bypass_architectural_layers/dart/analyzer.js +40 -0
- package/rules/common/C048_no_bypass_architectural_layers/index.js +83 -0
- package/rules/common/C052_parsing_or_data_transformation/config.json +7 -2
- package/rules/common/C052_parsing_or_data_transformation/dart/analyzer.js +40 -0
- package/rules/common/C052_parsing_or_data_transformation/index.js +83 -0
- package/rules/common/C060_no_override_superclass/config.json +7 -2
- package/rules/common/C060_no_override_superclass/dart/analyzer.js +40 -0
- package/rules/common/C060_no_override_superclass/index.js +83 -0
- package/rules/common/C065_one_behavior_per_test/config.json +187 -28
- package/rules/common/C065_one_behavior_per_test/dart/analyzer.js +40 -0
- package/rules/common/C065_one_behavior_per_test/index.js +83 -0
- package/rules/common/C067_no_hardcoded_config/config.json +18 -4
- package/rules/common/C067_no_hardcoded_config/dart/analyzer.js +40 -0
- package/rules/common/C067_no_hardcoded_config/index.js +83 -0
- package/rules/common/C070_no_real_time_tests/config.json +41 -12
- package/rules/common/C070_no_real_time_tests/dart/analyzer.js +40 -0
- package/rules/common/C070_no_real_time_tests/index.js +83 -0
- package/rules/common/C072_single_test_behavior/config.json +28 -0
- package/rules/common/C072_single_test_behavior/dart/analyzer.js +40 -0
- package/rules/common/C072_single_test_behavior/index.js +83 -0
- package/rules/common/C073_validate_required_config_on_startup/config.json +93 -18
- package/rules/common/C073_validate_required_config_on_startup/dart/analyzer.js +40 -0
- package/rules/common/C073_validate_required_config_on_startup/index.js +83 -0
- package/rules/common/C073_validate_required_config_on_startup/{analyzer.js → typescript/analyzer.js} +0 -1
- package/rules/common/C075_explicit_return_types/config.json +28 -0
- package/rules/common/C075_explicit_return_types/dart/analyzer.js +40 -0
- package/rules/common/C075_explicit_return_types/index.js +83 -0
- package/rules/common/C076_explicit_function_types/config.json +18 -4
- package/rules/common/C076_explicit_function_types/dart/analyzer.js +40 -0
- package/rules/common/C076_explicit_function_types/index.js +83 -0
- package/rules/index.js +26 -6
- package/rules/security/S003_open_redirect_protection/config.json +11 -53
- package/rules/security/S003_open_redirect_protection/dart/analyzer.js +43 -0
- package/rules/security/S003_open_redirect_protection/index.js +94 -0
- package/rules/security/S003_open_redirect_protection/typescript/analyzer.js +105 -0
- package/rules/security/S003_open_redirect_protection/{symbol-based-analyzer.js → typescript/semantic-analyzer.js} +1 -1
- package/rules/security/S004_sensitive_data_logging/config.json +1 -1
- package/rules/security/S004_sensitive_data_logging/dart/analyzer.js +58 -0
- package/rules/security/S004_sensitive_data_logging/index.js +93 -0
- package/rules/security/S005_no_origin_auth/dart/analyzer.js +30 -0
- package/rules/security/S005_no_origin_auth/index.js +83 -0
- package/rules/security/S005_no_origin_auth/{analyzer.js → typescript/analyzer.js} +1 -0
- package/rules/security/S006_no_plaintext_recovery_codes/dart/analyzer.js +30 -0
- package/rules/security/S006_no_plaintext_recovery_codes/index.js +83 -0
- package/rules/security/S007_no_plaintext_otp/dart/analyzer.js +30 -0
- package/rules/security/S007_no_plaintext_otp/index.js +83 -0
- package/rules/security/S009_no_insecure_encryption/dart/analyzer.js +30 -0
- package/rules/security/S009_no_insecure_encryption/index.js +83 -0
- package/rules/security/S010_no_insecure_encryption/dart/analyzer.js +30 -0
- package/rules/security/S010_no_insecure_encryption/index.js +83 -0
- package/rules/security/S011_secure_guid_generation/dart/analyzer.js +30 -0
- package/rules/security/S011_secure_guid_generation/index.js +83 -0
- package/rules/security/S012_hardcoded_secrets/dart/analyzer.js +30 -0
- package/rules/security/S012_hardcoded_secrets/index.js +83 -0
- package/rules/security/S012_hardcoded_secrets/typescript/config.json +75 -0
- package/rules/security/S013_tls_enforcement/dart/analyzer.js +30 -0
- package/rules/security/S013_tls_enforcement/index.js +83 -0
- package/rules/security/S014_tls_version_enforcement/dart/analyzer.js +30 -0
- package/rules/security/S014_tls_version_enforcement/index.js +83 -0
- package/rules/security/S015_insecure_tls_certificate/config.json +41 -0
- package/rules/security/S015_insecure_tls_certificate/dart/analyzer.js +19 -0
- package/rules/security/S015_insecure_tls_certificate/index.js +83 -0
- package/rules/security/S016_no_sensitive_querystring/dart/analyzer.js +30 -0
- package/rules/security/S016_no_sensitive_querystring/index.js +83 -0
- package/rules/security/S017_use_parameterized_queries/dart/analyzer.js +30 -0
- package/rules/security/S017_use_parameterized_queries/index.js +83 -0
- package/rules/security/S019_smtp_injection_protection/dart/analyzer.js +30 -0
- package/rules/security/S019_smtp_injection_protection/index.js +83 -0
- package/rules/security/S020_no_eval_dynamic_code/dart/analyzer.js +30 -0
- package/rules/security/S020_no_eval_dynamic_code/index.js +83 -0
- package/rules/security/S022_escape_output_context/dart/analyzer.js +30 -0
- package/rules/security/S022_escape_output_context/index.js +83 -0
- package/rules/security/S023_no_json_injection/dart/analyzer.js +30 -0
- package/rules/security/S023_no_json_injection/index.js +83 -0
- package/rules/security/S024_xpath_xxe_protection/dart/analyzer.js +30 -0
- package/rules/security/S024_xpath_xxe_protection/index.js +83 -0
- package/rules/security/S025_server_side_validation/dart/analyzer.js +30 -0
- package/rules/security/S025_server_side_validation/index.js +83 -0
- package/rules/security/S026_json_schema_validation/dart/analyzer.js +30 -0
- package/rules/security/S026_json_schema_validation/index.js +83 -0
- package/rules/security/S027_no_hardcoded_secrets/dart/analyzer.js +30 -0
- package/rules/security/S027_no_hardcoded_secrets/index.js +83 -0
- package/rules/security/S028_file_upload_size_limits/dart/analyzer.js +30 -0
- package/rules/security/S028_file_upload_size_limits/index.js +83 -0
- package/rules/security/S029_csrf_protection/dart/analyzer.js +30 -0
- package/rules/security/S029_csrf_protection/index.js +83 -0
- package/rules/security/S030_directory_browsing_protection/dart/analyzer.js +30 -0
- package/rules/security/S030_directory_browsing_protection/index.js +83 -0
- package/rules/security/S031_secure_session_cookies/dart/analyzer.js +30 -0
- package/rules/security/S031_secure_session_cookies/index.js +83 -0
- package/rules/security/S032_httponly_session_cookies/dart/analyzer.js +30 -0
- package/rules/security/S032_httponly_session_cookies/index.js +83 -0
- package/rules/security/S033_samesite_session_cookies/dart/analyzer.js +30 -0
- package/rules/security/S033_samesite_session_cookies/index.js +83 -0
- package/rules/security/S034_host_prefix_session_cookies/dart/analyzer.js +30 -0
- package/rules/security/S034_host_prefix_session_cookies/index.js +83 -0
- package/rules/security/S035_path_session_cookies/dart/analyzer.js +30 -0
- package/rules/security/S035_path_session_cookies/index.js +83 -0
- package/rules/security/S036_lfi_rfi_protection/dart/analyzer.js +30 -0
- package/rules/security/S036_lfi_rfi_protection/index.js +83 -0
- package/rules/security/S037_cache_headers/dart/analyzer.js +30 -0
- package/rules/security/S037_cache_headers/index.js +83 -0
- package/rules/security/S038_no_version_headers/dart/analyzer.js +30 -0
- package/rules/security/S038_no_version_headers/index.js +83 -0
- package/rules/security/S039_no_session_tokens_in_url/dart/analyzer.js +30 -0
- package/rules/security/S039_no_session_tokens_in_url/index.js +83 -0
- package/rules/security/S040_session_fixation_protection/dart/analyzer.js +30 -0
- package/rules/security/S040_session_fixation_protection/index.js +83 -0
- package/rules/security/S041_session_token_invalidation/dart/analyzer.js +30 -0
- package/rules/security/S041_session_token_invalidation/index.js +83 -0
- package/rules/security/S042_require_re_authentication_for_long_lived/dart/analyzer.js +30 -0
- package/rules/security/S042_require_re_authentication_for_long_lived/index.js +83 -0
- package/rules/security/S043_password_changes_invalidate_all_sessions/dart/analyzer.js +30 -0
- package/rules/security/S043_password_changes_invalidate_all_sessions/index.js +83 -0
- package/rules/security/S044_re_authentication_required/dart/analyzer.js +30 -0
- package/rules/security/S044_re_authentication_required/index.js +83 -0
- package/rules/security/S045_brute_force_protection/dart/analyzer.js +30 -0
- package/rules/security/S045_brute_force_protection/index.js +83 -0
- package/rules/security/S048_no_current_password_in_reset/dart/analyzer.js +30 -0
- package/rules/security/S048_no_current_password_in_reset/index.js +83 -0
- package/rules/security/S049_short_validity_tokens/dart/analyzer.js +30 -0
- package/rules/security/S049_short_validity_tokens/index.js +83 -0
- package/rules/security/S049_short_validity_tokens/typescript/config.json +124 -0
- package/rules/security/S051_password_length_policy/dart/analyzer.js +30 -0
- package/rules/security/S051_password_length_policy/index.js +83 -0
- package/rules/security/S051_password_length_policy/typescript/config.json +83 -0
- package/rules/security/S052_weak_otp_entropy/dart/analyzer.js +30 -0
- package/rules/security/S052_weak_otp_entropy/index.js +83 -0
- package/rules/security/S052_weak_otp_entropy/typescript/config.json +57 -0
- package/rules/security/S054_no_default_accounts/dart/analyzer.js +30 -0
- package/rules/security/S054_no_default_accounts/index.js +83 -0
- package/rules/security/S054_no_default_accounts/typescript/config.json +101 -0
- package/rules/security/S055_content_type_validation/dart/analyzer.js +30 -0
- package/rules/security/S055_content_type_validation/index.js +83 -0
- package/rules/security/S056_log_injection_protection/dart/analyzer.js +30 -0
- package/rules/security/S056_log_injection_protection/index.js +83 -0
- package/rules/security/S057_utc_logging/dart/analyzer.js +30 -0
- package/rules/security/S057_utc_logging/index.js +83 -0
- package/rules/security/S057_utc_logging/typescript/config.json +105 -0
- package/rules/security/S058_no_ssrf/dart/analyzer.js +30 -0
- package/rules/security/S058_no_ssrf/index.js +83 -0
- package/rules/security/S058_no_ssrf/{analyzer.js → typescript/analyzer.js} +0 -1
- package/rules/security/S058_no_ssrf/typescript/config.json +125 -0
- package/scripts/build-release.sh +12 -0
- package/rules/common/C002_no_duplicate_code/test-cases/api-handlers.ts +0 -64
- package/rules/common/C002_no_duplicate_code/test-cases/data-processor.ts +0 -46
- package/rules/common/C002_no_duplicate_code/test-cases/good-example.tsx +0 -40
- package/rules/common/C002_no_duplicate_code/test-cases/product-service.ts +0 -57
- package/rules/common/C002_no_duplicate_code/test-cases/user-service.ts +0 -49
- package/rules/common/C067_no_hardcoded_config/symbol-based-analyzer.js.backup +0 -3853
- package/rules/security/S003_open_redirect_protection/analyzer.js +0 -135
- /package/rules/common/C002_no_duplicate_code/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C003_no_vague_abbreviations/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C006_function_naming/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/{C008 → C008_variable_declaration_locality}/config.json +0 -0
- /package/rules/common/{C008 → C008_variable_declaration_locality/typescript}/analyzer.js +0 -0
- /package/rules/common/{C008 → C008_variable_declaration_locality/typescript}/ts-morph-analyzer.js +0 -0
- /package/rules/common/C010_limit_block_nesting/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C010_limit_block_nesting/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/common/C010_limit_block_nesting/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C012_command_query_separation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C012_command_query_separation/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
- /package/rules/common/C013_no_dead_code/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C013_no_dead_code/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/common/C013_no_dead_code/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C014_dependency_injection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C014_dependency_injection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C017_constructor_logic/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C017_constructor_logic/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C018_no_throw_generic_error/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C018_no_throw_generic_error/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/common/C018_no_throw_generic_error/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C019_log_level_usage/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C019_log_level_usage/{pattern-analyzer.js → typescript/pattern-analyzer.js} +0 -0
- /package/rules/common/C019_log_level_usage/{system-log-analyzer.js → typescript/system-log-analyzer.js} +0 -0
- /package/rules/common/C020_unused_imports/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C021_import_organization/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C023_no_duplicate_variable/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C023_no_duplicate_variable/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C024_no_scatter_hardcoded_constants/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C029_catch_block_logging/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C030_use_custom_error_classes/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C031_validation_separation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C033_separate_service_repository/{README.md → typescript/README.md} +0 -0
- /package/rules/common/C033_separate_service_repository/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C033_separate_service_repository/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/common/C033_separate_service_repository/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C035_error_logging_context/{STRATEGY.md → typescript/STRATEGY.md} +0 -0
- /package/rules/common/C035_error_logging_context/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C035_error_logging_context/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/common/C035_error_logging_context/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C040_centralized_validation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C040_centralized_validation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/common/C040_centralized_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C041_no_sensitive_hardcode/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C041_no_sensitive_hardcode/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C042_boolean_name_prefix/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C043_no_console_or_print/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C047_no_duplicate_retry_logic/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C047_no_duplicate_retry_logic/{c047-semantic-rule.js → typescript/c047-semantic-rule.js} +0 -0
- /package/rules/common/C047_no_duplicate_retry_logic/{symbol-analyzer-enhanced.js → typescript/symbol-analyzer-enhanced.js} +0 -0
- /package/rules/common/C047_no_duplicate_retry_logic/{symbol-config.json → typescript/symbol-config.json} +0 -0
- /package/rules/common/C048_no_bypass_architectural_layers/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C048_no_bypass_architectural_layers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C052_parsing_or_data_transformation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C052_parsing_or_data_transformation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C060_no_override_superclass/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C060_no_override_superclass/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C065_one_behavior_per_test/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C067_no_hardcoded_config/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C067_no_hardcoded_config/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C070_no_real_time_tests/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C070_no_real_time_tests/{regex-analyzer.js → typescript/regex-analyzer.js} +0 -0
- /package/rules/common/C072_single_test_behavior/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C073_validate_required_config_on_startup/{README.md → typescript/README.md} +0 -0
- /package/rules/common/C073_validate_required_config_on_startup/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/common/C075_explicit_return_types/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C076_explicit_function_types/{README.md → typescript/README.md} +0 -0
- /package/rules/common/C076_explicit_function_types/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/common/C076_explicit_function_types/{semantic-analyzer.js → typescript/semantic-analyzer.js} +0 -0
- /package/rules/security/S003_open_redirect_protection/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S004_sensitive_data_logging/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S004_sensitive_data_logging/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S005_no_origin_auth/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S005_no_origin_auth/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
- /package/rules/security/S005_no_origin_auth/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S006_no_plaintext_recovery_codes/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S006_no_plaintext_recovery_codes/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S006_no_plaintext_recovery_codes/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S007_no_plaintext_otp/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S007_no_plaintext_otp/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S007_no_plaintext_otp/{semantic-analyzer.js → typescript/semantic-analyzer.js} +0 -0
- /package/rules/security/S007_no_plaintext_otp/{semantic-config.json → typescript/semantic-config.json} +0 -0
- /package/rules/security/S007_no_plaintext_otp/{semantic-wrapper.js → typescript/semantic-wrapper.js} +0 -0
- /package/rules/security/S009_no_insecure_encryption/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S009_no_insecure_encryption/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S010_no_insecure_encryption/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S010_no_insecure_encryption/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S011_secure_guid_generation/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S011_secure_guid_generation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S011_secure_guid_generation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S012_hardcoded_secrets/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S012_hardcoded_secrets/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S013_tls_enforcement/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S013_tls_enforcement/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S013_tls_enforcement/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S014_tls_version_enforcement/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S014_tls_version_enforcement/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S014_tls_version_enforcement/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S015_insecure_tls_certificate/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S015_insecure_tls_certificate/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
- /package/rules/security/S016_no_sensitive_querystring/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S016_no_sensitive_querystring/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S016_no_sensitive_querystring/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S017_use_parameterized_queries/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S017_use_parameterized_queries/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S017_use_parameterized_queries/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S019_smtp_injection_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S019_smtp_injection_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S020_no_eval_dynamic_code/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S020_no_eval_dynamic_code/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S020_no_eval_dynamic_code/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S022_escape_output_context/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S022_escape_output_context/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S023_no_json_injection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S023_no_json_injection/{ast-analyzer.js → typescript/ast-analyzer.js} +0 -0
- /package/rules/security/S024_xpath_xxe_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S024_xpath_xxe_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S024_xpath_xxe_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S025_server_side_validation/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S025_server_side_validation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S025_server_side_validation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S025_server_side_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S026_json_schema_validation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S027_no_hardcoded_secrets/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S027_no_hardcoded_secrets/{categories.json → typescript/categories.json} +0 -0
- /package/rules/security/S027_no_hardcoded_secrets/{categorized-analyzer.js → typescript/categorized-analyzer.js} +0 -0
- /package/rules/security/S028_file_upload_size_limits/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S028_file_upload_size_limits/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S028_file_upload_size_limits/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S029_csrf_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S030_directory_browsing_protection/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S030_directory_browsing_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S030_directory_browsing_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S030_directory_browsing_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S031_secure_session_cookies/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S031_secure_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S031_secure_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S032_httponly_session_cookies/{FRAMEWORK_SUPPORT.md → typescript/FRAMEWORK_SUPPORT.md} +0 -0
- /package/rules/security/S032_httponly_session_cookies/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S032_httponly_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S032_httponly_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S032_httponly_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S033_samesite_session_cookies/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S033_samesite_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S033_samesite_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S033_samesite_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S034_host_prefix_session_cookies/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S034_host_prefix_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S034_host_prefix_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S034_host_prefix_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S035_path_session_cookies/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S035_path_session_cookies/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S035_path_session_cookies/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S035_path_session_cookies/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S036_lfi_rfi_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S037_cache_headers/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S037_cache_headers/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S037_cache_headers/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S037_cache_headers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S038_no_version_headers/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S038_no_version_headers/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S038_no_version_headers/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S038_no_version_headers/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S039_no_session_tokens_in_url/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S039_no_session_tokens_in_url/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S039_no_session_tokens_in_url/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S039_no_session_tokens_in_url/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S040_session_fixation_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S041_session_token_invalidation/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S041_session_token_invalidation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S041_session_token_invalidation/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S041_session_token_invalidation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S042_require_re_authentication_for_long_lived/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S042_require_re_authentication_for_long_lived/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S042_require_re_authentication_for_long_lived/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S043_password_changes_invalidate_all_sessions/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S043_password_changes_invalidate_all_sessions/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S043_password_changes_invalidate_all_sessions/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S044_re_authentication_required/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S044_re_authentication_required/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S044_re_authentication_required/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S044_re_authentication_required/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S045_brute_force_protection/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S045_brute_force_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S045_brute_force_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S048_no_current_password_in_reset/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S048_no_current_password_in_reset/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S049_short_validity_tokens/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S049_short_validity_tokens/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S049_short_validity_tokens/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S051_password_length_policy/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S052_weak_otp_entropy/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S054_no_default_accounts/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S054_no_default_accounts/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S055_content_type_validation/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S055_content_type_validation/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S055_content_type_validation/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S056_log_injection_protection/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S056_log_injection_protection/{regex-based-analyzer.js → typescript/regex-based-analyzer.js} +0 -0
- /package/rules/security/S056_log_injection_protection/{symbol-based-analyzer.js → typescript/symbol-based-analyzer.js} +0 -0
- /package/rules/security/S057_utc_logging/{README.md → typescript/README.md} +0 -0
- /package/rules/security/S057_utc_logging/{analyzer.js → typescript/analyzer.js} +0 -0
- /package/rules/security/S058_no_ssrf/{README.md → typescript/README.md} +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C076 Dart Analyzer - Explicit Function Types
|
|
3
|
+
*
|
|
4
|
+
* This is a JS wrapper that delegates to DartAnalyzer binary.
|
|
5
|
+
* Actual implementation: dart_analyzer/lib/rules/C076_explicit_function_types.dart
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
class DartC076Analyzer {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.ruleId = 'C076';
|
|
11
|
+
this.language = 'dart';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
getMetadata() {
|
|
15
|
+
return {
|
|
16
|
+
ruleId: 'C076',
|
|
17
|
+
name: 'Explicit Function Types',
|
|
18
|
+
language: 'dart',
|
|
19
|
+
delegateTo: 'dart_analyzer',
|
|
20
|
+
description: 'Function parameters should have explicit type annotations'
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getConfig() {
|
|
25
|
+
return {
|
|
26
|
+
severity: 'warning'
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async analyze(files, language, options) {
|
|
31
|
+
// Delegated to DartAnalyzer binary via heuristic-engine.js
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
supportsLanguage(language) {
|
|
36
|
+
return language === 'dart';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = DartC076Analyzer;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C076 Rule Router - Explicit Function Types
|
|
3
|
+
*
|
|
4
|
+
* Routes analysis to the appropriate language-specific analyzer.
|
|
5
|
+
* Supports: TypeScript, JavaScript
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
class C076Router {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.analyzers = new Map();
|
|
13
|
+
this.ruleId = 'C076';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getAnalyzer(language) {
|
|
17
|
+
const normalizedLang = this.normalizeLanguage(language);
|
|
18
|
+
|
|
19
|
+
if (!this.analyzers.has(normalizedLang)) {
|
|
20
|
+
try {
|
|
21
|
+
const analyzerPath = path.join(__dirname, normalizedLang, 'analyzer.js');
|
|
22
|
+
const AnalyzerClass = require(analyzerPath);
|
|
23
|
+
this.analyzers.set(normalizedLang, new AnalyzerClass());
|
|
24
|
+
} catch (error) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return this.analyzers.get(normalizedLang);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
normalizeLanguage(language) {
|
|
33
|
+
if (typeof language !== 'string') {
|
|
34
|
+
return 'typescript';
|
|
35
|
+
}
|
|
36
|
+
const languageMap = {
|
|
37
|
+
'typescript': 'typescript',
|
|
38
|
+
'javascript': 'typescript',
|
|
39
|
+
'ts': 'typescript',
|
|
40
|
+
'js': 'typescript'
|
|
41
|
+
};
|
|
42
|
+
return languageMap[language.toLowerCase()] || 'typescript';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
supportsLanguage(language) {
|
|
46
|
+
if (typeof language !== 'string') return false;
|
|
47
|
+
const supported = ['typescript', 'javascript', 'ts', 'js'];
|
|
48
|
+
return supported.includes(language.toLowerCase());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getSupportedLanguages() {
|
|
52
|
+
return ['typescript', 'javascript'];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async analyze(files, language, options = {}) {
|
|
56
|
+
const analyzer = this.getAnalyzer(language);
|
|
57
|
+
if (!analyzer) return [];
|
|
58
|
+
if (typeof analyzer.analyze === 'function') {
|
|
59
|
+
return analyzer.analyze(files, language, options);
|
|
60
|
+
}
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async initialize(semanticEngineOrLanguage = null, semanticEngine = null) {
|
|
65
|
+
let engine = semanticEngine;
|
|
66
|
+
let lang = null;
|
|
67
|
+
|
|
68
|
+
if (typeof semanticEngineOrLanguage === 'string') {
|
|
69
|
+
lang = semanticEngineOrLanguage;
|
|
70
|
+
} else if (semanticEngineOrLanguage && typeof semanticEngineOrLanguage === 'object') {
|
|
71
|
+
engine = semanticEngineOrLanguage;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (lang) {
|
|
75
|
+
const analyzer = this.getAnalyzer(lang);
|
|
76
|
+
if (analyzer && typeof analyzer.initialize === 'function') {
|
|
77
|
+
await analyzer.initialize(engine);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = new C076Router();
|
package/rules/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SunLint Heuristic Rules Registry
|
|
3
|
-
* Central
|
|
4
|
-
S015: require('./security/S015_insecure_tls_certificate/analyzer'),
|
|
5
|
-
S023: require('./security/S023_no_json_injection/analyzer'),stry for all heuristic rules organized by category
|
|
3
|
+
* Central registry for all heuristic rules organized by category
|
|
6
4
|
*/
|
|
7
5
|
|
|
8
6
|
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Load rule analyzer from category folder
|
|
11
|
+
* Supports both old structure (analyzer.js) and new multi-language structure (index.js router)
|
|
12
|
+
*
|
|
12
13
|
* @param {string} category - Rule category (common, security, typescript)
|
|
13
14
|
* @param {string} ruleId - Rule ID (e.g., C006_function_naming)
|
|
14
15
|
* @returns {Object} Rule analyzer module
|
|
@@ -21,7 +22,18 @@ function loadRule(category, ruleId) {
|
|
|
21
22
|
console.log(`🔬 Loading C047 semantic analyzer: ${semanticPath}`);
|
|
22
23
|
return require(semanticPath);
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
+
|
|
26
|
+
// Try new multi-language structure first (index.js router)
|
|
27
|
+
const routerPath = path.join(__dirname, category, ruleId, 'index.js');
|
|
28
|
+
try {
|
|
29
|
+
if (fs.existsSync(routerPath)) {
|
|
30
|
+
return require(routerPath);
|
|
31
|
+
}
|
|
32
|
+
} catch (routerError) {
|
|
33
|
+
// Fall through to old structure
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Fallback to old structure (analyzer.js)
|
|
25
37
|
const rulePath = path.join(__dirname, category, ruleId, 'analyzer.js');
|
|
26
38
|
return require(rulePath);
|
|
27
39
|
} catch (error) {
|
|
@@ -48,13 +60,17 @@ function loadRuleConfig(category, ruleId) {
|
|
|
48
60
|
|
|
49
61
|
// 🔹 Common Rules (C-series) - General coding standards
|
|
50
62
|
const commonRules = {
|
|
63
|
+
// Multi-language rules (TypeScript + Dart)
|
|
51
64
|
C002: loadRule('common', 'C002_no_duplicate_code'),
|
|
65
|
+
C003: loadRule('common', 'C003_no_vague_abbreviations'),
|
|
66
|
+
|
|
67
|
+
// TypeScript-only rules (existing)
|
|
52
68
|
C006: loadRule('common', 'C006_function_naming'),
|
|
53
69
|
C012: loadRule('common', 'C012_command_query_separation'),
|
|
54
70
|
C013: loadRule('common', 'C013_no_dead_code'),
|
|
55
71
|
C014: loadRule('common', 'C014_dependency_injection'),
|
|
56
72
|
C018: loadRule('common', 'C018_no_throw_generic_error'),
|
|
57
|
-
C019: loadRule('common', 'C019_log_level_usage'),
|
|
73
|
+
C019: loadRule('common', 'C019_log_level_usage'),
|
|
58
74
|
C030: loadRule('common', 'C030_use_custom_error_classes'),
|
|
59
75
|
C023: loadRule('common', 'C023_no_duplicate_variable'),
|
|
60
76
|
C024: loadRule('common', 'C024_no_scatter_hardcoded_constants'),
|
|
@@ -72,6 +88,11 @@ const commonRules = {
|
|
|
72
88
|
|
|
73
89
|
// 🔒 Security Rules (S-series) - Ready for migration
|
|
74
90
|
const securityRules = {
|
|
91
|
+
// Multi-language rules (TypeScript + Dart)
|
|
92
|
+
S003: loadRule('security', 'S003_open_redirect_protection'),
|
|
93
|
+
S004: loadRule('security', 'S004_sensitive_data_logging'),
|
|
94
|
+
|
|
95
|
+
// TypeScript-only rules (existing)
|
|
75
96
|
S006: loadRule('security', 'S006_no_plaintext_recovery_codes'),
|
|
76
97
|
S010: loadRule('security', 'S010_no_insecure_encryption'),
|
|
77
98
|
S015: loadRule('security', 'S015_insecure_tls_certificate'),
|
|
@@ -80,7 +101,6 @@ const securityRules = {
|
|
|
80
101
|
S027: loadRule('security', 'S027_no_hardcoded_secrets'),
|
|
81
102
|
S029: loadRule('security', 'S029_csrf_protection'),
|
|
82
103
|
// S001: loadRule('security', 'S001_fail_securely'),
|
|
83
|
-
// S003: loadRule('security', 'S003_no_unvalidated_redirect'),
|
|
84
104
|
// S012: loadRule('security', 'S012_hardcode_secret'),
|
|
85
105
|
// ... 46 more security rules ready for migration
|
|
86
106
|
};
|
|
@@ -1,58 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"id": "S003",
|
|
3
3
|
"name": "Open Redirect Protection",
|
|
4
|
-
"description": "URL
|
|
4
|
+
"description": "Chuyển hướng URL phải nằm trong danh sách cho phép (Allow List) - Ngăn chặn lỗ hổng Open Redirect",
|
|
5
5
|
"category": "security",
|
|
6
|
-
"severity": "
|
|
7
|
-
"languages": ["
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"injection",
|
|
12
|
-
"open-redirect",
|
|
13
|
-
"phishing",
|
|
14
|
-
"url-validation"
|
|
15
|
-
],
|
|
16
|
-
"enabled": true,
|
|
17
|
-
"fixable": false,
|
|
18
|
-
"engine": "heuristic",
|
|
19
|
-
"metadata": {
|
|
20
|
-
"owaspCategory": "A03:2021 - Injection",
|
|
21
|
-
"cweId": "CWE-601",
|
|
22
|
-
"description": "Applications that redirect users to URLs from untrusted input without validation are vulnerable to phishing attacks. Attackers can create legitimate-looking links that redirect victims to malicious sites.",
|
|
23
|
-
"impact": "Medium - Phishing attacks, credential theft, malware distribution",
|
|
24
|
-
"likelihood": "High",
|
|
25
|
-
"remediation": "Use allow list (whitelist) to validate redirect URLs, or only allow relative URLs within the same domain"
|
|
6
|
+
"severity": "error",
|
|
7
|
+
"languages": ["typescript", "javascript", "dart"],
|
|
8
|
+
"config": {
|
|
9
|
+
"redirectMethods": ["redirect", "redirectTo", "navigateTo", "location.href", "window.location"],
|
|
10
|
+
"checkUserInput": true
|
|
26
11
|
},
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"window.location = userInput without validation",
|
|
32
|
-
"response.sendRedirect(request.getParameter(*)) without validation",
|
|
33
|
-
"new RedirectView(userInput) without validation",
|
|
34
|
-
"res.setHeader('Location', req.query.*) without validation"
|
|
35
|
-
],
|
|
36
|
-
"secure": [
|
|
37
|
-
"Validate against allow list (whitelist) of trusted domains",
|
|
38
|
-
"Only allow relative URLs (startsWith('/') && !startsWith('//'))",
|
|
39
|
-
"Use indirect mapping (key -> URL mapping)",
|
|
40
|
-
"Parse and validate URL with new URL() and check hostname",
|
|
41
|
-
"Use framework validation (e.g., @IsIn(['home', 'dashboard']))"
|
|
42
|
-
]
|
|
43
|
-
},
|
|
44
|
-
"examples": {
|
|
45
|
-
"violations": [
|
|
46
|
-
"res.redirect(req.query.url);",
|
|
47
|
-
"window.location.href = params.get('redirect');",
|
|
48
|
-
"response.sendRedirect(request.getParameter('next'));",
|
|
49
|
-
"new RedirectView(request.getParameter('url'));"
|
|
50
|
-
],
|
|
51
|
-
"fixes": [
|
|
52
|
-
"const url = req.query.url; if (ALLOWED_URLS.includes(url)) res.redirect(url);",
|
|
53
|
-
"if (isAllowedDomain(url)) window.location.href = url;",
|
|
54
|
-
"const destination = REDIRECT_MAP[req.query.key]; res.redirect(destination);",
|
|
55
|
-
"if (url.startsWith('/') && !url.startsWith('//')) res.redirect(url);"
|
|
56
|
-
]
|
|
57
|
-
}
|
|
12
|
+
"references": [
|
|
13
|
+
"https://owasp.org/Top10/A01_2021-Broken_Access_Control/",
|
|
14
|
+
"https://cwe.mitre.org/data/definitions/601.html"
|
|
15
|
+
]
|
|
58
16
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S003 Dart Analyzer - Open Redirect Protection
|
|
3
|
+
*
|
|
4
|
+
* This is a JS wrapper that delegates to DartAnalyzer binary.
|
|
5
|
+
* Actual implementation: dart_analyzer/lib/rules/open_redirect_analyzer.dart
|
|
6
|
+
*
|
|
7
|
+
* Rule: Chuyển hướng URL phải nằm trong danh sách cho phép
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
class DartS003Analyzer {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.ruleId = 'S003';
|
|
13
|
+
this.language = 'dart';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getMetadata() {
|
|
17
|
+
return {
|
|
18
|
+
ruleId: 'S003',
|
|
19
|
+
name: 'Open Redirect Protection',
|
|
20
|
+
language: 'dart',
|
|
21
|
+
delegateTo: 'dart_analyzer',
|
|
22
|
+
description: 'Detect unsafe redirect patterns'
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getConfig() {
|
|
27
|
+
return {
|
|
28
|
+
redirectMethods: ['redirect', 'navigateTo', 'pushNamed', 'go'],
|
|
29
|
+
severity: 'error'
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async analyze(files, language, options) {
|
|
34
|
+
// Delegated to DartAnalyzer binary via heuristic-engine.js
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
supportsLanguage(language) {
|
|
39
|
+
return language === 'dart';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = DartS003Analyzer;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S003 Rule Router - Open Redirect Protection
|
|
3
|
+
*
|
|
4
|
+
* Routes analysis to the appropriate language-specific analyzer.
|
|
5
|
+
* Supports: TypeScript, JavaScript, Dart
|
|
6
|
+
*
|
|
7
|
+
* Rule: Chuyển hướng URL phải nằm trong danh sách cho phép (Allow List)
|
|
8
|
+
* - Không được chuyển hướng đến URL nhận từ đầu vào của người dùng mà không xác thực
|
|
9
|
+
* - Phải đối chiếu URL với danh sách cho phép trước khi thực hiện redirect
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
class S003Router {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.analyzers = new Map();
|
|
17
|
+
this.ruleId = 'S003';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getAnalyzer(language) {
|
|
21
|
+
const normalizedLang = this.normalizeLanguage(language);
|
|
22
|
+
|
|
23
|
+
if (!this.analyzers.has(normalizedLang)) {
|
|
24
|
+
try {
|
|
25
|
+
const analyzerPath = path.join(__dirname, normalizedLang, 'analyzer.js');
|
|
26
|
+
const AnalyzerClass = require(analyzerPath);
|
|
27
|
+
this.analyzers.set(normalizedLang, new AnalyzerClass());
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return this.analyzers.get(normalizedLang);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
normalizeLanguage(language) {
|
|
37
|
+
// Handle case where language might not be a string
|
|
38
|
+
if (typeof language !== 'string') {
|
|
39
|
+
return 'typescript'; // Default fallback
|
|
40
|
+
}
|
|
41
|
+
const languageMap = {
|
|
42
|
+
'typescript': 'typescript',
|
|
43
|
+
'javascript': 'typescript',
|
|
44
|
+
'ts': 'typescript',
|
|
45
|
+
'js': 'typescript',
|
|
46
|
+
'dart': 'dart'
|
|
47
|
+
};
|
|
48
|
+
return languageMap[language.toLowerCase()] || language.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
supportsLanguage(language) {
|
|
52
|
+
if (typeof language !== 'string') return false;
|
|
53
|
+
const supported = ['typescript', 'javascript', 'ts', 'js', 'dart'];
|
|
54
|
+
return supported.includes(language.toLowerCase());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getSupportedLanguages() {
|
|
58
|
+
return ['typescript', 'javascript', 'dart'];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async analyze(files, language, options = {}) {
|
|
62
|
+
const analyzer = this.getAnalyzer(language);
|
|
63
|
+
if (!analyzer) return [];
|
|
64
|
+
if (typeof analyzer.analyze === 'function') {
|
|
65
|
+
return analyzer.analyze(files, language, options);
|
|
66
|
+
}
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async initialize(semanticEngineOrLanguage = null, semanticEngine = null) {
|
|
71
|
+
// Handle both signatures:
|
|
72
|
+
// 1. initialize(semanticEngine) - called by heuristic engine
|
|
73
|
+
// 2. initialize(language, semanticEngine) - original signature
|
|
74
|
+
let engine = semanticEngine;
|
|
75
|
+
let lang = null;
|
|
76
|
+
|
|
77
|
+
if (typeof semanticEngineOrLanguage === 'string') {
|
|
78
|
+
lang = semanticEngineOrLanguage;
|
|
79
|
+
} else if (semanticEngineOrLanguage && typeof semanticEngineOrLanguage === 'object') {
|
|
80
|
+
engine = semanticEngineOrLanguage;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// If language specified, initialize only that analyzer
|
|
84
|
+
if (lang) {
|
|
85
|
+
const analyzer = this.getAnalyzer(lang);
|
|
86
|
+
if (analyzer && typeof analyzer.initialize === 'function') {
|
|
87
|
+
await analyzer.initialize(engine);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Otherwise, this is just a general initialization - do nothing for now
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = new S003Router();
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S003 TypeScript Analyzer - Open Redirect Protection
|
|
3
|
+
*
|
|
4
|
+
* Detects unsafe redirect patterns in TypeScript/JavaScript code.
|
|
5
|
+
*
|
|
6
|
+
* Rule: Chuyển hướng URL phải nằm trong danh sách cho phép
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
class TypeScriptS003Analyzer {
|
|
13
|
+
constructor(config = {}) {
|
|
14
|
+
this.ruleId = 'S003';
|
|
15
|
+
this.language = 'typescript';
|
|
16
|
+
this.config = {
|
|
17
|
+
redirectMethods: config.redirectMethods || [
|
|
18
|
+
'redirect', 'redirectTo', 'navigateTo',
|
|
19
|
+
'location.href', 'window.location', 'res.redirect'
|
|
20
|
+
],
|
|
21
|
+
checkUserInput: config.checkUserInput !== false
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getMetadata() {
|
|
26
|
+
return {
|
|
27
|
+
ruleId: 'S003',
|
|
28
|
+
name: 'Open Redirect Protection',
|
|
29
|
+
language: 'typescript',
|
|
30
|
+
description: 'Detect unsafe redirect patterns that may lead to open redirect vulnerabilities'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getConfig() {
|
|
35
|
+
return this.config;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async analyze(files, language, options = {}) {
|
|
39
|
+
const violations = [];
|
|
40
|
+
|
|
41
|
+
for (const filePath of files) {
|
|
42
|
+
if (!/\.(ts|tsx|js|jsx)$/i.test(filePath)) continue;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
46
|
+
const fileViolations = this.analyzeContent(content, filePath);
|
|
47
|
+
violations.push(...fileViolations);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
// Skip files that can't be read
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return violations;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
analyzeContent(content, filePath) {
|
|
57
|
+
const violations = [];
|
|
58
|
+
const lines = content.split('\n');
|
|
59
|
+
|
|
60
|
+
// Patterns for detecting unsafe redirects
|
|
61
|
+
const unsafePatterns = [
|
|
62
|
+
// res.redirect(req.query.url)
|
|
63
|
+
/res\.redirect\s*\(\s*(req\.(query|body|params)\.[\w]+)/g,
|
|
64
|
+
// window.location = userInput
|
|
65
|
+
/window\.location\s*=\s*([\w]+)/g,
|
|
66
|
+
// location.href = variable (not a literal)
|
|
67
|
+
/location\.href\s*=\s*([^'"]+)/g,
|
|
68
|
+
// redirect(url) where url is from params
|
|
69
|
+
/redirect\s*\(\s*(req\.(query|body|params)\.[\w]+)/g,
|
|
70
|
+
// router.push(userInput)
|
|
71
|
+
/router\.push\s*\(\s*([\w]+)\s*\)/g,
|
|
72
|
+
// navigate(url) without validation
|
|
73
|
+
/navigate\s*\(\s*(req\.(query|body|params)\.[\w]+)/g
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
lines.forEach((line, lineIndex) => {
|
|
77
|
+
for (const pattern of unsafePatterns) {
|
|
78
|
+
let match;
|
|
79
|
+
pattern.lastIndex = 0;
|
|
80
|
+
while ((match = pattern.exec(line)) !== null) {
|
|
81
|
+
// Skip if URL is a string literal (safe)
|
|
82
|
+
if (/['"`]/.test(match[1])) continue;
|
|
83
|
+
|
|
84
|
+
violations.push({
|
|
85
|
+
ruleId: 'S003',
|
|
86
|
+
file: filePath,
|
|
87
|
+
line: lineIndex + 1,
|
|
88
|
+
column: match.index + 1,
|
|
89
|
+
severity: 'error',
|
|
90
|
+
message: `Potential open redirect vulnerability: redirecting to unvalidated URL "${match[1]}"`,
|
|
91
|
+
suggestion: 'Validate the redirect URL against an allowlist before redirecting'
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return violations;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
supportsLanguage(language) {
|
|
101
|
+
return ['typescript', 'javascript', 'ts', 'js'].includes(language.toLowerCase());
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = TypeScriptS003Analyzer;
|
|
@@ -144,7 +144,7 @@ class S003SymbolBasedAnalyzer {
|
|
|
144
144
|
taintedVariables
|
|
145
145
|
);
|
|
146
146
|
} catch (error) {
|
|
147
|
-
|
|
147
|
+
// Silently ignore analysis errors - file may not be parseable TypeScript
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
return violations;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"description": "Prevent logging of sensitive information like passwords, tokens, and payment data without proper redaction",
|
|
5
5
|
"category": "security",
|
|
6
6
|
"severity": "warning",
|
|
7
|
-
"languages": ["
|
|
7
|
+
"languages": ["typescript", "javascript", "dart"],
|
|
8
8
|
"tags": [
|
|
9
9
|
"security",
|
|
10
10
|
"owasp",
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S004 Dart Analyzer - Sensitive Data Logging Protection
|
|
3
|
+
*
|
|
4
|
+
* This is a JS wrapper that delegates to DartAnalyzer binary.
|
|
5
|
+
* Actual implementation: dart_analyzer/lib/rules/sensitive_data_logging_analyzer.dart
|
|
6
|
+
*
|
|
7
|
+
* Rule: Prevent logging of sensitive information like passwords, tokens, and payment data
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
class DartS004Analyzer {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.ruleId = 'S004';
|
|
13
|
+
this.language = 'dart';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get rule metadata
|
|
18
|
+
*/
|
|
19
|
+
getMetadata() {
|
|
20
|
+
return {
|
|
21
|
+
ruleId: 'S004',
|
|
22
|
+
name: 'Sensitive Data Logging Protection',
|
|
23
|
+
language: 'dart',
|
|
24
|
+
delegateTo: 'dart_analyzer',
|
|
25
|
+
description: 'Prevent logging of sensitive information without proper redaction'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get default configuration
|
|
31
|
+
*/
|
|
32
|
+
getConfig() {
|
|
33
|
+
return {
|
|
34
|
+
sensitivePatterns: [
|
|
35
|
+
'password', 'secret', 'token', 'apikey', 'api_key',
|
|
36
|
+
'accessToken', 'access_token', 'refreshToken', 'refresh_token',
|
|
37
|
+
'credential', 'auth', 'private', 'creditCard', 'credit_card',
|
|
38
|
+
'ssn', 'socialSecurity'
|
|
39
|
+
],
|
|
40
|
+
logMethods: ['print', 'debugPrint', 'log', 'logger'],
|
|
41
|
+
severity: 'warning'
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Analysis is delegated to DartAnalyzer via heuristic-engine.js
|
|
47
|
+
*/
|
|
48
|
+
async analyze(files, language, options) {
|
|
49
|
+
// Delegated to DartAnalyzer binary via heuristic-engine.js
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
supportsLanguage(language) {
|
|
54
|
+
return language === 'dart';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = DartS004Analyzer;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S004 Rule Router - Sensitive Data Logging Protection
|
|
3
|
+
*
|
|
4
|
+
* Routes analysis to the appropriate language-specific analyzer.
|
|
5
|
+
* Supports: TypeScript, JavaScript, Dart
|
|
6
|
+
*
|
|
7
|
+
* Rule: Prevent logging of sensitive information like passwords, tokens, and payment data
|
|
8
|
+
* - Detect logging of sensitive data without proper redaction
|
|
9
|
+
* - Mask or redact sensitive fields before logging
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
class S004Router {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.analyzers = new Map();
|
|
17
|
+
this.ruleId = 'S004';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getAnalyzer(language) {
|
|
21
|
+
const normalizedLang = this.normalizeLanguage(language);
|
|
22
|
+
|
|
23
|
+
if (!this.analyzers.has(normalizedLang)) {
|
|
24
|
+
try {
|
|
25
|
+
const analyzerPath = path.join(__dirname, normalizedLang, 'analyzer.js');
|
|
26
|
+
const AnalyzerClass = require(analyzerPath);
|
|
27
|
+
this.analyzers.set(normalizedLang, new AnalyzerClass());
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return this.analyzers.get(normalizedLang);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
normalizeLanguage(language) {
|
|
37
|
+
// Handle case where language might not be a string
|
|
38
|
+
if (typeof language !== 'string') {
|
|
39
|
+
return 'typescript'; // Default fallback
|
|
40
|
+
}
|
|
41
|
+
const languageMap = {
|
|
42
|
+
'typescript': 'typescript',
|
|
43
|
+
'javascript': 'typescript',
|
|
44
|
+
'ts': 'typescript',
|
|
45
|
+
'js': 'typescript',
|
|
46
|
+
'dart': 'dart'
|
|
47
|
+
};
|
|
48
|
+
return languageMap[language.toLowerCase()] || language.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
supportsLanguage(language) {
|
|
52
|
+
if (typeof language !== 'string') return false;
|
|
53
|
+
const supported = ['typescript', 'javascript', 'ts', 'js', 'dart'];
|
|
54
|
+
return supported.includes(language.toLowerCase());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getSupportedLanguages() {
|
|
58
|
+
return ['typescript', 'javascript', 'dart'];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async analyze(files, language, options = {}) {
|
|
62
|
+
const analyzer = this.getAnalyzer(language);
|
|
63
|
+
if (!analyzer) return [];
|
|
64
|
+
if (typeof analyzer.analyze === 'function') {
|
|
65
|
+
return analyzer.analyze(files, language, options);
|
|
66
|
+
}
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async initialize(semanticEngineOrLanguage = null, semanticEngine = null) {
|
|
71
|
+
// Handle both signatures:
|
|
72
|
+
// 1. initialize(semanticEngine) - called by heuristic engine
|
|
73
|
+
// 2. initialize(language, semanticEngine) - original signature
|
|
74
|
+
let engine = semanticEngine;
|
|
75
|
+
let lang = null;
|
|
76
|
+
|
|
77
|
+
if (typeof semanticEngineOrLanguage === 'string') {
|
|
78
|
+
lang = semanticEngineOrLanguage;
|
|
79
|
+
} else if (semanticEngineOrLanguage && typeof semanticEngineOrLanguage === 'object') {
|
|
80
|
+
engine = semanticEngineOrLanguage;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// If language specified, initialize only that analyzer
|
|
84
|
+
if (lang) {
|
|
85
|
+
const analyzer = this.getAnalyzer(lang);
|
|
86
|
+
if (analyzer && typeof analyzer.initialize === 'function') {
|
|
87
|
+
await analyzer.initialize(engine);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = new S004Router();
|