@sun-asterisk/sunlint 1.3.39 → 1.3.41
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/rules/rules-registry-generated.json +134 -108
- package/core/rule-selection-service.js +11 -0
- package/docs/GENERATED_FILES_QUICK_REFERENCE.md +96 -0
- package/docs/GENERATED_FILE_HANDLING_SUMMARY.md +152 -0
- package/docs/skills/CREATE_NEW_DART_RULE.md +161 -14
- package/origin-rules/dart-en.md +151 -163
- package/package.json +2 -1
- package/rules/dart/D002_dispose_resources/config.json +25 -0
- package/rules/dart/D003_prefer_widgets_over_methods/config.json +14 -0
- package/rules/dart/D004_avoid_shrinkwrap_listview/config.json +13 -0
- package/rules/dart/D005_limit_widget_nesting/config.json +13 -0
- package/rules/dart/D006_prefer_extracting_large_callbacks/config.json +25 -0
- package/rules/dart/D007_prefer_init_first_dispose_last/config.json +10 -0
- package/rules/dart/D008_avoid_long_functions/config.json +12 -0
- package/rules/dart/D009_limit_function_parameters/config.json +13 -0
- package/rules/dart/D010_limit_cyclomatic_complexity/config.json +12 -0
- package/rules/dart/D011_prefer_named_parameters/config.json +12 -0
- package/rules/dart/D012_prefer_named_boolean_parameters/config.json +9 -0
- package/rules/dart/D013_single_public_class/config.json +10 -0
- package/rules/dart/D014_unsafe_collection_access/config.json +10 -0
- package/rules/dart/D015_copywith_all_parameters/config.json +9 -0
- package/rules/dart/D016_project_should_have_tests/config.json +24 -0
- package/rules/dart/D017_pubspec_dependencies_review/config.json +23 -0
- package/rules/dart/D018_remove_commented_code/config.json +13 -0
- package/rules/dart/D019_avoid_single_child_multi_child_widget/config.json +21 -0
- package/rules/dart/D020_limit_if_else_branches/config.json +12 -0
- package/rules/dart/D021_avoid_negated_boolean_checks/config.json +14 -0
- package/rules/dart/D022_use_setstate_correctly/config.json +14 -0
- package/rules/dart/D023_avoid_unnecessary_method_overrides/config.json +13 -0
- package/rules/dart/D024_avoid_unnecessary_stateful_widget/config.json +9 -0
- package/rules/dart/D025_avoid_nested_conditional_expressions/config.json +9 -0
- package/skill-assets/sunlint-code-quality/AGENTS.md +80 -0
- package/skill-assets/sunlint-code-quality/SKILL.md +176 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C006-verb-noun-functions.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C013-no-dead-code.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C014-dependency-injection.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C017-no-constructor-logic.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C018-generic-errors.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C019-error-log-level.md +29 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C020-no-unused-imports.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C022-no-unused-variables.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C023-no-duplicate-names.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C024-centralize-constants.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C029-catch-log-root-cause.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C030-custom-error-classes.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C033-separate-data-access.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C035-error-context-logging.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C041-no-hardcoded-secrets.md +25 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C042-boolean-naming.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C052-controller-parsing.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C060-superclass-logic.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/C067-no-hardcoded-config.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S003-open-redirect.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S004-no-log-credentials.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S005-server-authorization.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S006-default-credentials.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S007-output-encoding.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S009-approved-crypto.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S010-csprng.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S011-encrypted-client-hello.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S012-secrets-management.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S013-tls-connections.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S016-no-sensitive-query-string.md +39 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S017-parameterized-queries.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S019-email-input-sanitization.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S020-eval-code-execution.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S022-context-escaping.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S023-dynamic-js-encoding.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S025-server-validation.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S026-tls-encryption.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S027-mtls-validation.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S028-upload-limits.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S029-csrf-protection.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S030-directory-browsing.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S031-secure-cookie-flag.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S032-httponly-cookie.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S033-samesite-cookie.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S034-host-prefix-cookie.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S035-app-hostnames.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S036-internal-file-paths.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S037-anti-cache-headers.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S039-tls-certificate-validation.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S041-logout-invalidation.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S042-long-lived-sessions.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S044-critical-changes-reauth.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S045-brute-force-protection.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S047-oauth-csrf-protection.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S048-oauth-redirect-validation.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S049-auth-code-expiry.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S050-token-entropy.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S051-password-length.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S052-otp-entropy.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S053-generic-error-messages.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S054-no-default-admin.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S055-content-type-validation.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S056-log-injection.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S057-synchronized-time.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/csharp/S058-ssrf-protection.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/go/C006-verb-noun-functions.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/go/C013-no-dead-code.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/go/C014-dependency-injection.md +85 -0
- package/skill-assets/sunlint-code-quality/rules/go/C017-no-constructor-logic.md +67 -0
- package/skill-assets/sunlint-code-quality/rules/go/C018-generic-errors.md +63 -0
- package/skill-assets/sunlint-code-quality/rules/go/C019-error-log-level.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/go/C020-no-unused-imports.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/go/C022-no-unused-variables.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/go/C023-no-duplicate-names.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/go/C024-centralize-constants.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/go/C029-catch-log-root-cause.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/go/C030-custom-error-classes.md +69 -0
- package/skill-assets/sunlint-code-quality/rules/go/C033-separate-data-access.md +68 -0
- package/skill-assets/sunlint-code-quality/rules/go/C035-error-context-logging.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/go/C041-no-hardcoded-secrets.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/go/C042-boolean-naming.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/go/C052-controller-parsing.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/go/C060-superclass-logic.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/go/C067-no-hardcoded-config.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/go/S003-open-redirect.md +80 -0
- package/skill-assets/sunlint-code-quality/rules/go/S004-no-log-credentials.md +66 -0
- package/skill-assets/sunlint-code-quality/rules/go/S005-server-authorization.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/go/S006-default-credentials.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/go/S007-output-encoding.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/go/S009-approved-crypto.md +63 -0
- package/skill-assets/sunlint-code-quality/rules/go/S010-csprng.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/go/S011-encrypted-client-hello.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/go/S012-secrets-management.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/go/S013-tls-connections.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/go/S016-no-sensitive-query-string.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/go/S017-parameterized-queries.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/go/S019-email-input-sanitization.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/go/S020-eval-code-execution.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/go/S022-context-escaping.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/go/S023-dynamic-js-encoding.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/go/S025-server-validation.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/go/S026-tls-encryption.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/go/S027-mtls-validation.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/go/S028-upload-limits.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/go/S029-csrf-protection.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/go/S030-directory-browsing.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/go/S031-secure-cookie-flag.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/go/S032-httponly-cookie.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/go/S033-samesite-cookie.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/go/S034-host-prefix-cookie.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/go/S035-app-hostnames.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/go/S036-internal-file-paths.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/go/S037-anti-cache-headers.md +43 -0
- package/skill-assets/sunlint-code-quality/rules/go/S039-tls-certificate-validation.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/go/S041-logout-invalidation.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/go/S042-long-lived-sessions.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/go/S044-critical-changes-reauth.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/go/S045-brute-force-protection.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/go/S047-oauth-csrf-protection.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/go/S048-oauth-redirect-validation.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/go/S049-auth-code-expiry.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/go/S050-token-entropy.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/go/S051-password-length.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/go/S052-otp-entropy.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/go/S053-generic-error-messages.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/go/S054-no-default-admin.md +43 -0
- package/skill-assets/sunlint-code-quality/rules/go/S055-content-type-validation.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/go/S056-log-injection.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/go/S057-synchronized-time.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/go/S058-ssrf-protection.md +70 -0
- package/skill-assets/sunlint-code-quality/rules/java/C006-verb-noun-functions.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/java/C013-no-dead-code.md +175 -0
- package/skill-assets/sunlint-code-quality/rules/java/C014-dependency-injection.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/java/C017-no-constructor-logic.md +39 -0
- package/skill-assets/sunlint-code-quality/rules/java/C018-generic-errors.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/java/C019-error-log-level.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/java/C020-no-unused-imports.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/java/C022-no-unused-variables.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/java/C023-no-duplicate-names.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/java/C024-centralize-constants.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/java/C029-catch-log-root-cause.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/java/C030-custom-error-classes.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/java/C033-separate-data-access.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/java/C035-error-context-logging.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/java/C041-no-hardcoded-secrets.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/java/C042-boolean-naming.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/java/C052-controller-parsing.md +39 -0
- package/skill-assets/sunlint-code-quality/rules/java/C060-superclass-logic.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/java/C067-no-hardcoded-config.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/java/S003-open-redirect.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/java/S004-no-log-credentials.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/java/S005-server-authorization.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/java/S006-default-credentials.md +39 -0
- package/skill-assets/sunlint-code-quality/rules/java/S007-output-encoding.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/java/S009-approved-crypto.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/java/S010-csprng.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/java/S011-encrypted-client-hello.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/java/S012-secrets-management.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/java/S013-tls-connections.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/java/S016-no-sensitive-query-string.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/java/S017-parameterized-queries.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/java/S019-email-input-sanitization.md +32 -0
- package/skill-assets/sunlint-code-quality/rules/java/S020-eval-code-execution.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/java/S022-context-escaping.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/java/S023-dynamic-js-encoding.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/java/S025-server-validation.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/java/S026-tls-encryption.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/java/S027-mtls-validation.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/java/S028-upload-limits.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/java/S029-csrf-protection.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/java/S030-directory-browsing.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/java/S031-secure-cookie-flag.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/java/S032-httponly-cookie.md +31 -0
- package/skill-assets/sunlint-code-quality/rules/java/S033-samesite-cookie.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/java/S034-host-prefix-cookie.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/java/S035-app-hostnames.md +23 -0
- package/skill-assets/sunlint-code-quality/rules/java/S036-internal-file-paths.md +39 -0
- package/skill-assets/sunlint-code-quality/rules/java/S037-anti-cache-headers.md +37 -0
- package/skill-assets/sunlint-code-quality/rules/java/S039-tls-certificate-validation.md +43 -0
- package/skill-assets/sunlint-code-quality/rules/java/S041-logout-invalidation.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/java/S042-long-lived-sessions.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/java/S044-critical-changes-reauth.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/java/S045-brute-force-protection.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/java/S047-oauth-csrf-protection.md +33 -0
- package/skill-assets/sunlint-code-quality/rules/java/S048-oauth-redirect-validation.md +25 -0
- package/skill-assets/sunlint-code-quality/rules/java/S049-auth-code-expiry.md +23 -0
- package/skill-assets/sunlint-code-quality/rules/java/S050-token-entropy.md +20 -0
- package/skill-assets/sunlint-code-quality/rules/java/S051-password-length.md +20 -0
- package/skill-assets/sunlint-code-quality/rules/java/S052-otp-entropy.md +23 -0
- package/skill-assets/sunlint-code-quality/rules/java/S053-generic-error-messages.md +21 -0
- package/skill-assets/sunlint-code-quality/rules/java/S054-no-default-admin.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/java/S055-content-type-validation.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/java/S056-log-injection.md +38 -0
- package/skill-assets/sunlint-code-quality/rules/java/S057-synchronized-time.md +35 -0
- package/skill-assets/sunlint-code-quality/rules/java/S058-ssrf-protection.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C006-verb-noun-functions.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C013-no-dead-code.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C014-dependency-injection.md +64 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C017-no-constructor-logic.md +68 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C018-generic-errors.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C019-error-log-level.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C020-no-unused-imports.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C022-no-unused-variables.md +39 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C023-no-duplicate-names.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C024-centralize-constants.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C029-catch-log-root-cause.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C030-custom-error-classes.md +72 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C033-separate-data-access.md +69 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C035-error-context-logging.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C041-no-hardcoded-secrets.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C042-boolean-naming.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C052-controller-parsing.md +71 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C060-superclass-logic.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/C067-no-hardcoded-config.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S003-open-redirect.md +66 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S004-no-log-credentials.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S005-server-authorization.md +75 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S006-default-credentials.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S007-output-encoding.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S009-approved-crypto.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S010-csprng.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S011-encrypted-client-hello.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S012-secrets-management.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S013-tls-connections.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S016-no-sensitive-query-string.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S017-parameterized-queries.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S019-email-input-sanitization.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S020-eval-code-execution.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S022-context-escaping.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S023-dynamic-js-encoding.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S025-server-validation.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S026-tls-encryption.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S027-mtls-validation.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S028-upload-limits.md +67 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S029-csrf-protection.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S030-directory-browsing.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S031-secure-cookie-flag.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S032-httponly-cookie.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S033-samesite-cookie.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S034-host-prefix-cookie.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S035-app-hostnames.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S036-internal-file-paths.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S037-anti-cache-headers.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S039-tls-certificate-validation.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S041-logout-invalidation.md +71 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S042-long-lived-sessions.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S044-critical-changes-reauth.md +64 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S045-brute-force-protection.md +64 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S047-oauth-csrf-protection.md +74 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S048-oauth-redirect-validation.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S049-auth-code-expiry.md +70 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S050-token-entropy.md +65 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S051-password-length.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S052-otp-entropy.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S053-generic-error-messages.md +66 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S054-no-default-admin.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S055-content-type-validation.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S056-log-injection.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S057-synchronized-time.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/kotlin/S058-ssrf-protection.md +69 -0
- package/skill-assets/sunlint-code-quality/rules/php/C006-verb-noun-functions.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/php/C013-no-dead-code.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/php/C014-dependency-injection.md +71 -0
- package/skill-assets/sunlint-code-quality/rules/php/C017-no-constructor-logic.md +68 -0
- package/skill-assets/sunlint-code-quality/rules/php/C018-generic-errors.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/php/C019-error-log-level.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/php/C020-no-unused-imports.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/php/C022-no-unused-variables.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/php/C023-no-duplicate-names.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/php/C024-centralize-constants.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/php/C029-catch-log-root-cause.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/php/C030-custom-error-classes.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/php/C033-separate-data-access.md +79 -0
- package/skill-assets/sunlint-code-quality/rules/php/C035-error-context-logging.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/php/C041-no-hardcoded-secrets.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/php/C042-boolean-naming.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/php/C052-controller-parsing.md +66 -0
- package/skill-assets/sunlint-code-quality/rules/php/C060-superclass-logic.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/php/C067-no-hardcoded-config.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/php/S003-open-redirect.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/php/S004-no-log-credentials.md +67 -0
- package/skill-assets/sunlint-code-quality/rules/php/S005-server-authorization.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/php/S006-default-credentials.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/php/S007-output-encoding.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/php/S009-approved-crypto.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/php/S010-csprng.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/php/S011-encrypted-client-hello.md +41 -0
- package/skill-assets/sunlint-code-quality/rules/php/S012-secrets-management.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/php/S013-tls-connections.md +67 -0
- package/skill-assets/sunlint-code-quality/rules/php/S016-no-sensitive-query-string.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/php/S017-parameterized-queries.md +44 -0
- package/skill-assets/sunlint-code-quality/rules/php/S019-email-input-sanitization.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/php/S020-eval-code-execution.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/php/S022-context-escaping.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/php/S023-dynamic-js-encoding.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/php/S025-server-validation.md +63 -0
- package/skill-assets/sunlint-code-quality/rules/php/S026-tls-encryption.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/php/S027-mtls-validation.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/php/S028-upload-limits.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/php/S029-csrf-protection.md +65 -0
- package/skill-assets/sunlint-code-quality/rules/php/S030-directory-browsing.md +40 -0
- package/skill-assets/sunlint-code-quality/rules/php/S031-secure-cookie-flag.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/php/S032-httponly-cookie.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/php/S033-samesite-cookie.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/php/S034-host-prefix-cookie.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/php/S035-app-hostnames.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/php/S036-internal-file-paths.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/php/S037-anti-cache-headers.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/php/S039-tls-certificate-validation.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/php/S041-logout-invalidation.md +63 -0
- package/skill-assets/sunlint-code-quality/rules/php/S042-long-lived-sessions.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/php/S044-critical-changes-reauth.md +71 -0
- package/skill-assets/sunlint-code-quality/rules/php/S045-brute-force-protection.md +67 -0
- package/skill-assets/sunlint-code-quality/rules/php/S047-oauth-csrf-protection.md +72 -0
- package/skill-assets/sunlint-code-quality/rules/php/S048-oauth-redirect-validation.md +54 -0
- package/skill-assets/sunlint-code-quality/rules/php/S049-auth-code-expiry.md +71 -0
- package/skill-assets/sunlint-code-quality/rules/php/S050-token-entropy.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/php/S051-password-length.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/php/S052-otp-entropy.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/php/S053-generic-error-messages.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/php/S054-no-default-admin.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/php/S055-content-type-validation.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/php/S056-log-injection.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/php/S057-synchronized-time.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/php/S058-ssrf-protection.md +65 -0
- package/skill-assets/sunlint-code-quality/rules/python/C006-verb-noun-functions.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/python/C013-no-dead-code.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/python/C014-dependency-injection.md +68 -0
- package/skill-assets/sunlint-code-quality/rules/python/C017-no-constructor-logic.md +30 -0
- package/skill-assets/sunlint-code-quality/rules/python/C018-generic-errors.md +25 -0
- package/skill-assets/sunlint-code-quality/rules/python/C019-error-log-level.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/python/C020-no-unused-imports.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/python/C022-no-unused-variables.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/python/C023-no-duplicate-names.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/python/C024-centralize-constants.md +27 -0
- package/skill-assets/sunlint-code-quality/rules/python/C029-catch-log-root-cause.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/python/C030-custom-error-classes.md +28 -0
- package/skill-assets/sunlint-code-quality/rules/python/C033-separate-data-access.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/python/C035-error-context-logging.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/python/C041-no-hardcoded-secrets.md +23 -0
- package/skill-assets/sunlint-code-quality/rules/python/C042-boolean-naming.md +24 -0
- package/skill-assets/sunlint-code-quality/rules/python/C052-controller-parsing.md +34 -0
- package/skill-assets/sunlint-code-quality/rules/python/C060-superclass-logic.md +26 -0
- package/skill-assets/sunlint-code-quality/rules/python/C067-no-hardcoded-config.md +22 -0
- package/skill-assets/sunlint-code-quality/rules/python/S003-open-redirect.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S004-no-log-credentials.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S005-server-authorization.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S006-default-credentials.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S007-output-encoding.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S009-approved-crypto.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S010-csprng.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S011-encrypted-client-hello.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S012-secrets-management.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S013-tls-connections.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S016-no-sensitive-query-string.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S017-parameterized-queries.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/python/S019-email-input-sanitization.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S020-eval-code-execution.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/python/S022-context-escaping.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S023-dynamic-js-encoding.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S025-server-validation.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S026-tls-encryption.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S027-mtls-validation.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S028-upload-limits.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S029-csrf-protection.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S030-directory-browsing.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S031-secure-cookie-flag.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S032-httponly-cookie.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S033-samesite-cookie.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S034-host-prefix-cookie.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S035-app-hostnames.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S036-internal-file-paths.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/python/S037-anti-cache-headers.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S039-tls-certificate-validation.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S041-logout-invalidation.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S042-long-lived-sessions.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S044-critical-changes-reauth.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S045-brute-force-protection.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S047-oauth-csrf-protection.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S048-oauth-redirect-validation.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S049-auth-code-expiry.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S050-token-entropy.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S051-password-length.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S052-otp-entropy.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S053-generic-error-messages.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S054-no-default-admin.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S055-content-type-validation.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S056-log-injection.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S057-synchronized-time.md +16 -0
- package/skill-assets/sunlint-code-quality/rules/python/S058-ssrf-protection.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C006-verb-noun-functions.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C013-no-dead-code.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C014-dependency-injection.md +69 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C017-no-constructor-logic.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C018-generic-errors.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C019-error-log-level.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C020-no-unused-imports.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C022-no-unused-variables.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C023-no-duplicate-names.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C024-centralize-constants.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C029-catch-log-root-cause.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C030-custom-error-classes.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C033-separate-data-access.md +69 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C035-error-context-logging.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C041-no-hardcoded-secrets.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C042-boolean-naming.md +42 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C052-controller-parsing.md +64 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C060-superclass-logic.md +67 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/C067-no-hardcoded-config.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S003-open-redirect.md +76 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S004-no-log-credentials.md +71 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S005-server-authorization.md +68 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S006-default-credentials.md +69 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S007-output-encoding.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S009-approved-crypto.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S010-csprng.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S011-encrypted-client-hello.md +45 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S012-secrets-management.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S013-tls-connections.md +70 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S016-no-sensitive-query-string.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S017-parameterized-queries.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S019-email-input-sanitization.md +56 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S020-eval-code-execution.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S022-context-escaping.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S023-dynamic-js-encoding.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S025-server-validation.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S026-tls-encryption.md +47 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S027-mtls-validation.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S028-upload-limits.md +65 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S029-csrf-protection.md +62 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S030-directory-browsing.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S031-secure-cookie-flag.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S032-httponly-cookie.md +36 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S033-samesite-cookie.md +46 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S034-host-prefix-cookie.md +50 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S035-app-hostnames.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S036-internal-file-paths.md +53 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S037-anti-cache-headers.md +52 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S039-tls-certificate-validation.md +51 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S041-logout-invalidation.md +58 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S042-long-lived-sessions.md +55 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S044-critical-changes-reauth.md +69 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S045-brute-force-protection.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S047-oauth-csrf-protection.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S048-oauth-redirect-validation.md +59 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S049-auth-code-expiry.md +73 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S050-token-entropy.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S051-password-length.md +60 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S052-otp-entropy.md +49 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S053-generic-error-messages.md +61 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S054-no-default-admin.md +64 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S055-content-type-validation.md +64 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S056-log-injection.md +48 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S057-synchronized-time.md +57 -0
- package/skill-assets/sunlint-code-quality/rules/typescript/S058-ssrf-protection.md +63 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: No Duplicate Variable Names In Scope
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents shadowing bugs and improves code clarity
|
|
5
|
+
tags: variables, shadowing, scope, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## No Duplicate Variable Names In Scope
|
|
9
|
+
|
|
10
|
+
Variable shadowing occurs when a variable declared within a certain scope has the same name as a variable declared in an outer scope. This leads to subtle bugs and confusion about which variable is being accessed.
|
|
11
|
+
|
|
12
|
+
**Incorrect (shadowed variables):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
val user = getCurrentUser()
|
|
16
|
+
|
|
17
|
+
fun processOrder(order: Order) {
|
|
18
|
+
val user = order.user // Shadows outer 'user'!
|
|
19
|
+
|
|
20
|
+
// Which user is this?
|
|
21
|
+
println(user.name)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Shadowing in lambdas
|
|
25
|
+
items.forEach { item ->
|
|
26
|
+
val item = transform(item) // Shadows lambda parameter!
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (unique names):**
|
|
31
|
+
|
|
32
|
+
```kotlin
|
|
33
|
+
val currentUser = getCurrentUser()
|
|
34
|
+
|
|
35
|
+
fun processOrder(order: Order) {
|
|
36
|
+
val orderUser = order.user // Distinct name
|
|
37
|
+
|
|
38
|
+
println(orderUser.name)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Different names in nested scope
|
|
42
|
+
items.forEach { item ->
|
|
43
|
+
val transformedItem = transform(item)
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Tools:** detekt (VariableShadowing), Android Studio Linter, Manual Review
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Centralize Constants
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: makes values easy to find, update, and understand
|
|
5
|
+
tags: constants, magic-numbers, configuration, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Centralize Constants
|
|
9
|
+
|
|
10
|
+
Magic numbers or strings scattered throughout the code are difficult to manage and prone to errors. Centralizing constants makes the codebase more maintainable and self-documenting.
|
|
11
|
+
|
|
12
|
+
**Incorrect (magic numbers and strings):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
if (password.length < 8) { }
|
|
16
|
+
if (retryCount > 3) { }
|
|
17
|
+
if (status == 1) { }
|
|
18
|
+
Handler().postDelayed(callback, 300000)
|
|
19
|
+
if (user.role == "admin") { }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Correct (centralized constants):**
|
|
23
|
+
|
|
24
|
+
```kotlin
|
|
25
|
+
// Constants.kt or within an object
|
|
26
|
+
object Config {
|
|
27
|
+
const val PASSWORD_MIN_LENGTH = 8
|
|
28
|
+
const val MAX_RETRY_ATTEMPTS = 3
|
|
29
|
+
const val SESSION_TIMEOUT_MS = 5 * 60 * 1000L // 5 minutes
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
enum class OrderStatus(val value: Int) {
|
|
33
|
+
PENDING(1),
|
|
34
|
+
APPROVED(2),
|
|
35
|
+
SHIPPED(3)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
object UserRoles {
|
|
39
|
+
const val ADMIN = "admin"
|
|
40
|
+
const val USER = "user"
|
|
41
|
+
const val GUEST = "guest"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Usage
|
|
45
|
+
if (password.length < Config.PASSWORD_MIN_LENGTH) { }
|
|
46
|
+
if (retryCount > Config.MAX_RETRY_ATTEMPTS) { }
|
|
47
|
+
if (status == OrderStatus.PENDING.value) { }
|
|
48
|
+
Handler().postDelayed(callback, Config.SESSION_TIMEOUT_MS)
|
|
49
|
+
if (user.role == UserRoles.ADMIN) { }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Benefits:**
|
|
53
|
+
- Single source of truth.
|
|
54
|
+
- Improved readability and domain expression.
|
|
55
|
+
- Avoids duplication and "search-and-replace" errors.
|
|
56
|
+
- Type safety (especially when using Enums or Sealed Classes).
|
|
57
|
+
|
|
58
|
+
**Tools:** detekt (MagicNumber), Android Studio Linter, Manual Review
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: All Catch Blocks Must Log Root Cause
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables debugging and incident response
|
|
5
|
+
tags: error-handling, logging, debugging, observability, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## All Catch Blocks Must Log Root Cause
|
|
9
|
+
|
|
10
|
+
Silent failures make debugging impossible. Without proper logging, you cannot trace issues in production.
|
|
11
|
+
|
|
12
|
+
**Incorrect (silent or minimal logging):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
try {
|
|
16
|
+
processPayment(order)
|
|
17
|
+
} catch (e: Exception) {
|
|
18
|
+
// Empty catch - silent failure!
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
saveUser(user)
|
|
23
|
+
} catch (e: Exception) {
|
|
24
|
+
return null // No logging, no context
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Correct (comprehensive error logging):**
|
|
29
|
+
|
|
30
|
+
```kotlin
|
|
31
|
+
try {
|
|
32
|
+
processPayment(order)
|
|
33
|
+
} catch (error: Exception) {
|
|
34
|
+
logger.error("Payment processing failed", error) {
|
|
35
|
+
payload("orderId" to order.id)
|
|
36
|
+
payload("userId" to order.userId)
|
|
37
|
+
payload("amount" to order.amount)
|
|
38
|
+
}
|
|
39
|
+
throw PaymentFailedException("Payment could not be processed", error)
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Log context should include:**
|
|
44
|
+
- Error message and stack trace
|
|
45
|
+
- Relevant entity IDs (order, user, etc.)
|
|
46
|
+
- Request/correlation ID
|
|
47
|
+
- Input that caused the error
|
|
48
|
+
- Timing information
|
|
49
|
+
|
|
50
|
+
**Tools:** Static analyzer, detekt, PR review
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Custom Error Classes
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables proper error categorization, structured logging, and precise handling
|
|
5
|
+
tags: error-handling, custom-errors, exceptions, patterns, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Custom Error Classes
|
|
9
|
+
|
|
10
|
+
Custom exception classes enable structured error handling, meaningful categorization, and better observability. They allow the application to provide clear diagnostic information and programmatic error codes.
|
|
11
|
+
|
|
12
|
+
**Incorrect (generic exceptions):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
throw Exception("User not found")
|
|
16
|
+
throw RuntimeException("Invalid input")
|
|
17
|
+
throw IllegalStateException("Database connection failed")
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (custom exception hierarchy):**
|
|
21
|
+
|
|
22
|
+
```kotlin
|
|
23
|
+
// Base application exception
|
|
24
|
+
open class AppException(
|
|
25
|
+
val code: String,
|
|
26
|
+
override val message: String,
|
|
27
|
+
val statusCode: Int = 500,
|
|
28
|
+
val context: Map<String, Any?>? = null,
|
|
29
|
+
cause: Throwable? = null
|
|
30
|
+
) : RuntimeException(message, cause)
|
|
31
|
+
|
|
32
|
+
// Specific domain exceptions
|
|
33
|
+
class UserNotFoundException(userId: String) : AppException(
|
|
34
|
+
code = "USER_NOT_FOUND",
|
|
35
|
+
message = "User $userId not found",
|
|
36
|
+
statusCode = 404,
|
|
37
|
+
context = mapOf("userId" to userId)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
class ValidationException(field: String, message: String) : AppException(
|
|
41
|
+
code = "VALIDATION_ERROR",
|
|
42
|
+
message = message,
|
|
43
|
+
statusCode = 400,
|
|
44
|
+
context = mapOf("field" to field)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
// Usage
|
|
48
|
+
throw UserNotFoundException(userId)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Using Sealed Classes for Error Handling (Functional Style):**
|
|
52
|
+
|
|
53
|
+
```kotlin
|
|
54
|
+
sealed class Result<out T> {
|
|
55
|
+
data class Success<out T>(val data: T) : Result<T>()
|
|
56
|
+
data class Failure(val error: AppException) : Result<Nothing>()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Logic returning a result instead of throwing
|
|
60
|
+
fun findUser(id: String): Result<User> {
|
|
61
|
+
val user = db.find(id)
|
|
62
|
+
return user?.let { Result.Success(it) } ?: Result.Failure(UserNotFoundException(id))
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Benefits:**
|
|
67
|
+
- Type-safe error handling logic.
|
|
68
|
+
- Structured context for logging systems (ELK, Sentry).
|
|
69
|
+
- Automatic mapping to API response formats.
|
|
70
|
+
- Clearer domain modeling.
|
|
71
|
+
|
|
72
|
+
**Tools:** detekt (TooGenericExceptionThrown), Manual Review, PR rules
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Separate Processing And Data Access
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables testable business logic and better maintenance
|
|
5
|
+
tags: separation, repository, service, architecture, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Separate Processing And Data Access
|
|
9
|
+
|
|
10
|
+
Mixing business logic with raw database queries or data access logic creates tight coupling. This makes testing difficult (requiring a database) and makes the code harder to maintain and refactor.
|
|
11
|
+
|
|
12
|
+
**Incorrect (mixed concerns):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
class OrderService {
|
|
16
|
+
fun calculateDiscount(userId: String): Double {
|
|
17
|
+
// Business logic mixed with raw SQL or data access
|
|
18
|
+
val user = db.query("SELECT * FROM users WHERE id = ?", userId)
|
|
19
|
+
val orders = db.query("SELECT * FROM orders WHERE user_id = ?", userId)
|
|
20
|
+
|
|
21
|
+
var discount = 0.0
|
|
22
|
+
if (orders.size > 10) discount += 0.05
|
|
23
|
+
if (user.getBoolean("isPremium")) discount += 0.10
|
|
24
|
+
|
|
25
|
+
return discount
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (separated layers using Repository Pattern):**
|
|
31
|
+
|
|
32
|
+
```kotlin
|
|
33
|
+
// Repository - focus on data mapping and retrieval
|
|
34
|
+
interface UserRepository {
|
|
35
|
+
fun findById(userId: String): User?
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface OrderRepository {
|
|
39
|
+
fun findByUserId(userId: String): List<Order>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Service - focus on business rules and orchestration
|
|
43
|
+
class DiscountService(
|
|
44
|
+
private val userRepository: UserRepository,
|
|
45
|
+
private val orderRepository: OrderRepository
|
|
46
|
+
) {
|
|
47
|
+
fun calculateDiscount(userId: String): Double {
|
|
48
|
+
val user = userRepository.findById(userId)
|
|
49
|
+
val orders = orderRepository.findByUserId(userId)
|
|
50
|
+
|
|
51
|
+
return computeDiscount(user, orders)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Business logic is pure and easily testable
|
|
55
|
+
private fun computeDiscount(user: User?, orders: List<Order>): Double {
|
|
56
|
+
var discount = 0.0
|
|
57
|
+
if (orders.size > 10) discount += 0.05
|
|
58
|
+
if (user?.isPremium == true) discount += 0.10
|
|
59
|
+
return discount
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Benefits:**
|
|
65
|
+
- Business logic can be unit-tested without a database.
|
|
66
|
+
- Data sources can be swapped (e.g., migrating from SQL to NoSQL) without changing business rules.
|
|
67
|
+
- Improved readability and clear separation of concerns.
|
|
68
|
+
|
|
69
|
+
**Tools:** Architectural Review, Code Review, Manual Audit
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Log All Relevant Context On Errors
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables quick debugging and accurate incident response
|
|
5
|
+
tags: error-handling, logging, context, debugging, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Log All Relevant Context On Errors
|
|
9
|
+
|
|
10
|
+
Logs without context are nearly useless for production troubleshooting. Comprehensive context-rich logs allow developers to reconstruct the state that led to an error.
|
|
11
|
+
|
|
12
|
+
**Incorrect (minimal context):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
logger.error("Error occurred")
|
|
16
|
+
logger.error(exception.message)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Correct (comprehensive context):**
|
|
20
|
+
|
|
21
|
+
```kotlin
|
|
22
|
+
logger.error("Failed to process order", exception) {
|
|
23
|
+
// What happened
|
|
24
|
+
payload("errorCode" to exception.code)
|
|
25
|
+
|
|
26
|
+
// Core Business Context
|
|
27
|
+
payload("orderId" to order.id)
|
|
28
|
+
payload("userId" to user.id)
|
|
29
|
+
payload("requestId" to MDC.get("requestId")) // Assuming MDC use
|
|
30
|
+
|
|
31
|
+
// Input/State that caused the issue
|
|
32
|
+
payload("itemsCount" to order.items.size)
|
|
33
|
+
payload("totalAmount" to order.total)
|
|
34
|
+
|
|
35
|
+
// Timing information
|
|
36
|
+
payload("processingTimeMs" to System.currentTimeMillis() - startTime)
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Essential log context should include:**
|
|
41
|
+
- Error details (Exception name, full stack trace).
|
|
42
|
+
- Entity IDs (user ID, order ID, account ID).
|
|
43
|
+
- Coordination IDs (Request ID, Correlation ID, Trace ID).
|
|
44
|
+
- Summarized input data (avoid PII - Personal Identifiable Information).
|
|
45
|
+
- System state hints (environment, version).
|
|
46
|
+
|
|
47
|
+
**Tools:** SLF4J with Logback/Log4j2, Structured Logging (KLogging, Logstash Logback Encoder), Sentry
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: No Hardcoded Secrets In Repo
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: prevents sensitive credential exposure and security breaches
|
|
5
|
+
tags: secrets, credentials, security, git, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## No Hardcoded Secrets In Repo
|
|
9
|
+
|
|
10
|
+
Hardcoding sensitive credentials (API keys, DB passwords, private keys) in the source code or configuration files is a major security risk. Once committed, they are visible to anyone with access to the repo and historical versions.
|
|
11
|
+
|
|
12
|
+
**Incorrect (secrets in code):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
const val STRIPE_API_KEY = "sk_live_abc123"
|
|
16
|
+
val dbPassword = "root_password"
|
|
17
|
+
|
|
18
|
+
// HARDCODED in resource files or code
|
|
19
|
+
val connection = DriverManager.getConnection("jdbc:mysql://localhost/db", "admin", "secret123")
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Correct (environment/secrets manager):**
|
|
23
|
+
|
|
24
|
+
```kotlin
|
|
25
|
+
// Load from Environment Variables
|
|
26
|
+
val apiKey = System.getenv("API_KEY")
|
|
27
|
+
|
|
28
|
+
// Load from a secure property file (not committed to git)
|
|
29
|
+
val properties = Properties().apply {
|
|
30
|
+
val inputStream = FileInputStream("secrets.properties")
|
|
31
|
+
load(inputStream)
|
|
32
|
+
}
|
|
33
|
+
val dbPassword = properties.getProperty("DB_PASSWORD")
|
|
34
|
+
|
|
35
|
+
// Using a cloud secrets manager (AWS Secrets Manager, GCP Secret Manager, Vault)
|
|
36
|
+
val stripeKey = secretsClient.getSecret("stripe/live-key")
|
|
37
|
+
|
|
38
|
+
// Validate presence at startup
|
|
39
|
+
checkNotNull(apiKey) { "API_KEY environment variable must be set" }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Protecting Secrets:**
|
|
43
|
+
- Add `.env`, `secrets.properties`, `*.jks`, `*.pem` to `.gitignore`.
|
|
44
|
+
- Use CI/CD secrets for deployment.
|
|
45
|
+
- Avoid printing secrets to log files.
|
|
46
|
+
|
|
47
|
+
**Tools:** Gitleaks, TruffleHog, SonarQube, detekt (HardcodedSecret)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Boolean Names Is/Has/Should Prefix
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: makes conditional logic instantly readable and self-documenting
|
|
5
|
+
tags: naming, booleans, readability, conventions, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Boolean Names Is/Has/Should Prefix
|
|
9
|
+
|
|
10
|
+
Boolean variables and function names should start with a prefix that makes their true/false nature obvious. This improves readability of `if` statements and logical expressions.
|
|
11
|
+
|
|
12
|
+
**Incorrect (unclear boolean names):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
val active = user.status == "active"
|
|
16
|
+
val admin = checkAdminRole(user)
|
|
17
|
+
val items = cart.isNotEmpty()
|
|
18
|
+
val update = needsRefresh()
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Correct (clear boolean prefixes):**
|
|
22
|
+
|
|
23
|
+
```kotlin
|
|
24
|
+
val isActive = user.status == "active"
|
|
25
|
+
val isAdmin = checkAdminRole(user)
|
|
26
|
+
val hasItems = cart.isNotEmpty()
|
|
27
|
+
val shouldUpdate = needsRefresh()
|
|
28
|
+
val canEdit = user.hasPermission("edit")
|
|
29
|
+
val willExpire = expirationDate.isBefore(tomorrow)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Common Boolean Prefixes:**
|
|
33
|
+
|
|
34
|
+
| Prefix | Use Case | Example |
|
|
35
|
+
|--------|----------|---------|
|
|
36
|
+
| `is` | Status or State | `isActive`, `isEmpty`, `isReady` |
|
|
37
|
+
| `has` | Possession or Collection | `hasItems`, `hasPermission`, `hasMetadata` |
|
|
38
|
+
| `should` | Recommendations or Tasks | `shouldRetry`, `shouldSkip`, `shouldNotify` |
|
|
39
|
+
| `can` | Permissions or Capabilities | `canExecute`, `canSubmit`, `canDelete` |
|
|
40
|
+
| `will` | Future State | `willChange`, `willExpire`, `willSync` |
|
|
41
|
+
|
|
42
|
+
**Tools:** detekt, Android Studio Linter (Naming conventions), Code Review
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Separate Data Mapping From Controllers
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: keeps controllers thin, focused on HTTP concerns, and makes mapping logic reusable
|
|
5
|
+
tags: controller, parsing, transformation, mapping, patterns, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Separate Data Mapping From Controllers
|
|
9
|
+
|
|
10
|
+
Controllers should be thin and only responsible for handling HTTP requests, orchestrating service calls, and returning responses. Complex data transformations or mapping logic should be extracted into separate Mapper classes or Extension functions.
|
|
11
|
+
|
|
12
|
+
**Incorrect (mapping logic in controller):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
@RestController
|
|
16
|
+
class UserController(private val userService: UserService) {
|
|
17
|
+
|
|
18
|
+
@GetMapping("/users/{id}")
|
|
19
|
+
fun getUser(@PathVariable id: String): ResponseEntity<UserResponse> {
|
|
20
|
+
val user = userService.findById(id) ?: throw NotFoundException()
|
|
21
|
+
|
|
22
|
+
// Complex mapping logic inside controller
|
|
23
|
+
val response = UserResponse(
|
|
24
|
+
id = user.id,
|
|
25
|
+
fullName = "${user.firstName} ${user.lastName}",
|
|
26
|
+
email = user.email.lowercase(),
|
|
27
|
+
formattedDate = user.createdAt.format(DateTimeFormatter.ISO_DATE)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
return ResponseEntity.ok(response)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Correct (using Mappers or Extension Functions):**
|
|
36
|
+
|
|
37
|
+
```kotlin
|
|
38
|
+
// Option 1: Using a dedicated Mapper
|
|
39
|
+
object UserMapper {
|
|
40
|
+
fun toResponse(user: User): UserResponse = UserResponse(
|
|
41
|
+
id = user.id,
|
|
42
|
+
fullName = "${user.firstName} ${user.lastName}",
|
|
43
|
+
email = user.email.lowercase(),
|
|
44
|
+
formattedDate = user.createdAt.format(DateTimeFormatter.ISO_DATE)
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Option 2: Using Kotlin Extension Functions
|
|
49
|
+
fun User.toResponse(): UserResponse = UserResponse(
|
|
50
|
+
id = id,
|
|
51
|
+
fullName = "$firstName $lastName",
|
|
52
|
+
email = email.lowercase(),
|
|
53
|
+
formattedDate = createdAt.format(DateTimeFormatter.ISO_DATE)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
// Clean and focused controller
|
|
57
|
+
@RestController
|
|
58
|
+
class UserController(private val userService: UserService) {
|
|
59
|
+
@GetMapping("/users/{id}")
|
|
60
|
+
fun getUser(@PathVariable id: String): UserResponse {
|
|
61
|
+
return userService.findById(id)?.toResponse() ?: throw NotFoundException()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Benefits:**
|
|
67
|
+
- **Reusability:** The same mapping logic can be used across multiple controllers or background jobs.
|
|
68
|
+
- **Testability:** Mappers can be unit-tested in isolation without mocking HTTP infrastructure.
|
|
69
|
+
- **Maintainability:** Changes to API formats are centralized.
|
|
70
|
+
|
|
71
|
+
**Tools:** MapStruct, Kotlin Extension Functions, ModelMapper, Architectural Review
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Do Not Ignore Superclass Logic
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: ensures proper inheritance behavior and execution of base class contracts
|
|
5
|
+
tags: inheritance, override, superclass, oop, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Do Not Ignore Superclass Logic
|
|
9
|
+
|
|
10
|
+
When overriding methods in Kotlin, it is crucial to call the `super` implementation unless you explicitly intend to replace it entirely. Ignoring superclass logic often leads to missing validations, hooks, or lifecycle events defined in the base class.
|
|
11
|
+
|
|
12
|
+
**Incorrect (ignoring superclass):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
open class BaseService {
|
|
16
|
+
open fun save(entity: Entity) {
|
|
17
|
+
validate(entity)
|
|
18
|
+
db.save(entity)
|
|
19
|
+
logger.info("Entity saved")
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class UserService : BaseService() {
|
|
24
|
+
override fun save(user: User) {
|
|
25
|
+
// BUG: Skips validation and logging from the base class!
|
|
26
|
+
db.save(user)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Correct (calling super):**
|
|
32
|
+
|
|
33
|
+
```kotlin
|
|
34
|
+
class UserService : BaseService() {
|
|
35
|
+
override fun save(user: User) {
|
|
36
|
+
// Perform user-specific logic
|
|
37
|
+
user.lastModified = Instant.now()
|
|
38
|
+
|
|
39
|
+
// Ensure base class logic (validation, etc.) is executed
|
|
40
|
+
super.save(user)
|
|
41
|
+
|
|
42
|
+
// Add additional post-save logic
|
|
43
|
+
notifyAdmins(user)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Exception (intentional replacement):**
|
|
49
|
+
|
|
50
|
+
```kotlin
|
|
51
|
+
class AdminService : BaseService() {
|
|
52
|
+
// Override: Admins bypass standard validation logic
|
|
53
|
+
override fun save(admin: User) {
|
|
54
|
+
// Intentionally skip super.save()
|
|
55
|
+
db.save(admin)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Tools:** Android Studio / IntelliJ IDEA hints, detekt, Code Review
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Do Not Hardcode Configuration
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables environment-specific deployments without code changes
|
|
5
|
+
tags: configuration, environment, deployment, quality, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Do Not Hardcode Configuration
|
|
9
|
+
|
|
10
|
+
Configuration values that change between environments (Development, Staging, Production) should never be hardcoded in the source code. Hardcoding necessitates re-compilation and re-deployment for simple configuration changes and risks exposing production settings in lower environments.
|
|
11
|
+
|
|
12
|
+
**Incorrect (hardcoded config):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
const val API_URL = "https://api.production.sun-asterisk.vn"
|
|
16
|
+
const val TIMEOUT_MS = 5000
|
|
17
|
+
const val MAX_RETRIES = 3
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (externalized configuration):**
|
|
21
|
+
|
|
22
|
+
```kotlin
|
|
23
|
+
// In Spring Boot: use application.yml/properties with placeholders
|
|
24
|
+
// api.url: ${API_URL:http://localhost:8080}
|
|
25
|
+
|
|
26
|
+
@ConfigurationProperties(prefix = "app")
|
|
27
|
+
data class AppConfig(
|
|
28
|
+
val apiUrl: String,
|
|
29
|
+
val timeoutMs: Int = 5000,
|
|
30
|
+
val maxRetries: Int = 3
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
// In Ktor: use HOCON configuration (application.conf)
|
|
34
|
+
// storage {
|
|
35
|
+
// bucket = ${?STORAGE_BUCKET}
|
|
36
|
+
// }
|
|
37
|
+
|
|
38
|
+
val bucket = environment.config.propertyOrNull("storage.bucket")?.getString()
|
|
39
|
+
?: "default-dev-bucket"
|
|
40
|
+
|
|
41
|
+
// Manual Environment Access
|
|
42
|
+
val dbUrl = System.getenv("DATABASE_URL") ?: "jdbc:h2:mem:test"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Best Practices:**
|
|
46
|
+
- Use environment variables for sensitive or environment-specific values.
|
|
47
|
+
- Provide sensible defaults for local development.
|
|
48
|
+
- Validate required configuration values at application startup (fail-fast).
|
|
49
|
+
- Avoid "magic strings" for configuration keys; use typesafe configuration classes.
|
|
50
|
+
|
|
51
|
+
**Tools:** Spring Boot `@ConfigurationProperties`, Ktor `HoconApplicationConfig`, `dotenv-kotlin`, Manual Review
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: URL Redirects Must Be In Allow List
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents open redirect vulnerabilities used in phishing attacks
|
|
5
|
+
tags: redirect, url, allow-list, validation, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## URL Redirects Must Be In Allow List
|
|
9
|
+
|
|
10
|
+
Open redirect vulnerabilities allow attackers to use your trusted domain to redirect users to malicious sites. This is commonly used in phishing campaigns to make malicious URLs look legitimate.
|
|
11
|
+
|
|
12
|
+
**Incorrect (unvalidated redirect URL):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// Open redirect vulnerability
|
|
16
|
+
@GetMapping("/redirect")
|
|
17
|
+
fun redirect(request: HttpServletRequest, response: HttpServletResponse) {
|
|
18
|
+
val url = request.getParameter("url")
|
|
19
|
+
response.sendRedirect(url) // Attacker: ?url=https://evil.com
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Partial validation (bypassable)
|
|
23
|
+
if (url.contains("sun-asterisk.vn")) {
|
|
24
|
+
response.sendRedirect(url) // Bypass: https://attacker.com?sun-asterisk.vn
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Correct (allow list or relative path validation):**
|
|
29
|
+
|
|
30
|
+
```kotlin
|
|
31
|
+
import java.net.URI
|
|
32
|
+
|
|
33
|
+
private val ALLOWED_HOSTS = setOf("sun-asterisk.vn", "app.sun-asterisk.vn")
|
|
34
|
+
|
|
35
|
+
@GetMapping("/redirect")
|
|
36
|
+
fun safeRedirect(@RequestParam url: String, response: HttpServletResponse) {
|
|
37
|
+
try {
|
|
38
|
+
val uri = URI(url)
|
|
39
|
+
val host = uri.host
|
|
40
|
+
|
|
41
|
+
// 1. Validate against allow list (for absolute URLs)
|
|
42
|
+
if (host != null && !ALLOWED_HOSTS.contains(host)) {
|
|
43
|
+
throw SecurityException("Host not allowed")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2. Or enforce relative paths only (safe for internal navigation)
|
|
47
|
+
if (host == null) {
|
|
48
|
+
if (!url.startsWith("/") || url.startsWith("//")) {
|
|
49
|
+
throw SecurityException("Invalid relative path")
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
response.sendRedirect(url)
|
|
54
|
+
} catch (e: Exception) {
|
|
55
|
+
response.sendError(400, "Invalid URL")
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Security Best Practices:**
|
|
61
|
+
- Prefer relative URLs over absolute URLs for internal redirects.
|
|
62
|
+
- If absolute URLs are required, strictly validate the `host` against an allow list.
|
|
63
|
+
- Reject URLs that use the `//` shorthand (protocol-relative) to avoid cross-domain redirects.
|
|
64
|
+
- Display a transition page for redirects to external unlisted sites.
|
|
65
|
+
|
|
66
|
+
**Tools:** SonarQube (S5144, S1134), Semgrep, Manual Security Audit
|