@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,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Validate OAuth Redirect URIs Exactly
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: prevents authorization code theft by ensuring tokens are only sent to verified client URLs
|
|
5
|
+
tags: oauth, redirect, uri, validation, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Validate OAuth Redirect URIs Exactly
|
|
9
|
+
|
|
10
|
+
When acting as an OAuth 2.0 Identity Provider (IdP) or using an external one, the `redirect_uri` parameter must be validated against an exact, pre-registered whitelist. Loose validation (like prefix matching or regex) can be bypassed by attackers to steal secrets.
|
|
11
|
+
|
|
12
|
+
**Incorrect (partial or loose validation):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// VULNERABLE: Substring matching
|
|
16
|
+
if (redirectUri.contains("sun-asterisk.vn")) {
|
|
17
|
+
// Attack: https://attacker.com?sun-asterisk.vn
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// VULNERABLE: Prefix matching without trailing slash
|
|
21
|
+
if (redirectUri.startsWith("https://app.sun-asterisk.vn")) {
|
|
22
|
+
// Attack: https://app.sun-asterisk.vn.attacker.com/callback
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Correct (exact match against registered URIs):**
|
|
27
|
+
|
|
28
|
+
```kotlin
|
|
29
|
+
private val ALLOWED_REDIRECT_URIS = setOf(
|
|
30
|
+
"https://auth.sun-asterisk.vn/callback",
|
|
31
|
+
"https://mobile.sun-asterisk.vn/oauth/success"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
fun validateRedirectUri(inputUri: String) {
|
|
35
|
+
// MUST perform a case-sensitive exact string comparison
|
|
36
|
+
if (!ALLOWED_REDIRECT_URIS.contains(inputUri)) {
|
|
37
|
+
throw SecurityException("Unauthorized redirect_uri: $inputUri")
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// If acting as an OAuth Provider (Spring Security Auth Server)
|
|
42
|
+
@Configuration
|
|
43
|
+
class SecurityConfig {
|
|
44
|
+
@Bean
|
|
45
|
+
fun registeredClientRepository(): RegisteredClientRepository {
|
|
46
|
+
return InMemoryRegisteredClientRepository(
|
|
47
|
+
RegisteredClient.withId("client-id")
|
|
48
|
+
.redirectUri("https://app.example.com/login/oauth2/code/gateway") // Exact
|
|
49
|
+
.build()
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Security Requirements:**
|
|
56
|
+
1. **Exact Matching:** Use `equals()` or Set `contains()`. Never use `startsWith` or `contains`.
|
|
57
|
+
2. **No Wildcards:** Do not support wildcards in redirect URIs.
|
|
58
|
+
3. **HTTPS Only:** In production, only allow `https://` (except for specific localhost dev cases if strictly necessary).
|
|
59
|
+
4. **Pre-Registration:** The client must register their redirect URIs before they can initiate any OAuth flows.
|
|
60
|
+
|
|
61
|
+
**Tools:** Spring Security OAuth2, OWASP ZAP, Manual Audit, Penetration Testing
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Authentication Codes Must Expire Quickly
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: reduces the time window for attackers to brute-force or intercept one-time codes
|
|
5
|
+
tags: authentication, codes, expiry, otp, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Authentication Codes Must Expire Quickly
|
|
9
|
+
|
|
10
|
+
One-time codes (OTP) used for password resets, 2FA, or login links should have a very short operational lifespan. The longer a code is valid, the more time an attacker has to social engineer the code from the victim or brute-force it.
|
|
11
|
+
|
|
12
|
+
**Incorrect (long-lived or non-expiring codes):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// VULNERABLE: Code remains valid for 24 hours
|
|
16
|
+
val resetToken = UUID.randomUUID().toString()
|
|
17
|
+
db.save(ResetToken(userId, resetToken, createdAt = Instant.now()))
|
|
18
|
+
|
|
19
|
+
// In the verification logic:
|
|
20
|
+
fun verify(token: String) {
|
|
21
|
+
val record = db.findByToken(token) ?: throw Exception("Invalid")
|
|
22
|
+
// No check for time elapsed!
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Correct (short expiry with state management):**
|
|
27
|
+
|
|
28
|
+
```kotlin
|
|
29
|
+
import java.time.Duration
|
|
30
|
+
import java.time.Instant
|
|
31
|
+
|
|
32
|
+
private val OTP_EXPIRY = Duration.ofMinutes(5)
|
|
33
|
+
|
|
34
|
+
fun generateAndStoreOtp(userId: String) {
|
|
35
|
+
val code = (100000..999999).random().toString()
|
|
36
|
+
|
|
37
|
+
// Store in Redis with TTL (Time To Live)
|
|
38
|
+
redis.set("otp:$userId", code, OTP_EXPIRY.toSeconds())
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fun verifyOtp(userId: String, inputCode: String): Boolean {
|
|
42
|
+
val storedCode = redis.get("otp:$userId")
|
|
43
|
+
|
|
44
|
+
if (storedCode == null) {
|
|
45
|
+
throw ExpiredCodeException("OTP has expired")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (storedCode == inputCode) {
|
|
49
|
+
// IMPORTANT: Invalidate the code immediately after successful use
|
|
50
|
+
redis.del("otp:$userId")
|
|
51
|
+
return true
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Increment failure counter for rate limiting...
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Recommended Expiry Guidelines:**
|
|
60
|
+
- **2FA / Login Codes:** 2 - 10 minutes.
|
|
61
|
+
- **Magic Login Links:** 15 - 30 minutes.
|
|
62
|
+
- **Email Verification:** 24 hours (security requirement is lower than active login).
|
|
63
|
+
- **Password Reset:** 15 - 60 minutes.
|
|
64
|
+
|
|
65
|
+
**Security Checklist:**
|
|
66
|
+
1. **Single Use:** Delete the code immediately upon successful verification.
|
|
67
|
+
2. **Rate Limiting:** Lock the account or the OTP flow after 3-5 failed attempts.
|
|
68
|
+
3. **Secure Generation:** Use `SecureRandom` instead of `Random` for code generation.
|
|
69
|
+
|
|
70
|
+
**Tools:** Redis (with EXPIRE), Spring Security, Manual Audit
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Reference Tokens 128-bit Entropy CSPRNG
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents session hijacking via token guessing or brute-forcing
|
|
5
|
+
tags: tokens, entropy, csprng, session, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Reference Tokens 128-bit Entropy CSPRNG
|
|
9
|
+
|
|
10
|
+
Opaque tokens (session IDs, API keys, reset tokens) must be generated using a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) and contain enough entropy (randomness) to make them impossible to guess. 128 bits of entropy is the modern minimum standard.
|
|
11
|
+
|
|
12
|
+
**Incorrect (low entropy or predictable tokens):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// VULNERABLE: Predicatable and low entropy (around 53 bits)
|
|
16
|
+
val id = (Math.random() * 1000000).toLong().toString()
|
|
17
|
+
|
|
18
|
+
// VULNERABLE: Short tokens (only 32 bits if using 4 hex chars)
|
|
19
|
+
val token = List(4) { ('a'..'z').random() }.joinToString("")
|
|
20
|
+
|
|
21
|
+
// INSECURE: Using non-secure Random
|
|
22
|
+
val random = java.util.Random()
|
|
23
|
+
val weakToken = BigInteger(130, random).toString(32)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Correct (high entropy bytes from CSPRNG):**
|
|
27
|
+
|
|
28
|
+
```kotlin
|
|
29
|
+
import java.security.SecureRandom
|
|
30
|
+
import java.util.Base64
|
|
31
|
+
|
|
32
|
+
// 1. 128-bit minimum (16 bytes = 128 bits)
|
|
33
|
+
val secureRandom = SecureRandom()
|
|
34
|
+
|
|
35
|
+
fun generateSessionToken(): String {
|
|
36
|
+
val bytes = ByteArray(16)
|
|
37
|
+
secureRandom.nextBytes(bytes)
|
|
38
|
+
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. 256-bit for highly sensitive tokens (32 bytes)
|
|
42
|
+
fun generateApiKey(): String {
|
|
43
|
+
val bytes = ByteArray(32)
|
|
44
|
+
secureRandom.nextBytes(bytes)
|
|
45
|
+
return "sk_" + Base64.getUrlEncoder().withoutPadding().encodeToString(bytes)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 3. Using UUID (Standardized 128-bit random token)
|
|
49
|
+
val uuidToken = UUID.randomUUID().toString()
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Security Benchmarks:**
|
|
53
|
+
|
|
54
|
+
| Length | Entropy (approx) | Usage Recommendation |
|
|
55
|
+
| :--- | :--- | :--- |
|
|
56
|
+
| 16 bytes | 128 bits | **Minimum** for session tokens |
|
|
57
|
+
| 24 bytes | 192 bits | Strong |
|
|
58
|
+
| 32 bytes | 256 bits | **Recommended** for Long-lived API keys / Refresh tokens |
|
|
59
|
+
|
|
60
|
+
**Entropy Requirements:**
|
|
61
|
+
- Use `java.security.SecureRandom`.
|
|
62
|
+
- Ensure tokens are long enough. A Hex-encoded string needs twice as many characters as the raw bytes (e.g., 32 hex chars for 16 bytes).
|
|
63
|
+
- Do not include identifying information (like User IDs or IDs) in opaque reference tokens.
|
|
64
|
+
|
|
65
|
+
**Tools:** OWASP ZAP, Manual Review, SonarQube (S2245)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Support 12-64 Character Passwords
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: enables secure passphrase usage and improves account security
|
|
5
|
+
tags: password, length, passphrase, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Support 12-64 Character Passwords
|
|
9
|
+
|
|
10
|
+
Longer passwords (passphrases) are significantly harder to crack than short, complex ones. Restricting password length to small values (like 16 characters) prevents users from choosing highly secure passphrases.
|
|
11
|
+
|
|
12
|
+
**Incorrect (too restrictive limits):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
data class UserRegistration(
|
|
16
|
+
@get:Size(min = 8, max = 16) val password: String // Too short!
|
|
17
|
+
)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (reasonable limits following modern standards):**
|
|
21
|
+
|
|
22
|
+
```kotlin
|
|
23
|
+
data class UserRegistration(
|
|
24
|
+
@get:NotBlank
|
|
25
|
+
@get:Size(min = 12, max = 64, message = "Password must be 12-64 characters")
|
|
26
|
+
val password: String
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
// Dynamic complexity requirements
|
|
30
|
+
fun isPasswordSecure(password: String): Boolean {
|
|
31
|
+
// Basic length check
|
|
32
|
+
if (password.length !in 12..64) return false
|
|
33
|
+
|
|
34
|
+
// NIST: Long passphrases (16+) don't need arbitrary complexity rules
|
|
35
|
+
if (password.length >= 16) return true
|
|
36
|
+
|
|
37
|
+
// Shorter passwords (12-15) should have complexity
|
|
38
|
+
val hasUpper = password.any { it.isUpperCase() }
|
|
39
|
+
val hasLower = password.any { it.isLowerCase() }
|
|
40
|
+
val hasDigit = password.any { it.isDigit() }
|
|
41
|
+
|
|
42
|
+
return hasUpper && hasLower && hasDigit
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Modern Password Guidelines:**
|
|
47
|
+
- **Minimum:** 12 characters (absolute minimum 8).
|
|
48
|
+
- **Maximum:** At least 64 characters (allow up to 128 if possible).
|
|
49
|
+
- **Composition:** Allow all characters, including spaces and Unicode.
|
|
50
|
+
- **Truncation:** Never truncate passwords before hashing.
|
|
51
|
+
|
|
52
|
+
**Tools:** Bean Validation (@Size), Manual Review, OWASP Password Policy
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: OTPs Must Have 20-bit Entropy Minimum
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents attackers from guessing one-time passwords through automated trials
|
|
5
|
+
tags: otp, entropy, authentication, 2fa, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## OTPs Must Have 20-bit Entropy Minimum
|
|
9
|
+
|
|
10
|
+
One-Time Passwords (OTPs) are naturally shorter than session tokens, making them more susceptible to brute-force attacks. To compensate, they must have at least 20 bits of entropy (which roughly corresponds to a 6-digit numeric code) and be protected by strict rate-limiting.
|
|
11
|
+
|
|
12
|
+
**Incorrect (low entropy OTPs):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// VULNERABLE: Only 4 digits = 10,000 possibilities (approx 13 bits)
|
|
16
|
+
val weakOtp = (1000..9999).random().toString()
|
|
17
|
+
|
|
18
|
+
// VULNERABLE: Predicatable non-random source
|
|
19
|
+
val timeBased = System.currentTimeMillis().toString().takeLast(6)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Correct (secure, high-entropy OTP generation):**
|
|
23
|
+
|
|
24
|
+
```kotlin
|
|
25
|
+
import java.security.SecureRandom
|
|
26
|
+
|
|
27
|
+
private val secureRandom = SecureRandom()
|
|
28
|
+
|
|
29
|
+
// 1. 6-digit numeric OTP (~20 bits entropy) - Standard
|
|
30
|
+
fun generateOtp(): String {
|
|
31
|
+
val number = secureRandom.nextInt(1_000_000)
|
|
32
|
+
return String.format("%06d", number)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 2. 8-digit numeric OTP (~26 bits entropy) - Highly Secure
|
|
36
|
+
fun generateStrongOtp(): String {
|
|
37
|
+
val number = secureRandom.nextInt(100_000_000)
|
|
38
|
+
return String.format("%08d", number)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 3. Alphanumeric OTP for extra entropy in shorter lengths
|
|
42
|
+
// (6-char alphanumeric ≈ 30+ bits entropy)
|
|
43
|
+
val allowedChars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" // Avoid ambiguous chars (I/1, O/0)
|
|
44
|
+
fun generateAlphanumericOtp(): String {
|
|
45
|
+
return (1..6).map { allowedChars[secureRandom.nextInt(allowedChars.length)] }.joinToString("")
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Security Controls for OTPs:**
|
|
50
|
+
1. **Strict Rate Limiting:** This is the most important defense for OTPs. Block the user or IP after 3-5 failed attempts.
|
|
51
|
+
2. **Short Expiry:** Limit the validity to a few minutes (e.g., 5 mins).
|
|
52
|
+
3. **Secure Generation:** Always use a CSPRNG (`SecureRandom`).
|
|
53
|
+
4. **Single Use:** Invalidate the code immediately after any attempt (success or failure) to verify it, or at least after a success.
|
|
54
|
+
|
|
55
|
+
**Tools:** OWASP ESAPI, Google Authenticator (TOTP), Manual Audit, SonarQube (S2245)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Return Generic Error Messages
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents information disclosure and system reconnaissance
|
|
5
|
+
tags: error-messages, information-disclosure, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Return Generic Error Messages
|
|
9
|
+
|
|
10
|
+
Detailed error messages can expose internal system implementation details, database structures, or specific library versions to attackers. This information is invaluable for planning more targeted attacks.
|
|
11
|
+
|
|
12
|
+
**Incorrect (detailed errors exposed to client):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// Spring Boot Exception Handler exposing EVERYTHING
|
|
16
|
+
@ExceptionHandler(Exception::class)
|
|
17
|
+
fun handleAll(e: Exception): ResponseEntity<Any> {
|
|
18
|
+
val body = mapOf(
|
|
19
|
+
"message" to e.message,
|
|
20
|
+
"class" to e.javaClass.name,
|
|
21
|
+
"stackTrace" to e.stackTrace // CRITICAL: Never send stack traces to clients!
|
|
22
|
+
)
|
|
23
|
+
return ResponseEntity.status(500).body(body)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// User Enumeration vulnerability
|
|
27
|
+
if (user == null) {
|
|
28
|
+
return ResponseEntity.status(401).body("User not found")
|
|
29
|
+
}
|
|
30
|
+
if (!passwordValid) {
|
|
31
|
+
return ResponseEntity.status(401).body("Incorrect password")
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Correct (generic errors with internal tracking):**
|
|
36
|
+
|
|
37
|
+
```kotlin
|
|
38
|
+
@ExceptionHandler(Exception::class)
|
|
39
|
+
fun handleAll(e: Exception, request: WebRequest): ResponseEntity<Any> {
|
|
40
|
+
val trackingId = UUID.randomUUID().toString()
|
|
41
|
+
|
|
42
|
+
// Log full details internally
|
|
43
|
+
logger.error("Internal Error #$trackingId on ${request.getDescription(false)}", e)
|
|
44
|
+
|
|
45
|
+
// Provide a generic message and a tracking ID for the user to report
|
|
46
|
+
val body = mapOf(
|
|
47
|
+
"error" to "An internal system error occurred",
|
|
48
|
+
"code" to 500,
|
|
49
|
+
"trackingId" to trackingId
|
|
50
|
+
)
|
|
51
|
+
return ResponseEntity.status(500).body(body)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Same message for both prevents user enumeration
|
|
55
|
+
if (user == null || !passwordValid) {
|
|
56
|
+
return ResponseEntity.status(401).body("Invalid username or password")
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Security Best Practices:**
|
|
61
|
+
- Never return stack traces, raw query strings, or file paths in API responses.
|
|
62
|
+
- Use a Global Exception Handler to catch and sanitize all unhandled exceptions.
|
|
63
|
+
- Ensure authentication messages are identical regardless of whether the username exists.
|
|
64
|
+
- In production, disable Spring's `server.error.include-stacktrace` property.
|
|
65
|
+
|
|
66
|
+
**Tools:** Spring `@ControllerAdvice`, Ktor `StatusPages`, OWASP ZAP, Manual Audit
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Avoid Default Admin/Root Accounts
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents easy initial compromise via well-known default administrative credentials
|
|
5
|
+
tags: admin, default-accounts, credentials, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Avoid Default Admin/Root Accounts
|
|
9
|
+
|
|
10
|
+
Applications that ship with default administrative accounts (e.g., `admin/password`) are prime targets for automated attacks. Attackers scan for these default login paths and credentials as their first step in a system breach.
|
|
11
|
+
|
|
12
|
+
**Incorrect (default admin in seeds or config):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// Database migration/seed creating a default admin
|
|
16
|
+
fun seedDatabase() {
|
|
17
|
+
val adminExists = repository.existsByRole("ADMIN")
|
|
18
|
+
if (!adminExists) {
|
|
19
|
+
val root = User(email = "admin@example.com", password = passwordEncoder.encode("admin123"), role = "ADMIN")
|
|
20
|
+
repository.save(root)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (secure initial setup):**
|
|
26
|
+
|
|
27
|
+
```kotlin
|
|
28
|
+
// 1. Initial setup wizard approach
|
|
29
|
+
@PostMapping("/api/initial-setup")
|
|
30
|
+
fun setupAdmin(@RequestBody request: AdminSetupRequest): ResponseEntity<Any> {
|
|
31
|
+
if (userService.hasAnyAdmin()) {
|
|
32
|
+
return ResponseEntity.status(403).body("Setup already completed")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Validate password complexity
|
|
36
|
+
if (request.password.length < 16) {
|
|
37
|
+
return ResponseEntity.badRequest().body("Initial admin password must be at least 16 characters")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
userService.createAdmin(request.email, request.password)
|
|
41
|
+
return ResponseEntity.ok("Admin account created successfully")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 2. Environment-based initial credentials
|
|
45
|
+
val initialAdminPass = System.getenv("INITIAL_ADMIN_PASSWORD")
|
|
46
|
+
if (initialAdminPass.isNullOrBlank() || initialAdminPass.length < 12) {
|
|
47
|
+
throw IllegalStateException("A strong INITIAL_ADMIN_PASSWORD must be provided via environment variables")
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Security Best Practices:**
|
|
52
|
+
- Never hardcode administrative credentials in logic or configuration files.
|
|
53
|
+
- Force an administrative password change on first login if a temporary password is provided.
|
|
54
|
+
- Avoid obvious usernames like `admin`, `root`, `administrator`, or `sysadmin`.
|
|
55
|
+
- Use Multi-Factor Authentication (MFA) for all administrative access.
|
|
56
|
+
|
|
57
|
+
**Tools:** Security Audit, Penetration Testing, CI/CD configuration checks.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Validate Content-Type In REST Services
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents content-type confusion attacks and parsing vulnerabilities
|
|
5
|
+
tags: rest, content-type, validation, api, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Validate Content-Type In REST Services
|
|
9
|
+
|
|
10
|
+
Accepting any content type on your API endpoints can lead to unexpected parsing behavior or bypass security filters. For example, an attacker might send XML to an endpoint expecting JSON to trigger an XXE (XML External Entity) attack.
|
|
11
|
+
|
|
12
|
+
**Incorrect (no content-type validation):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// Ktor: Receiving raw body without validation
|
|
16
|
+
post("/api/data") {
|
|
17
|
+
val body = call.receiveText()
|
|
18
|
+
// No check if this is JSON, XML, or plain text
|
|
19
|
+
process(body)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Spring Boot: Permissive mapping
|
|
23
|
+
@PostMapping("/api/data", consumes = ["*/*"])
|
|
24
|
+
fun handle(@RequestBody data: String) { ... }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Correct (strict content-type validation):**
|
|
28
|
+
|
|
29
|
+
```kotlin
|
|
30
|
+
// Spring Boot: Explicit 'consumes' constraint
|
|
31
|
+
@PostMapping("/api/data", consumes = [MediaType.APPLICATION_JSON_VALUE])
|
|
32
|
+
fun handle(@RequestBody data: MyDataModel): ResponseEntity<Any> {
|
|
33
|
+
return ResponseEntity.ok(Success())
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Ktor: Content-Type check in interceptor or route
|
|
37
|
+
post("/api/data") {
|
|
38
|
+
val contentType = call.request.contentType()
|
|
39
|
+
if (contentType.withoutParameters() != ContentType.Application.Json) {
|
|
40
|
+
call.respond(HttpStatusCode.UnsupportedMediaType, "Only application/json is supported")
|
|
41
|
+
return@post
|
|
42
|
+
}
|
|
43
|
+
val data = call.receive<MyDataModel>()
|
|
44
|
+
// ...
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Multpart requirement for uploads
|
|
48
|
+
@PostMapping("/api/upload", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
|
|
49
|
+
fun upload(@RequestParam("file") file: MultipartFile) { ... }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Best Practices:**
|
|
53
|
+
- Use the `consumes` attribute in Spring's `@RequestMapping` or `@PostMapping`.
|
|
54
|
+
- Always return the `415 Unsupported Media Type` status code when the content type is not allowed.
|
|
55
|
+
- Ensure that the parser (JSON, XML) is configured securely (e.g., disabling external entities for XML).
|
|
56
|
+
- Avoid generic types like `application/octet-stream` unless specifically handling binary data.
|
|
57
|
+
|
|
58
|
+
**Tools:** Spring Security, Ktor ContentNegotiation, OWASP ZAP, API Gateway (e.g., Kong, AWS Gateway)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Protect Against Log Injection
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents log forging, track hiding, and malicious content injection
|
|
5
|
+
tags: logging, injection, sanitization, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Protect Against Log Injection
|
|
9
|
+
|
|
10
|
+
Log injection occurs when user-controlled data is written to a log file without sanitization. An attacker can inject newline characters to forge log entries or inject malicious payloads that could be executed by log analysis tools.
|
|
11
|
+
|
|
12
|
+
**Incorrect (unsanitized logging):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// Log injection vulnerability
|
|
16
|
+
val username = request.getParameter("username")
|
|
17
|
+
logger.info("User logged in: $username")
|
|
18
|
+
|
|
19
|
+
// Attacker input: "admin\n[2024-01-01] ERROR Database connection failed"
|
|
20
|
+
// Results in two lines in the log, one of which is fake.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Correct (structured and sanitized logging):**
|
|
24
|
+
|
|
25
|
+
```kotlin
|
|
26
|
+
// Use structured logging (automatically handles many injection risks)
|
|
27
|
+
logger.info("User logged in", StructuredArguments.value("username", sanitize(username)))
|
|
28
|
+
|
|
29
|
+
// Sanitize manual log input
|
|
30
|
+
fun sanitize(input: String?): String {
|
|
31
|
+
if (input == null) return ""
|
|
32
|
+
return input
|
|
33
|
+
.replace("[\r\n\t]".toRegex(), " ") // Replace newlines/tabs with space
|
|
34
|
+
.take(255) // Limit length to prevent log bloating attacks
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Logback configuration can also be set to replace newlines automatically:
|
|
38
|
+
// %-5p [%d] %c: %replace(%m){'[\r\n]', ''}%n
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Prevention Strategies:**
|
|
42
|
+
- Always use structured logging (e.g., Logstash Logback Encoder).
|
|
43
|
+
- Sanitize any user-controlled input before logging by stripping or replacing CRLF characters.
|
|
44
|
+
- Configure log appender to escape control characters.
|
|
45
|
+
- Limit the size of logged variables.
|
|
46
|
+
|
|
47
|
+
**Tools:** SonarQube (S2245), Semgrep, OWASP ESAPI (for Java/Kotlin), Manual Audit
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Synchronized Time (UTC) In Logs
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: enables accurate incident correlation and audit trail reconstruction across distributed systems
|
|
5
|
+
tags: logging, time, utc, synchronization, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Synchronized Time (UTC) In Logs
|
|
9
|
+
|
|
10
|
+
When an incident occurs, investigators need to correlate logs from multiple servers, databases, and third-party services. If timestamps are in different timezones or out of sync, reconstructing the timeline is nearly impossible.
|
|
11
|
+
|
|
12
|
+
**Incorrect (local time or inconsistent formats):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// Uses server's local timezone
|
|
16
|
+
logger.info("User action at ${Date()}")
|
|
17
|
+
|
|
18
|
+
// Inconsistent formats
|
|
19
|
+
println("[${System.currentTimeMillis()}] Event")
|
|
20
|
+
println("[${LocalDateTime.now()}] Event")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Correct (UTC with ISO 8601 format):**
|
|
24
|
+
|
|
25
|
+
```kotlin
|
|
26
|
+
import java.time.Instant
|
|
27
|
+
import java.time.format.DateTimeFormatter
|
|
28
|
+
|
|
29
|
+
// 1. Use Instant (Always UTC)
|
|
30
|
+
val timestamp = Instant.now().toString() // Output: 2024-01-15T10:30:00.000Z
|
|
31
|
+
|
|
32
|
+
// 2. Structured logging with ISO 8601 (Recommended)
|
|
33
|
+
logger.info("User action") {
|
|
34
|
+
payload("timestamp" to Instant.now().toString())
|
|
35
|
+
payload("userId" to user.id)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 3. Configure Logback to use UTC
|
|
39
|
+
// In logback.xml:
|
|
40
|
+
// <timestamp key="bySecond" datePattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" timeReference="UTC"/>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**System Requirements:**
|
|
44
|
+
- **UTC Everywhere:** Application logic, database storage, and logs should all use UTC.
|
|
45
|
+
- **ISO 8601:** Use the standardized format `YYYY-MM-DDTHH:mm:ss.SSSZ`.
|
|
46
|
+
- **NTP:** Ensure all servers in the cluster use the Network Time Protocol (NTP) to stay synchronized with a precise time source.
|
|
47
|
+
- **Precision:** Log with at least millisecond precision.
|
|
48
|
+
|
|
49
|
+
**Tools:** `java.time` (JSR-310), Logback, NTP, Sentry, Elasticsearch/Kibana
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Protect Against SSRF Attacks
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: prevents attackers from making requests to internal infrastructure or cloud metadata endpoints via the server
|
|
5
|
+
tags: ssrf, url, network, internal, security, kotlin
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Protect Against SSRF Attacks
|
|
9
|
+
|
|
10
|
+
Server-Side Request Forgery (SSRF) allows an attacker to force the server to make HTTP requests to an arbitrary domain. This is often used to scan internal networks, access private local services (e.g., Redis, DBs), or steal credentials from Cloud Metadata services (AWS/GCP/Azure metadata endpoints).
|
|
11
|
+
|
|
12
|
+
**Incorrect (trusting user-provided URLs):**
|
|
13
|
+
|
|
14
|
+
```kotlin
|
|
15
|
+
// VULNERABLE: Direct use of user input in a network client
|
|
16
|
+
@GetMapping("/proxy")
|
|
17
|
+
fun fetchUrl(@RequestParam url: String): String {
|
|
18
|
+
val client = HttpClient.newHttpClient()
|
|
19
|
+
val request = HttpRequest.newBuilder().uri(URI.create(url)).build()
|
|
20
|
+
return client.send(request, BodyHandlers.ofString()).body()
|
|
21
|
+
}
|
|
22
|
+
// Attacker: /proxy?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (strict validation and allow-listing):**
|
|
26
|
+
|
|
27
|
+
```kotlin
|
|
28
|
+
import java.net.InetAddress
|
|
29
|
+
import java.net.URI
|
|
30
|
+
|
|
31
|
+
private val ALLOWED_DOMAINS = setOf("trusted-api.com", "cdn.com")
|
|
32
|
+
|
|
33
|
+
fun safeFetch(targetUrl: String): String {
|
|
34
|
+
val uri = URI(targetUrl)
|
|
35
|
+
|
|
36
|
+
// 1. Protocol Whitelist
|
|
37
|
+
if (uri.scheme != "http" && uri.scheme != "https") {
|
|
38
|
+
throw SecurityException("Protocol not allowed")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. Domain Whitelist (Recommended)
|
|
42
|
+
if (!ALLOWED_DOMAINS.contains(uri.host)) {
|
|
43
|
+
throw SecurityException("Domain not authorized")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 3. IP Check (preventing local/private IP access)
|
|
47
|
+
val address = InetAddress.getByName(uri.host)
|
|
48
|
+
if (address.isLoopbackAddress || address.isSiteLocalAddress || address.isLinkLocalAddress) {
|
|
49
|
+
throw SecurityException("Internal network access forbidden")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 4. Disable Redirects or manually validate them
|
|
53
|
+
val client = HttpClient.newBuilder()
|
|
54
|
+
.followRedirects(HttpClient.Redirect.NEVER)
|
|
55
|
+
.build()
|
|
56
|
+
|
|
57
|
+
// Execute request...
|
|
58
|
+
return ""
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**SSRF Prevention Guidelines:**
|
|
63
|
+
- **Whitelisting:** Only allow requests to a predefined list of trusted domains.
|
|
64
|
+
- **Protocol Restriction:** Only allow `http` and `https`. Block `file://`, `gopher://`, `dict://`, etc.
|
|
65
|
+
- **Internal Network Blocking:** Block access to `localhost`, `127.0.0.1`, and private IP ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`).
|
|
66
|
+
- **Cloud Metadata Blocking:** Explicitly block `169.254.169.254`.
|
|
67
|
+
- **DNS Resolution:** Perform validation on the resolved IP address, not just the hostname.
|
|
68
|
+
|
|
69
|
+
**Tools:** SonarQube (S5144), Semgrep, OWASP SSRF Prevention Cheat Sheet
|