@sun-asterisk/sunlint 1.3.39 → 1.3.40
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/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/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,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Set Anti-cache Headers
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents sensitive data from being cached in browsers or intermediate proxies
|
|
5
|
+
tags: headers, cache, sensitive-data, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Set Anti-cache Headers
|
|
9
|
+
|
|
10
|
+
Pages containing sensitive user information (like bank statements, personal details, or private messages) should not be cached by browsers or intermediate proxy servers (CDNs). If cached, this information might be accessible to subsequent users of the same device or shared network.
|
|
11
|
+
|
|
12
|
+
**Incorrect (no cache control for sensitive data):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// Sensitive data returned without cache instructions
|
|
16
|
+
$balance = getBalance($userId);
|
|
17
|
+
echo json_encode(['balance' => $balance]);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (anti-cache headers):**
|
|
21
|
+
|
|
22
|
+
```php
|
|
23
|
+
// 1. Plain PHP
|
|
24
|
+
header('Cache-Control: no-store, no-cache, must-revalidate, private');
|
|
25
|
+
header('Pragma: no-cache');
|
|
26
|
+
header('Expires: 0');
|
|
27
|
+
|
|
28
|
+
echo json_encode($sensitiveData);
|
|
29
|
+
|
|
30
|
+
// 2. In Laravel Middleware
|
|
31
|
+
public function handle($request, Closure $next) {
|
|
32
|
+
$response = $next($request);
|
|
33
|
+
|
|
34
|
+
// Check if the response is for an authenticated user
|
|
35
|
+
if (auth()->check()) {
|
|
36
|
+
$response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
|
|
37
|
+
$response->headers->set('Pragma', 'no-cache');
|
|
38
|
+
$response->headers->set('Expires', '0');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return $response;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**When to use anti-cache:**
|
|
46
|
+
- User profile pages.
|
|
47
|
+
- Financial transactions and history.
|
|
48
|
+
- Admin dashboard pages.
|
|
49
|
+
- Any API endpoint returning non-public, authenticated data.
|
|
50
|
+
|
|
51
|
+
**Key Header Meanings:**
|
|
52
|
+
- `no-store`: Do not store any part of this response on disk (most important for security).
|
|
53
|
+
- `no-cache`: Must re-validate with the server before using a cached copy.
|
|
54
|
+
- `private`: Only intended for the single user, do not store in shared caches (proxies).
|
|
55
|
+
|
|
56
|
+
**Tools:** Header Audit Tools, Browser Developer Tools (Network Tab), SonarQube
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TLS Clients Must Validate Server Certificates
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: prevents Man-in-the-Middle (MITM) attacks by ensuring the server identity is authentic
|
|
5
|
+
tags: tls, certificates, validation, mitm, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## TLS Clients Must Validate Server Certificates
|
|
9
|
+
|
|
10
|
+
Disabling certificate validation (often done to "skip" errors in development) completely negates the security of TLS. It allows an attacker to intercept, read, and modify your traffic by simply presenting any certificate, including a self-signed one.
|
|
11
|
+
|
|
12
|
+
**Incorrect (disabled validation):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// 1. cURL - DANGEROUS
|
|
16
|
+
$ch = curl_init();
|
|
17
|
+
curl_setopt($ch, CURLOPT_URL, "https://api.example.com");
|
|
18
|
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // VULNERABLE
|
|
19
|
+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // VULNERABLE
|
|
20
|
+
|
|
21
|
+
// 2. Stream Context - DANGEROUS
|
|
22
|
+
$context = stream_context_create([
|
|
23
|
+
'ssl' => [
|
|
24
|
+
'verify_peer' => false, // VULNERABLE
|
|
25
|
+
'verify_peer_name' => false, // VULNERABLE
|
|
26
|
+
]
|
|
27
|
+
]);
|
|
28
|
+
file_get_contents("https://api.example.com", false, $context);
|
|
29
|
+
|
|
30
|
+
// 3. Guzzle - DANGEROUS
|
|
31
|
+
$client->get('https://api.example.com', ['verify' => false]);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Correct (enforced validation):**
|
|
35
|
+
|
|
36
|
+
```php
|
|
37
|
+
// 1. cURL - Enabled by default (Ensure CA bundle is present)
|
|
38
|
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
|
39
|
+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
|
40
|
+
|
|
41
|
+
// 2. Using an Internal CA for private services
|
|
42
|
+
curl_setopt($ch, CURLOPT_CAINFO, "/path/to/internal-ca.pem");
|
|
43
|
+
|
|
44
|
+
// 3. Guzzle (Recommended)
|
|
45
|
+
$client->get('https://api.example.com', [
|
|
46
|
+
'verify' => '/path/to/ca-bundle.crt' // Or true to use system default
|
|
47
|
+
]);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Common Pitfalls:**
|
|
51
|
+
- "Fixing" local development errors by setting `verify => false`. Instead, download the latest [cacert.pem](https://curl.se/docs/caextract.html) and update your `php.ini` (`curl.cainfo` and `openssl.cafile`).
|
|
52
|
+
- Using outdated OS images that have expired Root CAs.
|
|
53
|
+
|
|
54
|
+
**Tools:** `curl_error()`, `openssl_get_cert_locations()`, `SSLyze`, `OWASP ZAP`
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Invalidate Session On Logout
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: ensures logout actually terminates access
|
|
5
|
+
tags: session, logout, invalidation, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Invalidate Session On Logout
|
|
9
|
+
|
|
10
|
+
If sessions or tokens are not explicitly invalidated on the server during logout, an attacker who has stolen a session cookie or token can still access the application even after the user has "logged out".
|
|
11
|
+
|
|
12
|
+
**Incorrect (client-only or partial logout):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// Server-side: Just redirecting without destroying session
|
|
16
|
+
header("Location: /login.php");
|
|
17
|
+
exit;
|
|
18
|
+
|
|
19
|
+
// Frontend-only logout (session cookie still valid on server!)
|
|
20
|
+
// localStorage.removeItem('token');
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Correct (server-side invalidation):**
|
|
24
|
+
|
|
25
|
+
```php
|
|
26
|
+
// Standard PHP Session Invalidation
|
|
27
|
+
session_start();
|
|
28
|
+
|
|
29
|
+
// 1. Unset all session variables
|
|
30
|
+
$_SESSION = [];
|
|
31
|
+
|
|
32
|
+
// 2. Delete the session cookie
|
|
33
|
+
if (ini_get("session.use_cookies")) {
|
|
34
|
+
$params = session_get_cookie_params();
|
|
35
|
+
setcookie(session_name(), '', time() - 42000,
|
|
36
|
+
$params["path"], $params["domain"],
|
|
37
|
+
$params["secure"], $params["httponly"]
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 3. Destroy the session on server
|
|
42
|
+
session_destroy();
|
|
43
|
+
|
|
44
|
+
header("Location: /login.php");
|
|
45
|
+
exit;
|
|
46
|
+
|
|
47
|
+
// In Laravel (Recommended)
|
|
48
|
+
use Illuminate\Support\Facades\Auth;
|
|
49
|
+
use Illuminate\Support\Facades\Session;
|
|
50
|
+
|
|
51
|
+
Auth::logout();
|
|
52
|
+
Session::invalidate();
|
|
53
|
+
Session::regenerateToken(); // To prevent CSRF fixation
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Important Steps:**
|
|
57
|
+
1. Clear all session data (`$_SESSION = []`).
|
|
58
|
+
2. Expire the session cookie in the user's browser.
|
|
59
|
+
3. Call `session_destroy()` to remove server-side storage.
|
|
60
|
+
4. If using JWT, add the token to a blacklist until its natural expiration.
|
|
61
|
+
5. Redirect the user and set `Cache-Control: no-store` to prevent the browser from showing sensitive pages via the "Back" button.
|
|
62
|
+
|
|
63
|
+
**Tools:** OWASP ZAP, Manual Session Testing, Burp Suite, SonarQube
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Re-authenticate For Long-lived Sessions
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: ensures continuous identity verification for extended sessions
|
|
5
|
+
tags: session, authentication, timeout, reauthentication, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Re-authenticate For Long-lived Sessions
|
|
9
|
+
|
|
10
|
+
User sessions that remain active for days or weeks (e.g., using "Remember Me" features) are more susceptible to hijack if a device is left unattended or stolen. You should implement a system that requires users to perform a full re-authentication periodically or before performing sensitive actions.
|
|
11
|
+
|
|
12
|
+
**Incorrect (sessions never expire or never require re-auth):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// PHP session with no clear expiry logic
|
|
16
|
+
session_start();
|
|
17
|
+
// User stays logged in as long as the cookie exists
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct (enforcing session lifetime and re-auth):**
|
|
21
|
+
|
|
22
|
+
```php
|
|
23
|
+
// 1. Set reasonable idle session lifetime (php.ini)
|
|
24
|
+
// session.gc_maxlifetime = 1440 // 24 minutes default - increase to e.g. 14400 (4 hours)
|
|
25
|
+
|
|
26
|
+
// 2. track authentication time in session
|
|
27
|
+
session_start();
|
|
28
|
+
|
|
29
|
+
if (isset($_SESSION['user_id'])) {
|
|
30
|
+
$lastAuth = $_SESSION['last_auth_time'] ?? 0;
|
|
31
|
+
$maxAge = 4 * 60 * 60; // Require re-auth every 4 hours
|
|
32
|
+
|
|
33
|
+
if (time() - $lastAuth > $maxAge) {
|
|
34
|
+
$_SESSION['reauth_required'] = true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 3. Sensitive Action Middleware (Laravel example)
|
|
39
|
+
public function handle($request, Closure $next)
|
|
40
|
+
{
|
|
41
|
+
// Check if the user has authenticated within the last hour for sensitive actions
|
|
42
|
+
$lastAuthAt = $request->session()->get('auth.last_confirmed_at');
|
|
43
|
+
|
|
44
|
+
if (!$lastAuthAt || (time() - $lastAuthAt > 3600)) {
|
|
45
|
+
return redirect()->route('password.confirm');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return $next($request);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Implementation Strategy:**
|
|
53
|
+
- **Idle Timeout**: Automatically destroy the session after a period of user inactivity (e.g., 2 hours).
|
|
54
|
+
- **Absolute Lifetime**: Force a full logout or re-auth after a total duration (e.g., 24 hours), regardless of activity.
|
|
55
|
+
- **Sensitive Operations**: Require password entry before changing emails, passwords, or processing payments (see rule **S044**).
|
|
56
|
+
|
|
57
|
+
**Tools:** Laravel `password.confirm`, `session.gc_maxlifetime`, Custom PHP Middleware
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Re-authenticate Before Critical Changes
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents unauthorized critical operations in case of session hijacking
|
|
5
|
+
tags: authentication, critical, reauthentication, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Re-authenticate Before Critical Changes
|
|
9
|
+
|
|
10
|
+
For critical operations such as changing passwords, updating contact emails, or deleting an account, a valid session alone is not enough. You must require the user to provide their current password or a 2FA code to confirm the action.
|
|
11
|
+
|
|
12
|
+
**Incorrect (no confirmation for critical actions):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// VULNERABLE: Direct deletion without confirming identity
|
|
16
|
+
public function deleteAccount(Request $request) {
|
|
17
|
+
$user = Auth::user();
|
|
18
|
+
$user->delete();
|
|
19
|
+
return response()->json(['status' => 'success']);
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Correct (requiring password confirmation):**
|
|
24
|
+
|
|
25
|
+
```php
|
|
26
|
+
public function deleteAccount(Request $request) {
|
|
27
|
+
$request->validate([
|
|
28
|
+
'current_password' => 'required',
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
$user = Auth::user();
|
|
32
|
+
|
|
33
|
+
// 1. Manually verify the current password
|
|
34
|
+
if (!Hash::check($request->current_password, $user->password)) {
|
|
35
|
+
throw ValidationException::withMessages([
|
|
36
|
+
'current_password' => ['The provided password does not match our records.'],
|
|
37
|
+
]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 2. Perform the critical action
|
|
41
|
+
$user->delete();
|
|
42
|
+
|
|
43
|
+
// 3. Log security event
|
|
44
|
+
Log::warning("User account deleted: {$user->email}");
|
|
45
|
+
|
|
46
|
+
return response()->json(['status' => 'success']);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 2FA Verification example
|
|
50
|
+
public function updateEmail(Request $request) {
|
|
51
|
+
$request->validate(['email' => 'required|email', 'otp' => 'required']);
|
|
52
|
+
|
|
53
|
+
if (!TwoFactor::verify($request->otp)) {
|
|
54
|
+
return back()->withError('Invalid 2FA code.');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ...
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Critical actions that MUST require re-authentication:**
|
|
62
|
+
- Changing the account password.
|
|
63
|
+
- Updating the primary email address.
|
|
64
|
+
- Deleting the account.
|
|
65
|
+
- Disabling 2FA or changing security settings.
|
|
66
|
+
- Managing high-value payment methods or withdrawal addresses.
|
|
67
|
+
|
|
68
|
+
**Why is this necessary?**
|
|
69
|
+
If a user leaves their computer unlocked or their session cookie is stolen, the attacker can hijack the session. Requiring the password for critical changes creates a vital final barrier that prevents the attacker from locking out the real user or causing permanent data loss.
|
|
70
|
+
|
|
71
|
+
**Tools:** Laravel `password.confirm`, `Hash::check`, manual code review
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Implement Brute-force Protection
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: prevents password guessing and credential stuffing attacks
|
|
5
|
+
tags: brute-force, rate-limiting, authentication, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Implement Brute-force Protection
|
|
9
|
+
|
|
10
|
+
Without brute-force protection, attackers can use automated scripts to try millions of password combinations against your login endpoints. You must implement rate limiting or progressive delays for sensitive actions like authentication, password resets, and MFA verification.
|
|
11
|
+
|
|
12
|
+
**Incorrect (no protection):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// Standard login without limits
|
|
16
|
+
public function login(Request $request) {
|
|
17
|
+
if (Auth::attempt($request->only('email', 'password'))) {
|
|
18
|
+
return redirect()->intended('dashboard');
|
|
19
|
+
}
|
|
20
|
+
return back()->withErrors(['email' => 'Invalid credentials']);
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Correct (rate limiting and locking):**
|
|
25
|
+
|
|
26
|
+
```php
|
|
27
|
+
// 1. Using Laravel's built-in Rate Limiter (Recommended)
|
|
28
|
+
use Illuminate\Support\Facades\RateLimiter;
|
|
29
|
+
|
|
30
|
+
public function login(Request $request) {
|
|
31
|
+
$throttleKey = Str::lower($request->input('email')) . '|' . $request->ip();
|
|
32
|
+
|
|
33
|
+
if (RateLimiter::tooManyAttempts($throttleKey, 5)) {
|
|
34
|
+
$seconds = RateLimiter::availableIn($throttleKey);
|
|
35
|
+
return back()->withErrors([
|
|
36
|
+
'email' => "Too many attempts. Retry in {$seconds} seconds."
|
|
37
|
+
]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (Auth::attempt($request->only('email', 'password'))) {
|
|
41
|
+
RateLimiter::clear($throttleKey);
|
|
42
|
+
return redirect()->intended('dashboard');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
RateLimiter::hit($throttleKey, 60); // 1 minute window
|
|
46
|
+
return back()->withErrors(['email' => 'Invalid credentials']);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 2. Progressive Delay (Plain PHP)
|
|
50
|
+
if ($loginFailed) {
|
|
51
|
+
$attempts = $_SESSION['login_attempts'] ?? 0;
|
|
52
|
+
$_SESSION['login_attempts'] = $attempts + 1;
|
|
53
|
+
|
|
54
|
+
// Slow down attackers
|
|
55
|
+
if ($attempts > 3) {
|
|
56
|
+
sleep(pow(2, $attempts - 3)); // Exponential backoff
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Best Practices:**
|
|
62
|
+
1. **IP + Account Limiting**: Track attempts by both IP address and the targeted account (email/username).
|
|
63
|
+
2. **CAPTCHA**: Trigger a CAPTCHA (e.g., reCAPTCHA v3) after a certain number of failed attempts.
|
|
64
|
+
3. **Lockout Policy**: Temporarily disable an account after X failed attempts (e.g., lock for 30 minutes after 10 failures).
|
|
65
|
+
4. **Monitoring**: Log multiple failures from a single IP to trigger WAF (Web Application Firewall) blocks.
|
|
66
|
+
|
|
67
|
+
**Tools:** Laravel RateLimiter, Symfony Rate Limiter component, AWS WAF, Cloudflare Rate Limiting
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Protect OAuth Code Flow Vs CSRF
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents attackers from tricking users into linking malicious accounts via OAuth CSRF
|
|
5
|
+
tags: oauth, csrf, state, authorization, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Protect OAuth Code Flow Vs CSRF
|
|
9
|
+
|
|
10
|
+
During the OAuth 2.0 authorization code flow, an attacker could initiate an auth request and trick a logged-in user into clicking the callback URL. Without a `state` parameter, your application might link the attacker's account (e.g., GitHub/Google) to the victim's local session.
|
|
11
|
+
|
|
12
|
+
**Incorrect (no state parameter):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// Initiating OAuth without state
|
|
16
|
+
public function redirectToProvider() {
|
|
17
|
+
$url = "https://provider.com/oauth/authorize?" . http_build_query([
|
|
18
|
+
'client_id' => 'CLIENT_ID',
|
|
19
|
+
'redirect_uri' => 'CALLBACK_URL',
|
|
20
|
+
'response_type' => 'code',
|
|
21
|
+
'scope' => 'user:email',
|
|
22
|
+
]);
|
|
23
|
+
return redirect($url);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Callback without state validation
|
|
27
|
+
public function handleCallback(Request $request) {
|
|
28
|
+
$code = $request->input('code');
|
|
29
|
+
// Dangerous: missing state validation!
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Correct (state parameter validation):**
|
|
34
|
+
|
|
35
|
+
```php
|
|
36
|
+
// 1. Manually initiating with state
|
|
37
|
+
public function redirectToProvider() {
|
|
38
|
+
$state = bin2hex(random_bytes(16));
|
|
39
|
+
session(['oauth_state' => $state]); // Store in session
|
|
40
|
+
|
|
41
|
+
$url = "https://provider.com/oauth/authorize?" . http_build_query([
|
|
42
|
+
'client_id' => 'CLIENT_ID',
|
|
43
|
+
'redirect_uri' => 'CALLBACK_URL',
|
|
44
|
+
'response_type' => 'code',
|
|
45
|
+
'state' => $state,
|
|
46
|
+
]);
|
|
47
|
+
return redirect($url);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 2. Validating in callback
|
|
51
|
+
public function handleCallback(Request $request) {
|
|
52
|
+
$state = $request->input('state');
|
|
53
|
+
$storedState = session()->pull('oauth_state');
|
|
54
|
+
|
|
55
|
+
if (empty($state) || $state !== $storedState) {
|
|
56
|
+
abort(403, 'Invalid OAuth state.');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Proceed to exchange code for token
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 3. Using Laravel Socialite (Recommended)
|
|
64
|
+
* Socialite handles the state parameter automatically.
|
|
65
|
+
*/
|
|
66
|
+
return Socialite::driver('github')->redirect();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Why it matters?**
|
|
70
|
+
The `state` parameter acts as a secret token that links the initial request from your site to the final callback from the provider. If the `state` doesn't match, it means the auth flow was not initiated by the user on your application, signaling a potential CSRF attack.
|
|
71
|
+
|
|
72
|
+
**Tools:** Laravel Socialite, League OAuth2 Client, PHP `random_bytes()`, Manual Security Review
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Validate OAuth Redirect URIs Exactly
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: prevents authorization code theft via malicious redirection
|
|
5
|
+
tags: oauth, redirect, uri, validation, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Validate OAuth Redirect URIs Exactly
|
|
9
|
+
|
|
10
|
+
If you are building an OAuth 2.0 Identity Provider (IdP) or an internal auth service, you must validate the `redirect_uri` parameter against an exact match of pre-registered URIs. Loose validation (like substring or prefix matching) can be bypassed to leak authorization codes to an attacker-controlled site.
|
|
11
|
+
|
|
12
|
+
**Incorrect (loose or partial validation):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// VULNERABLE: Substring matching
|
|
16
|
+
if (strpos($redirectUri, "example.com") !== false) {
|
|
17
|
+
// Allows attacker.com/?leak=example.com
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// VULNERABLE: Prefix matching without trailing slash
|
|
21
|
+
if (strpos($redirectUri, "https://app.example.com") === 0) {
|
|
22
|
+
// Allows https://app.example.com.attacker.com
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Correct (exact matching against whitelist):**
|
|
27
|
+
|
|
28
|
+
```php
|
|
29
|
+
$registeredUris = [
|
|
30
|
+
'https://app.example.com/callback',
|
|
31
|
+
'https://staging.example.com/callback'
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
$requestedUri = $_GET['redirect_uri'];
|
|
35
|
+
|
|
36
|
+
// 1. Exact string comparison (Recommended)
|
|
37
|
+
if (!in_array($requestedUri, $registeredUris, true)) {
|
|
38
|
+
die("Error: Invalid redirect_uri provided.");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. Using Laravel Passport/Socialite
|
|
42
|
+
// These libraries handle exact validation if configured correctly in the client table.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Security Best Practices:**
|
|
46
|
+
- **No Wildcards**: Do not allow `*.example.com`. Modern OAuth standards discourage any form of pattern matching.
|
|
47
|
+
- **Pre-Registration**: Every client must register their exact callback URLs during the app registration phase.
|
|
48
|
+
- **HTTPS Only**: Only allow `https://` schemes for production redirect URIs.
|
|
49
|
+
- **Exact Path**: The entire path must match, not just the domain.
|
|
50
|
+
|
|
51
|
+
**Why it matters?**
|
|
52
|
+
If an attacker can redirect the OAuth flow to their own domain, they will receive the `?code=` parameter. They can then use this code to impersonate the user or link the user's account to their own, leading to a full account takeover.
|
|
53
|
+
|
|
54
|
+
**Tools:** Laravel Passport, OpenID Connect specifications, Manual Security Audit
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Authentication Codes Must Expire Quickly
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: reduces the opportunity for an attacker to use intercepted codes
|
|
5
|
+
tags: authentication, codes, expiry, otp, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Authentication Codes Must Expire Quickly
|
|
9
|
+
|
|
10
|
+
Any temporary authentication identifiers—such as MFA codes, password reset tokens, or email verification links—must have a strict and limited lifespan. The longer a code is valid, the more time an attacker has to guess or intercept it.
|
|
11
|
+
|
|
12
|
+
**Incorrect (codes last too long or never expire):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// Verification code without expiry
|
|
16
|
+
$user->verification_code = '123456';
|
|
17
|
+
$user->save(); // Stays valid forever!
|
|
18
|
+
|
|
19
|
+
// Reset link valid for 7 days
|
|
20
|
+
$resetUrl = generateResetLink($user, 7 * 24 * 60 * 60);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Correct (short lifespan and single-use logic):**
|
|
24
|
+
|
|
25
|
+
```php
|
|
26
|
+
// 1. Using Redis for TTL (Recommended for OTPs)
|
|
27
|
+
$otp = (string)random_int(100000, 999999);
|
|
28
|
+
$cacheKey = "auth_otp:{$user->id}";
|
|
29
|
+
|
|
30
|
+
// Store with 5-minute expiry (300 seconds)
|
|
31
|
+
Redis::setex($cacheKey, 300, json_encode([
|
|
32
|
+
'code' => $otp,
|
|
33
|
+
'attempts' => 0
|
|
34
|
+
]));
|
|
35
|
+
|
|
36
|
+
// 2. Verified and Single Use
|
|
37
|
+
public function verify(string $input) {
|
|
38
|
+
$data = json_decode(Redis::get($cacheKey), true);
|
|
39
|
+
|
|
40
|
+
if (!$data) return false;
|
|
41
|
+
|
|
42
|
+
// Check attempts to prevent brute-force
|
|
43
|
+
if ($data['attempts'] > 3) {
|
|
44
|
+
Redis::del($cacheKey);
|
|
45
|
+
throw new Exception("Too many attempts.");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if ($input === $data['code']) {
|
|
49
|
+
Redis::del($cacheKey); // DELETE IMMEDIATELY AFTER USE
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Increment attempts
|
|
54
|
+
$data['attempts']++;
|
|
55
|
+
Redis::setex($cacheKey, 300, json_encode($data));
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Recommended Expiry Times:**
|
|
61
|
+
- **2FA/OTP (Short code)**: 5 - 10 minutes.
|
|
62
|
+
- **Magic Links**: 15 minutes.
|
|
63
|
+
- **Password Reset (Long token)**: 60 minutes.
|
|
64
|
+
- **Email Verification**: 24 hours.
|
|
65
|
+
|
|
66
|
+
**Best Practices:**
|
|
67
|
+
- **Single Use**: Invalidating the code immediately after a successful *or* too many failed attempts is mandatory.
|
|
68
|
+
- **Secure Generation**: Use `random_int()` or `random_bytes()` for generation (see rule **S010**).
|
|
69
|
+
- **Rate Limiting**: Limit how many times a code can be requested per user/IP.
|
|
70
|
+
|
|
71
|
+
**Tools:** Laravel `signed` routes, Redis `SETEX`, PHPUnit (for expiry tests)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Reference Tokens 128-bit Entropy CSPRNG
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: prevents token prediction and brute-force attacks
|
|
5
|
+
tags: tokens, entropy, csprng, session, security, php
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Reference Tokens 128-bit Entropy CSPRNG
|
|
9
|
+
|
|
10
|
+
Predictable or low-entropy tokens (API keys, session IDs, reset tokens) can be guessed or brute-forced. Using a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) with at least 128 bits of entropy makes such attacks computationally infeasible.
|
|
11
|
+
|
|
12
|
+
**Incorrect (predictable or low-entropy tokens):**
|
|
13
|
+
|
|
14
|
+
```php
|
|
15
|
+
// 1. Predictable - using non-CS PRNG
|
|
16
|
+
$token = uniqid(); // Based on microtime, highly predictable
|
|
17
|
+
|
|
18
|
+
// 2. Predictable - Sequential or timestamp based
|
|
19
|
+
$token = "session_" . time() . "_" . $userId;
|
|
20
|
+
|
|
21
|
+
// 3. Low Entropy
|
|
22
|
+
$token = bin2hex(random_bytes(4)); // Only 32 bits of entropy
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (high-entropy CSPRNG tokens):**
|
|
26
|
+
|
|
27
|
+
```php
|
|
28
|
+
// 1. Minimum 128 bits (16 bytes = 128 bits)
|
|
29
|
+
$sessionToken = bin2hex(random_bytes(16));
|
|
30
|
+
|
|
31
|
+
// 2. Recommended 256 bits (32 bytes)
|
|
32
|
+
$apiKey = 'sk_' . bin2hex(random_bytes(32));
|
|
33
|
+
|
|
34
|
+
// 3. Using Base64 (URL safe) for better efficiency
|
|
35
|
+
$token = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(random_bytes(32)));
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 4. Using Laravel Helpers (Powered by random_bytes)
|
|
39
|
+
*/
|
|
40
|
+
use Illuminate\Support\Str;
|
|
41
|
+
|
|
42
|
+
$token = Str::random(40); // Generates a random alphanumeric string
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Entropy Guide:**
|
|
46
|
+
|
|
47
|
+
| Bytes | Bits | Use Case |
|
|
48
|
+
|-------|------|----------|
|
|
49
|
+
| 8 | 64 | **Weak** (Guessable in small datasets) |
|
|
50
|
+
| 16 | 128 | **Minimum** for session IDs |
|
|
51
|
+
| 32 | 256 | **Recommended** for API keys & Refresh Tokens |
|
|
52
|
+
|
|
53
|
+
**Key Rules:**
|
|
54
|
+
- **Always use `random_bytes()`** or `random_int()` in PHP.
|
|
55
|
+
- **Never use `rand()`**, `mt_rand()`, or `uniqid()` for security tokens.
|
|
56
|
+
- **Encode securely**: Use `bin2hex` or URL-safe Base64 for token representation.
|
|
57
|
+
|
|
58
|
+
**Tools:** PHP Internal `random_bytes()`, SonarQube, Manual Security Review
|