@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,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Custom Error Classes
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables proper error categorization and handling
|
|
5
|
+
tags: error-handling, custom-errors, exceptions, patterns, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Custom Error Classes
|
|
9
|
+
|
|
10
|
+
Custom error classes enable proper error handling, categorization, and monitoring. They provide clear contracts for API consumers.
|
|
11
|
+
|
|
12
|
+
**Incorrect (generic errors):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
throw new Error("User not found");
|
|
16
|
+
throw new Error("Invalid input");
|
|
17
|
+
throw new Error("Database connection failed");
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (custom error hierarchy):**
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// Base application error
|
|
24
|
+
class AppError extends Error {
|
|
25
|
+
constructor(
|
|
26
|
+
message: string,
|
|
27
|
+
public readonly code: string,
|
|
28
|
+
public readonly statusCode: number = 500,
|
|
29
|
+
public readonly context?: Record<string, unknown>
|
|
30
|
+
) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = this.constructor.name;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Specific errors
|
|
37
|
+
class UserNotFoundError extends AppError {
|
|
38
|
+
constructor(userId: string) {
|
|
39
|
+
super(`User ${userId} not found`, 'USER_NOT_FOUND', 404, { userId });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class ValidationError extends AppError {
|
|
44
|
+
constructor(field: string, message: string) {
|
|
45
|
+
super(message, 'VALIDATION_ERROR', 400, { field });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Usage
|
|
50
|
+
throw new UserNotFoundError(userId);
|
|
51
|
+
throw new ValidationError('email', 'Invalid email format');
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Benefits:**
|
|
55
|
+
- Type-safe error handling
|
|
56
|
+
- Automatic HTTP status mapping
|
|
57
|
+
- Structured error context
|
|
58
|
+
- Consistent error format
|
|
59
|
+
|
|
60
|
+
**Tools:** Linter, Convention
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Separate Processing And Data Access
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables testable business logic
|
|
5
|
+
tags: separation, repository, service, architecture, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Separate Processing And Data Access
|
|
9
|
+
|
|
10
|
+
Mixing business logic with database queries creates tight coupling and makes testing require real databases.
|
|
11
|
+
|
|
12
|
+
**Incorrect (mixed concerns):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
class OrderService {
|
|
16
|
+
async calculateDiscount(userId: string) {
|
|
17
|
+
// Business logic mixed with data access
|
|
18
|
+
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
19
|
+
const orders = await db.query('SELECT * FROM orders WHERE user_id = $1', [userId]);
|
|
20
|
+
|
|
21
|
+
let discount = 0;
|
|
22
|
+
if (orders.length > 10) discount += 5;
|
|
23
|
+
if (user.isPremium) discount += 10;
|
|
24
|
+
|
|
25
|
+
return discount;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (separated layers):**
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// Repository - data access only
|
|
34
|
+
class UserRepository {
|
|
35
|
+
async findById(userId: string): Promise<User | null> {
|
|
36
|
+
return db.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class OrderRepository {
|
|
41
|
+
async findByUserId(userId: string): Promise<Order[]> {
|
|
42
|
+
return db.query('SELECT * FROM orders WHERE user_id = $1', [userId]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Service - business logic only
|
|
47
|
+
class DiscountService {
|
|
48
|
+
constructor(
|
|
49
|
+
private userRepo: UserRepository,
|
|
50
|
+
private orderRepo: OrderRepository
|
|
51
|
+
) {}
|
|
52
|
+
|
|
53
|
+
async calculateDiscount(userId: string): Promise<number> {
|
|
54
|
+
const user = await this.userRepo.findById(userId);
|
|
55
|
+
const orders = await this.orderRepo.findByUserId(userId);
|
|
56
|
+
|
|
57
|
+
return this.computeDiscount(user, orders);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private computeDiscount(user: User | null, orders: Order[]): number {
|
|
61
|
+
let discount = 0;
|
|
62
|
+
if (orders.length > 10) discount += 5;
|
|
63
|
+
if (user?.isPremium) discount += 10;
|
|
64
|
+
return discount;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Tools:** Architectural review, Code Review
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Log All Relevant Context On Errors
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables quick debugging and incident response
|
|
5
|
+
tags: error-handling, logging, context, debugging, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Log All Relevant Context On Errors
|
|
9
|
+
|
|
10
|
+
Context-rich logs enable quick debugging. Without proper context, finding root causes is like finding a needle in a haystack.
|
|
11
|
+
|
|
12
|
+
**Incorrect (minimal context):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
logger.error('Error occurred');
|
|
16
|
+
logger.error(error.message);
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Correct (comprehensive context):**
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
logger.error('Failed to process order', {
|
|
23
|
+
// What happened
|
|
24
|
+
error: error.message,
|
|
25
|
+
stack: error.stack,
|
|
26
|
+
errorCode: error.code,
|
|
27
|
+
|
|
28
|
+
// Context
|
|
29
|
+
orderId: order.id,
|
|
30
|
+
userId: user.id,
|
|
31
|
+
requestId: ctx.requestId,
|
|
32
|
+
|
|
33
|
+
// Input that caused the issue
|
|
34
|
+
orderItems: order.items.length,
|
|
35
|
+
totalAmount: order.total,
|
|
36
|
+
|
|
37
|
+
// Timing
|
|
38
|
+
timestamp: new Date().toISOString(),
|
|
39
|
+
processingTimeMs: Date.now() - startTime
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Essential context:**
|
|
44
|
+
- Error details (message, stack, code)
|
|
45
|
+
- Entity identifiers
|
|
46
|
+
- Request/correlation IDs
|
|
47
|
+
- Relevant input summary
|
|
48
|
+
- Timing information
|
|
49
|
+
|
|
50
|
+
**Tools:** Logging framework, Observability tools
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: No Hardcoded Secrets In Repo
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents credential exposure
|
|
5
|
+
tags: secrets, credentials, security, git, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## No Hardcoded Secrets In Repo
|
|
9
|
+
|
|
10
|
+
Secrets in code are exposed to everyone with repo access and can be scraped by attackers.
|
|
11
|
+
|
|
12
|
+
**Incorrect (secrets in code):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const API_KEY = 'sk-abc123xyz789';
|
|
16
|
+
const DB_PASSWORD = 'admin123';
|
|
17
|
+
|
|
18
|
+
fetch('https://api.stripe.com/v1/charges', {
|
|
19
|
+
headers: { 'Authorization': 'Bearer sk_live_xxx' }
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Correct (environment/secrets manager):**
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// From environment
|
|
27
|
+
const API_KEY = process.env.API_KEY;
|
|
28
|
+
|
|
29
|
+
// From secrets manager
|
|
30
|
+
const apiKey = await secretManager.getSecret('stripe-api-key');
|
|
31
|
+
|
|
32
|
+
// Validation at startup
|
|
33
|
+
if (!process.env.API_KEY) {
|
|
34
|
+
throw new Error('API_KEY environment variable is required');
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```gitignore
|
|
39
|
+
# .gitignore
|
|
40
|
+
.env
|
|
41
|
+
.env.local
|
|
42
|
+
*.pem
|
|
43
|
+
*.key
|
|
44
|
+
secrets/
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Tools:** GitLeaks, TruffleHog, pre-commit hooks
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Boolean Names Is/Has/Should
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: makes conditions instantly readable
|
|
5
|
+
tags: naming, booleans, readability, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Boolean Names Is/Has/Should
|
|
9
|
+
|
|
10
|
+
Boolean prefixes make conditions instantly readable.
|
|
11
|
+
|
|
12
|
+
**Incorrect (unclear boolean names):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const active = user.status === 'active';
|
|
16
|
+
const admin = checkAdminRole(user);
|
|
17
|
+
const items = cart.length > 0;
|
|
18
|
+
const update = needsRefresh();
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Correct (boolean prefixes):**
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
const isActive = user.status === 'active';
|
|
25
|
+
const isAdmin = checkAdminRole(user);
|
|
26
|
+
const hasItems = cart.length > 0;
|
|
27
|
+
const shouldUpdate = needsRefresh();
|
|
28
|
+
const canEdit = hasPermission(user, 'edit');
|
|
29
|
+
const willExpire = expirationDate < tomorrow;
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Boolean prefixes:**
|
|
33
|
+
|
|
34
|
+
| Prefix | Use For |
|
|
35
|
+
|--------|---------|
|
|
36
|
+
| `is` | State (isActive, isEnabled) |
|
|
37
|
+
| `has` | Ownership (hasPermission, hasError) |
|
|
38
|
+
| `should` | Decision (shouldUpdate, shouldRetry) |
|
|
39
|
+
| `can` | Capability (canEdit, canDelete) |
|
|
40
|
+
| `will` | Future (willExpire, willRetry) |
|
|
41
|
+
|
|
42
|
+
**Tools:** Linter, Code Review
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Separate Parsing From Controllers
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: keeps controllers thin and focused
|
|
5
|
+
tags: controller, parsing, transformation, patterns, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Separate Parsing From Controllers
|
|
9
|
+
|
|
10
|
+
Controllers should be thin - only handling HTTP concerns. Transformation logic should be extracted.
|
|
11
|
+
|
|
12
|
+
**Incorrect (transformation in controller):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
class UserController {
|
|
16
|
+
async getUser(req: Request, res: Response) {
|
|
17
|
+
const user = await this.userService.findById(req.params.id);
|
|
18
|
+
|
|
19
|
+
// Transformation logic in controller
|
|
20
|
+
const response = {
|
|
21
|
+
id: user.id,
|
|
22
|
+
fullName: `${user.firstName} ${user.lastName}`,
|
|
23
|
+
email: user.email.toLowerCase(),
|
|
24
|
+
createdAt: format(user.createdAt, 'yyyy-MM-dd'),
|
|
25
|
+
age: differenceInYears(new Date(), user.birthDate)
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
res.json(response);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Correct (separate mapper):**
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// Mapper/Transformer
|
|
37
|
+
class UserMapper {
|
|
38
|
+
static toResponse(user: User): UserResponse {
|
|
39
|
+
return {
|
|
40
|
+
id: user.id,
|
|
41
|
+
fullName: `${user.firstName} ${user.lastName}`,
|
|
42
|
+
email: user.email.toLowerCase(),
|
|
43
|
+
createdAt: format(user.createdAt, 'yyyy-MM-dd'),
|
|
44
|
+
age: differenceInYears(new Date(), user.birthDate)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Clean controller
|
|
50
|
+
class UserController {
|
|
51
|
+
async getUser(req: Request, res: Response) {
|
|
52
|
+
const user = await this.userService.findById(req.params.id);
|
|
53
|
+
res.json(UserMapper.toResponse(user));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Benefits:**
|
|
59
|
+
- Reusable transformation logic
|
|
60
|
+
- Testable mappers
|
|
61
|
+
- Clean controllers
|
|
62
|
+
- Consistent response format
|
|
63
|
+
|
|
64
|
+
**Tools:** Code review, Architecture rules
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Do Not Ignore Superclass Logic
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: ensures proper inheritance behavior
|
|
5
|
+
tags: inheritance, override, superclass, oop, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Do Not Ignore Superclass Logic
|
|
9
|
+
|
|
10
|
+
When overriding methods, ensure superclass behavior is preserved unless explicitly intended otherwise.
|
|
11
|
+
|
|
12
|
+
**Incorrect (ignoring superclass):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
class BaseService {
|
|
16
|
+
async save(entity: Entity) {
|
|
17
|
+
this.validate(entity);
|
|
18
|
+
await this.beforeSave(entity);
|
|
19
|
+
await this.repository.save(entity);
|
|
20
|
+
await this.afterSave(entity);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class UserService extends BaseService {
|
|
25
|
+
async save(user: User) {
|
|
26
|
+
// Completely ignores validation, hooks, etc.
|
|
27
|
+
await this.repository.save(user);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Correct (calling super):**
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
class UserService extends BaseService {
|
|
36
|
+
async save(user: User) {
|
|
37
|
+
// Add user-specific preprocessing
|
|
38
|
+
user.updatedAt = new Date();
|
|
39
|
+
|
|
40
|
+
// Call superclass implementation
|
|
41
|
+
await super.save(user);
|
|
42
|
+
|
|
43
|
+
// Add user-specific postprocessing
|
|
44
|
+
await this.updateSearchIndex(user);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**When to skip super:**
|
|
50
|
+
- Complete replacement is intentional
|
|
51
|
+
- Base implementation doesn't apply
|
|
52
|
+
- Document the reason clearly
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
class UserService extends BaseService {
|
|
56
|
+
/**
|
|
57
|
+
* Override: Users require special validation,
|
|
58
|
+
* base validation is not applicable.
|
|
59
|
+
*/
|
|
60
|
+
async save(user: User) {
|
|
61
|
+
await this.validateUser(user);
|
|
62
|
+
// Intentionally not calling super
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Tools:** Static Analysis, Code Review
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Do Not Hardcode Configuration
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: enables environment-specific deployments
|
|
5
|
+
tags: configuration, environment, deployment, quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Do Not Hardcode Configuration
|
|
9
|
+
|
|
10
|
+
Hardcoded config requires code changes to deploy to different environments.
|
|
11
|
+
|
|
12
|
+
**Incorrect (hardcoded config):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const API_URL = 'https://api.production.example.com';
|
|
16
|
+
const TIMEOUT = 5000;
|
|
17
|
+
const MAX_FILE_SIZE = 10485760;
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (externalized config):**
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// config.ts
|
|
24
|
+
const config = {
|
|
25
|
+
api: {
|
|
26
|
+
url: process.env.API_URL || 'http://localhost:3000',
|
|
27
|
+
timeout: parseInt(process.env.API_TIMEOUT || '5000'),
|
|
28
|
+
},
|
|
29
|
+
upload: {
|
|
30
|
+
maxFileSize: parseInt(process.env.MAX_FILE_SIZE || '10485760'),
|
|
31
|
+
},
|
|
32
|
+
features: {
|
|
33
|
+
newDashboard: process.env.FEATURE_NEW_DASHBOARD === 'true',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Validate at startup
|
|
38
|
+
const required = ['API_URL', 'DATABASE_URL'];
|
|
39
|
+
for (const envVar of required) {
|
|
40
|
+
if (!process.env[envVar]) {
|
|
41
|
+
throw new Error(`Missing: ${envVar}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default config;
|
|
46
|
+
|
|
47
|
+
// Usage
|
|
48
|
+
import config from './config';
|
|
49
|
+
fetch(`${config.api.url}/users`, { timeout: config.api.timeout });
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Tools:** dotenv, config libraries, Manual review
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: URL Redirects Must Be In Allow List
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: prevents open redirect vulnerabilities
|
|
5
|
+
tags: redirect, url, allow-list, validation, security
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## URL Redirects Must Be In Allow List
|
|
9
|
+
|
|
10
|
+
Open redirect vulnerabilities allow attackers to redirect users to malicious sites, often used in phishing attacks.
|
|
11
|
+
|
|
12
|
+
**Incorrect (unvalidated redirect URL):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
// Open redirect vulnerability
|
|
16
|
+
app.get('/redirect', (req, res) => {
|
|
17
|
+
const url = req.query.url;
|
|
18
|
+
res.redirect(url); // Attacker: ?url=https://evil.com
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Partial validation (can be bypassed)
|
|
22
|
+
app.get('/redirect', (req, res) => {
|
|
23
|
+
const url = req.query.url;
|
|
24
|
+
if (url.includes('example.com')) {
|
|
25
|
+
res.redirect(url); // Bypass: evil.com?example.com
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (allow list validation):**
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const ALLOWED_REDIRECT_HOSTS = [
|
|
34
|
+
'example.com',
|
|
35
|
+
'app.example.com',
|
|
36
|
+
'admin.example.com'
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
app.get('/redirect', (req, res) => {
|
|
40
|
+
const url = req.query.url;
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const parsed = new URL(url);
|
|
44
|
+
|
|
45
|
+
// Validate against allow list
|
|
46
|
+
if (!ALLOWED_REDIRECT_HOSTS.includes(parsed.hostname)) {
|
|
47
|
+
return res.status(400).json({ error: 'Invalid redirect URL' });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
res.redirect(url);
|
|
51
|
+
} catch {
|
|
52
|
+
// Invalid URL format
|
|
53
|
+
res.status(400).json({ error: 'Invalid URL format' });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Or use relative URLs only
|
|
58
|
+
app.get('/redirect', (req, res) => {
|
|
59
|
+
const path = req.query.path;
|
|
60
|
+
|
|
61
|
+
// Only allow relative paths starting with /
|
|
62
|
+
if (!path.startsWith('/') || path.startsWith('//')) {
|
|
63
|
+
return res.status(400).json({ error: 'Invalid path' });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
res.redirect(path);
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Protection strategies:**
|
|
71
|
+
1. Allow list of trusted domains
|
|
72
|
+
2. Use relative URLs only
|
|
73
|
+
3. Validate URL structure
|
|
74
|
+
4. Warning page before external redirects
|
|
75
|
+
|
|
76
|
+
**Tools:** SonarQube, Semgrep, Manual Review
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Do Not Log Credentials Or Tokens
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents credential exposure in logs
|
|
5
|
+
tags: logging, credentials, tokens, secrets, security
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Do Not Log Credentials Or Tokens
|
|
9
|
+
|
|
10
|
+
Logs are often stored unencrypted and accessed by many people. Credentials in logs can be harvested by attackers or accidentally exposed.
|
|
11
|
+
|
|
12
|
+
**Incorrect (logging sensitive data):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
// Logging passwords
|
|
16
|
+
logger.info('Login attempt', {
|
|
17
|
+
username: user.username,
|
|
18
|
+
password: user.password // NEVER!
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Logging tokens
|
|
22
|
+
logger.debug('Request headers', { headers: req.headers });
|
|
23
|
+
// Authorization header contains token!
|
|
24
|
+
|
|
25
|
+
// Logging full request
|
|
26
|
+
logger.info('Incoming request', { body: req.body });
|
|
27
|
+
// May contain password, credit card, etc.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct (sanitized logging):**
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// Mask or omit sensitive fields
|
|
34
|
+
logger.info('Login attempt', {
|
|
35
|
+
username: user.username,
|
|
36
|
+
// password omitted
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Sanitize headers
|
|
40
|
+
const safeHeaders = {
|
|
41
|
+
...req.headers,
|
|
42
|
+
authorization: req.headers.authorization ? '[REDACTED]' : undefined,
|
|
43
|
+
cookie: req.headers.cookie ? '[REDACTED]' : undefined
|
|
44
|
+
};
|
|
45
|
+
logger.debug('Request headers', { headers: safeHeaders });
|
|
46
|
+
|
|
47
|
+
// Use sanitizer for request body
|
|
48
|
+
function sanitizeForLog(obj: Record<string, any>): Record<string, any> {
|
|
49
|
+
const sensitiveFields = ['password', 'token', 'secret', 'credit_card', 'ssn'];
|
|
50
|
+
const sanitized = { ...obj };
|
|
51
|
+
|
|
52
|
+
for (const field of sensitiveFields) {
|
|
53
|
+
if (field in sanitized) {
|
|
54
|
+
sanitized[field] = '[REDACTED]';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return sanitized;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
logger.info('Incoming request', { body: sanitizeForLog(req.body) });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Never log:**
|
|
65
|
+
- Passwords (plaintext or hashed)
|
|
66
|
+
- API keys and tokens
|
|
67
|
+
- Credit card numbers
|
|
68
|
+
- Social Security Numbers
|
|
69
|
+
- Session identifiers
|
|
70
|
+
|
|
71
|
+
**Tools:** SonarQube, Semgrep, Log Audit
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Enforce Authorization At Trusted Service Layer
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: prevents client-side authorization bypass
|
|
5
|
+
tags: authorization, server-side, middleware, access-control, security
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Enforce Authorization At Trusted Service Layer
|
|
9
|
+
|
|
10
|
+
Client-side authorization can be bypassed. All permission checks must occur server-side where they cannot be manipulated.
|
|
11
|
+
|
|
12
|
+
**Incorrect (client-side or trusting client data):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
// Client-side authorization (can be bypassed)
|
|
16
|
+
if (user.role === 'admin') {
|
|
17
|
+
showAdminPanel(); // Just hide/show - not secure!
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Trusting client-sent role
|
|
21
|
+
app.delete('/users/:id', (req, res) => {
|
|
22
|
+
const userRole = req.body.role; // From client!
|
|
23
|
+
if (userRole === 'admin') {
|
|
24
|
+
deleteUser(req.params.id);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Hidden form field for authorization
|
|
29
|
+
<input type="hidden" name="isAdmin" value="true" />
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Correct (server-side authorization):**
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// Server-side authorization
|
|
36
|
+
const authMiddleware = (requiredRole: string) => {
|
|
37
|
+
return async (req: Request, res: Response, next: NextFunction) => {
|
|
38
|
+
const user = await getUserFromToken(req.headers.authorization);
|
|
39
|
+
if (!user) {
|
|
40
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const hasPermission = await checkPermission(user.id, requiredRole);
|
|
44
|
+
if (!hasPermission) {
|
|
45
|
+
return res.status(403).json({ error: 'Forbidden' });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
req.user = user;
|
|
49
|
+
next();
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
app.delete('/users/:id',
|
|
54
|
+
authMiddleware('admin'), // Server-side check
|
|
55
|
+
async (req, res) => {
|
|
56
|
+
await deleteUser(req.params.id);
|
|
57
|
+
res.json({ success: true });
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Never trust:**
|
|
63
|
+
- Client-side JavaScript checks
|
|
64
|
+
- Hidden form fields
|
|
65
|
+
- URL parameters for access control
|
|
66
|
+
- Unvalidated tokens from browser storage
|
|
67
|
+
|
|
68
|
+
**Tools:** Manual Review, Static Analysis, Penetration Testing
|