From ec8239a82ab8ddd993cfccbb5334d33ec312bf85 Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Tue, 28 Nov 2023 11:42:35 -0800 Subject: [PATCH 01/12] Rename CI to Software Delivery --- config/_default/menus/menus.en.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/_default/menus/menus.en.yaml b/config/_default/menus/menus.en.yaml index a5f13e7469c7d..de7757b4367b0 100644 --- a/config/_default/menus/menus.en.yaml +++ b/config/_default/menus/menus.en.yaml @@ -14,8 +14,8 @@ main: - name: Application Performance identifier: apm_heading weight: 5000000 - - name: Continuous Integration - identifier: ci_visibility_heading + - name: Software Delivery + identifier: software_delivery_heading weight: 6000000 - name: Log Management identifier: log_management_heading @@ -2373,7 +2373,7 @@ main: url: continuous_integration/ pre: ci identifier: ci - parent: ci_visibility_heading + parent: software_delivery_heading weight: 150000 - name: Test Visibility url: continuous_integration/tests/ @@ -2609,7 +2609,7 @@ main: url: continuous_delivery/ pre: ci identifier: cd - parent: ci_visibility_heading + parent: software_delivery_heading weight: 160000 - name: Pipeline Visibility url: continuous_delivery/pipelines @@ -2645,7 +2645,7 @@ main: url: continuous_delivery/ pre: ci identifier: cd - parent: ci_visibility_heading + parent: software_delivery_heading weight: 160000 - name: Pipeline Visibility url: continuous_delivery/pipelines From 747d904257635617dbcd44840596515006dbdbd2 Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 30 Nov 2023 10:18:17 -0800 Subject: [PATCH 02/12] Reorder ITR --- config/_default/menus/menus.en.yaml | 201 ++++++++++++---------------- data/partials/home.yaml | 2 +- 2 files changed, 85 insertions(+), 118 deletions(-) diff --git a/config/_default/menus/menus.en.yaml b/config/_default/menus/menus.en.yaml index de7757b4367b0..c457db6759a8e 100644 --- a/config/_default/menus/menus.en.yaml +++ b/config/_default/menus/menus.en.yaml @@ -2445,166 +2445,136 @@ main: parent: ci_tests identifier: ci_tests_swift_tests weight: 107 + - name: Intelligent Test Runner + url: continuous_integration/intelligent_test_runner/ + parent: ci + identifier: ci_intelligent_test_runner + weight: 2 + - name: Setup + url: continuous_integration/intelligent_test_runner/setup/ + parent: ci_intelligent_test_runner + identifier: ci_intelligent_test_runner_setup + weight: 201 + - name: .NET + url: continuous_integration/intelligent_test_runner/setup/dotnet/ + parent: ci_intelligent_test_runner_setup + identifier: ci_itr_dotnet + weight: 201 + - name: Java + url: continuous_integration/intelligent_test_runner/setup/java/ + parent: ci_intelligent_test_runner_setup + identifier: ci_itr_java + weight: 202 + - name: JavaScript and TypeScript + url: continuous_integration/intelligent_test_runner/setup/javascript/ + parent: ci_intelligent_test_runner_setup + identifier: ci_itr_javascript + weight: 203 + - name: Python + url: continuous_integration/intelligent_test_runner/setup/python/ + parent: ci_intelligent_test_runner_setup + identifier: ci_itr_python + weight: 204 + - name: Swift + url: continuous_integration/intelligent_test_runner/setup/swift/ + parent: ci_intelligent_test_runner_setup + identifier: ci_itr_swift + weight: 205 - name: Pipeline Visibility url: continuous_integration/pipelines/ parent: ci identifier: pipeline_visibility - weight: 2 + weight: 3 - name: AWS CodePipeline url: continuous_integration/pipelines/awscodepipeline/ parent: pipeline_visibility identifier: ci_awscodepipeline - weight: 201 + weight: 301 - name: Azure url: continuous_integration/pipelines/azure/ parent: pipeline_visibility identifier: ci_azure - weight: 202 + weight: 302 - name: Buildkite url: continuous_integration/pipelines/buildkite/ parent: pipeline_visibility identifier: ci_buildkite - weight: 203 + weight: 303 - name: CircleCI url: continuous_integration/pipelines/circleci/ parent: pipeline_visibility identifier: ci_circleci - weight: 204 + weight: 304 - name: Codefresh url: continuous_integration/pipelines/codefresh/ parent: pipeline_visibility identifier: ci_codefresh - weight: 205 + weight: 305 - name: GitHub Actions url: continuous_integration/pipelines/github/ parent: pipeline_visibility identifier: ci_github - weight: 206 + weight: 306 - name: GitLab url: continuous_integration/pipelines/gitlab/ parent: pipeline_visibility identifier: ci_gitlab - weight: 207 + weight: 307 - name: Jenkins url: continuous_integration/pipelines/jenkins/ parent: pipeline_visibility identifier: ci_jenkins - weight: 208 + weight: 308 - name: TeamCity url: continuous_integration/pipelines/teamcity/ parent: pipeline_visibility identifier: ci_teamcity - weight: 209 + weight: 309 - name: Custom Commands url: continuous_integration/pipelines/custom_commands/ parent: pipeline_visibility identifier: ci_custom_commands - weight: 210 + weight: 310 - name: Custom Tags and Metrics url: continuous_integration/pipelines/custom_tags_and_metrics/ parent: pipeline_visibility identifier: ci_custom_tags_and_metrics - weight: 211 + weight: 311 - name: Search and Manage url: continuous_integration/search/ parent: ci identifier: ci_search - weight: 3 + weight: 4 - name: Explorer url: continuous_integration/explorer/ parent: ci identifier: ci_explorer - weight: 4 + weight: 5 - name: Search Syntax url: continuous_integration/explorer/search_syntax/ parent: ci_explorer identifier: ci_explorer_search_syntax - weight: 401 + weight: 501 - name: Facets url: continuous_integration/explorer/facets/ parent: ci_explorer identifier: ci_explorer_facets - weight: 402 + weight: 502 - name: Saved Views url: continuous_integration/explorer/saved_views/ parent: ci_explorer identifier: ci_explorer_saved_views - weight: 402 - - name: DORA Metrics - url: continuous_integration/dora_metrics/ - parent: ci - identifier: ci_explorer_dora_metrics - weight: 5 - - name: Intelligent Test Runner - url: continuous_integration/intelligent_test_runner/ - parent: ci - identifier: ci_intelligent_test_runner - weight: 6 - - name: Setup - url: continuous_integration/intelligent_test_runner/setup/ - parent: ci_intelligent_test_runner - identifier: ci_intelligent_test_runner_setup - weight: 601 - - name: .NET - url: continuous_integration/intelligent_test_runner/setup/dotnet/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_dotnet - weight: 601 - - name: Java - url: continuous_integration/intelligent_test_runner/setup/java/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_java - weight: 602 - - name: JavaScript and TypeScript - url: continuous_integration/intelligent_test_runner/setup/javascript/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_javascript - weight: 603 - - name: Python - url: continuous_integration/intelligent_test_runner/setup/python/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_python - weight: 604 - - name: Swift - url: continuous_integration/intelligent_test_runner/setup/swift/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_swift - weight: 605 - - name: Static Analysis - url: continuous_integration/static_analysis/ - parent: ci - identifier: ci_static_analysis - weight: 7 - - name: Rules - url: continuous_integration/static_analysis/rules - parent: ci_static_analysis - identifier: ci_static_analysis_rules - weight: 701 - - name: CircleCI Orbs - url: continuous_integration/static_analysis/circleci_orbs - parent: ci_static_analysis - identifier: ci_static_analysis_circleci_orbs - weight: 702 - - name: GitHub Actions - url: continuous_integration/static_analysis/github_actions - parent: ci_static_analysis - identifier: ci_static_analysis_github_actions - weight: 703 - - name: Quality Gates - url: continuous_integration/quality_gates/ - parent: ci - identifier: ci_quality_gates - weight: 8 + weight: 502 - name: Guides url: continuous_integration/guides/ parent: ci identifier: ci_guides - weight: 9 + weight: 6 - name: Troubleshooting url: continuous_integration/troubleshooting/ parent: ci identifier: ci_troubleshooting - weight: 10 + weight: 7 - name: CD Visibility url: continuous_delivery/ pre: ci @@ -2641,42 +2611,39 @@ main: identifier: cd_explorer_facets parent: cd_explorer weight: 302 - - name: CD Visibility - url: continuous_delivery/ + - name: DORA Metrics + url: continuous_integration/dora_metrics/ pre: ci - identifier: cd parent: software_delivery_heading - weight: 160000 - - name: Pipeline Visibility - url: continuous_delivery/pipelines - identifier: cd_pipelines - parent: cd - weight: 1 - - name: ArgoCD - url: continuous_delivery/pipelines/argocd - identifier: cd_pipelines_argocd - parent: cd_pipelines + identifier: ci_explorer_dora_metrics + weight: 170000 + - name: Static Analysis + url: continuous_integration/static_analysis/ + pre: ci + parent: software_delivery_heading + identifier: ci_static_analysis + weight: 180000 + - name: Rules + url: continuous_integration/static_analysis/rules + parent: ci_static_analysis + identifier: ci_static_analysis_rules weight: 101 - - name: Search and Manage - url: continuous_delivery/search - identifier: cd_search - parent: cd - weight: 2 - - name: Explorer - url: continuous_delivery/explorer - identifier: cd_explorer - parent: cd - weight: 3 - - name: Search Syntax - url: continuous_delivery/explorer/search_syntax - identifier: cd_explorer_search_syntax - parent: cd_explorer - weight: 301 - - name: Facets - url: continuous_delivery/explorer/facets - identifier: cd_explorer_facets - parent: cd_explorer - weight: 302 + - name: CircleCI Orbs + url: continuous_integration/static_analysis/circleci_orbs + parent: ci_static_analysis + identifier: ci_static_analysis_circleci_orbs + weight: 102 + - name: GitHub Actions + url: continuous_integration/static_analysis/github_actions + parent: ci_static_analysis + identifier: ci_static_analysis_github_actions + weight: 103 + - name: Quality Gates + url: continuous_integration/quality_gates/ + pre: ci + parent: software_delivery_heading + identifier: ci_quality_gates + weight: 190000 - name: Database Monitoring url: database_monitoring/ pre: database-2 diff --git a/data/partials/home.yaml b/data/partials/home.yaml index 194bc37e6a168..703c9cd677e68 100644 --- a/data/partials/home.yaml +++ b/data/partials/home.yaml @@ -111,7 +111,7 @@ nav_sections: - title: CD Visibility link: continuous_integration/ icon: ci - desc: See software delivery metrics, results, and insights for your CD provider + desc: See deployment metrics, results, and insights for your environments - title: Cloud Cost Management link: cloud_cost_management/ icon: cloud-cost-management From 685b518477c71c816803bd76010f16dc852315ea Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 30 Nov 2023 10:27:35 -0800 Subject: [PATCH 03/12] Spacing Nit --- config/_default/menus/menus.en.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/_default/menus/menus.en.yaml b/config/_default/menus/menus.en.yaml index f8319cae4f0a9..4d3311bec3fea 100644 --- a/config/_default/menus/menus.en.yaml +++ b/config/_default/menus/menus.en.yaml @@ -2611,7 +2611,7 @@ main: identifier: cd_explorer_facets parent: cd_explorer weight: 302 - - name: Saved Views + - name: Saved Views url: continuous_delivery/explorer/saved_views identifier: cd_explorer_saved_views parent: cd_explorer From 6739086a5df93eaca1cb6982acb334b6e0756b4a Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:15:38 -0800 Subject: [PATCH 04/12] Update Slugs + Add Aliases --- config/_default/menus/menus.en.yaml | 30 +- .../dora_metrics/_index.md | 2 + .../quality_gates/_index.md | 2 + .../static_analysis/_index.md | 2 + content/en/static_analysis/circleci_orbs.md | 102 ++ content/en/static_analysis/github_actions.md | 72 ++ .../static_analysis/rules/_index.md | 2 + .../docker-best-practices/absolute-workdir.md | 34 + .../alias-must-be-unique.md | 40 + .../docker-best-practices/apt-get-yes.md | 32 + .../docker-best-practices/apt-pin-version.md | 39 + .../docker-best-practices/avoid-chmod-777.md | 35 + .../avoid-commands-not-relevant.md | 35 + .../rules/docker-best-practices/avoid-http.md | 35 + .../rules/docker-best-practices/dnf-use-y.md | 32 + .../expose-admin-ports.md | 34 + .../expose-valid-port.md | 32 + .../image-avoid-digest.md | 34 + .../maintainer-deprecated.md | 32 + .../docker-best-practices/multiple-cmd.md | 35 + .../multiple-entrypoint.md | 35 + .../multiple-healthcheck.md | 33 + .../docker-best-practices/no-root-user.md | 38 + .../docker-best-practices/pip-no-cache.md | 35 + .../docker-best-practices/pip-pin-versions.md | 34 + .../tag-image-version.md | 34 + .../rules/docker-best-practices/yum-use-y.md | 32 + .../docker-best-practices/zypper-use-y.md | 34 + .../for-direction.md | 83 ++ .../javascript-best-practices/new-parens.md | 85 ++ .../javascript-best-practices/no-alert.md | 80 ++ .../no-async-promise-executor.md | 35 + .../javascript-best-practices/no-caller.md | 36 + .../no-case-declarations.md | 60 ++ .../no-compare-neg-zero.md | 69 ++ .../no-cond-assign.md | 74 ++ .../javascript-best-practices/no-console.md | 35 + .../javascript-best-practices/no-debugger.md | 32 + .../no-delete-var.md | 32 + .../javascript-best-practices/no-dupe-args.md | 43 + .../no-dupe-class-members.md | 92 ++ .../javascript-best-practices/no-dupe-keys.md | 68 ++ .../no-duplicate-case.md | 73 ++ .../no-empty-character-class.md | 52 + .../no-empty-pattern.md | 45 + .../javascript-best-practices/no-empty.md | 77 ++ .../javascript-best-practices/no-ex-assign.md | 38 + .../no-implied-eval.md | 180 ++++ .../no-import-assign.md | 149 +++ .../no-inner-declarations.md | 71 ++ .../javascript-best-practices/no-iterator.md | 40 + .../no-loss-of-precision.md | 132 +++ .../no-new-symbol.md | 35 + .../javascript-best-practices/no-octal.md | 47 + .../javascript-best-practices/no-proto.md | 41 + .../no-script-url.md | 40 + .../no-unsafe-negation.md | 45 + .../javascript-best-practices/no-with.md | 32 + .../require-yield.md | 45 + .../javascript-best-practices/use-isnan.md | 91 ++ .../javascript-best-practices/valid-typeof.md | 87 ++ .../event-check-origin.md | 44 + .../inner-outer-html.md | 81 ++ .../insecure-websocket.md | 34 + .../local-storage-sensitive-data.md | 39 + .../manual-sanitization.md | 45 + .../postmessage-permissive-origin.md | 38 + .../react-dangerously-inner-html.md | 50 + .../regexp-non-literal.md | 35 + .../javascript-code-style/assignment-name.md | 95 ++ .../rules/javascript-code-style/class-name.md | 33 + .../rules/javascript-code-style/eqeqeq.md | 85 ++ .../func-name-matching.md | 195 ++++ .../rules/javascript-code-style/func-names.md | 96 ++ .../javascript-code-style/function-naming.md | 38 + .../javascript-code-style/max-class-lines.md | 258 +++++ .../max-function-lines.md | 952 ++++++++++++++++++ .../rules/javascript-code-style/max-params.md | 46 + .../javascript-code-style/method-name.md | 38 + .../no-array-constructor.md | 45 + .../javascript-code-style/no-div-regex.md | 33 + .../no-duplicate-imports.md | 42 + .../no-floating-decimal.md | 41 + .../javascript-code-style/no-lonely-if.md | 122 +++ .../javascript-code-style/no-multi-assign.md | 72 ++ .../javascript-code-style/no-new-func.md | 54 + .../javascript-code-style/no-new-object.md | 61 ++ .../rules/javascript-code-style/no-new.md | 33 + .../javascript-code-style/no-return-assign.md | 84 ++ .../javascript-code-style/no-self-compare.md | 51 + .../rules/javascript-code-style/no-var.md | 62 ++ .../javascript-code-style/parameter-name.md | 37 + .../rules/javascript-code-style/radix.md | 84 ++ .../axios-avoid-insecure-http.md | 34 + .../unique-function-arguments.md | 40 + .../xml-no-external-entities.md | 43 + .../javascript-express/access-restriction.md | 46 + .../default-session-config.md | 50 + .../external-filename-upload.md | 57 ++ .../javascript-express/external-resource.md | 44 + .../javascript-express/hardcoded-secret.md | 69 ++ .../https-protocol-missing.md | 46 + .../insecure-allow-origin.md | 51 + .../javascript-express/insecure-cookie.md | 62 ++ .../javascript-express/jwt-not-revoked.md | 93 ++ .../javascript-express/missing-helmet.md | 67 ++ .../javascript-express/path-traversal.md | 57 ++ .../reduce-server-fingerprinting.md | 66 ++ .../javascript-express/xss-vulnerability.md | 45 + .../rules/javascript-inclusive/comments.md | 47 + .../javascript-inclusive/declarations.md | 50 + .../javascript-inclusive/formal-parameters.md | 42 + .../rules/javascript-inclusive/identifiers.md | 50 + .../rules/javascript-node-security/argon2.md | 38 + .../avoid-crypto-rc4.md | 32 + .../avoid-crypto-sha1.md | 32 + .../javascript-node-security/avoid-des.md | 34 + .../chmod-permissions.md | 42 + .../command-injection.md | 34 + .../crypto-avoid-weak-hash.md | 33 + .../detect-buffer-noassert.md | 115 +++ .../detect-child-process.md | 119 +++ .../detect-eval-with-expression.md | 42 + .../detect-new-buffer.md | 34 + .../detect-non-literal-fs-filename.md | 149 +++ .../detect-non-literal-regexp.md | 36 + .../detect-non-literal-require.md | 42 + .../detected-jwt-token.md | 38 + .../hardcoded-hmac-key.md | 47 + .../javascript-node-security/insecure-hash.md | 41 + .../insecure-jwt-secret-usage.md | 54 + .../jwt-hardcoded-secret.md | 41 + .../jwt-sensitive-data.md | 41 + .../jwt-weak-encryption.md | 35 + .../log-sensitive-data.md | 44 + .../oauth2-hardcoded-secret.md | 56 ++ .../javascript-node-security/sql-injection.md | 276 +++++ .../variable-sql-statement-injection.md | 35 + .../rules/jsx-react/jsx-key.md | 45 + .../jsx-react/jsx-no-comment-textnodes.md | 69 ++ .../rules/jsx-react/jsx-no-duplicate-key.md | 41 + .../rules/jsx-react/jsx-no-duplicate-props.md | 34 + .../rules/jsx-react/jsx-no-target-blank.md | 49 + .../rules/jsx-react/no-children-prop.md | 44 + .../jsx-react/no-danger-with-children.md | 43 + .../rules/jsx-react/no-deprecated.md | 73 ++ .../rules/jsx-react/no-render-return-value.md | 34 + .../rules/jsx-react/no-string-refs.md | 58 ++ .../rules/jsx-react/require-render-return.md | 52 + .../ambiguous-class-name.md | 34 + .../ambiguous-function-name.md | 34 + .../ambiguous-variable-name.md | 33 + .../any-type-disallow.md | 45 + .../argument-same-name.md | 34 + .../assertraises-specific-exception.md | 34 + .../avoid-duplicate-keys.md | 43 + .../avoid-string-concat.md | 54 + .../class-methods-use-self.md | 46 + .../collection-while-iterating.md | 39 + .../comment-fixme-todo-ownership.md | 52 + .../comparison-constant-left.md | 47 + .../condition-similar-block.md | 48 + .../ctx-manager-enter-exit-defined.md | 48 + .../dataclass-special-methods.md | 66 ++ .../equal-basic-types.md | 36 + .../exception-inherit.md | 38 + .../finally-no-break-continue-return.md | 72 ++ .../function-already-exists.md | 50 + .../function-variable-argument-name.md | 39 + .../generic-exception-last.md | 57 ++ .../get-set-arguments.md | 69 ++ .../if-return-no-else.md | 46 + .../import-modules-twice.md | 45 + .../import-single-module.md | 35 + .../python-best-practices/init-call-parent.md | 52 + .../init-method-required.md | 106 ++ .../init-no-return-value.md | 44 + .../invalid-strip-call.md | 32 + .../logging-no-format.md | 37 + .../python-best-practices/method-hidden.md | 48 + .../python-best-practices/nested-blocks.md | 78 ++ .../no-assert-on-tuples.md | 34 + .../rules/python-best-practices/no-assert.md | 46 + .../python-best-practices/no-bare-except.md | 70 ++ .../python-best-practices/no-bare-raise.md | 49 + .../no-base-exception.md | 55 + .../no-datetime-today.md | 38 + .../python-best-practices/no-double-not.md | 34 + .../no-double-unary-operator.md | 35 + .../no-duplicate-base-class.md | 43 + .../python-best-practices/no-equal-unary.md | 40 + .../rules/python-best-practices/no-exit.md | 38 + .../no-generic-exception.md | 46 + .../rules/python-best-practices/no-if-true.md | 34 + .../no-range-loop-with-len.md | 43 + .../no-silent-exception.md | 43 + .../python-best-practices/open-add-flag.md | 45 + .../os-environ-no-assign.md | 37 + .../raising-not-implemented.md | 42 + .../return-bytes-not-string.md | 38 + .../return-outside-function.md | 41 + .../python-best-practices/self-assignment.md | 34 + .../slots-no-single-string.md | 53 + .../special-methods-arguments.md | 54 + .../static-method-no-self.md | 38 + .../too-many-nested-if.md | 39 + .../python-best-practices/too-many-while.md | 41 + .../type-check-isinstance.md | 39 + .../python-best-practices/unreachable-code.md | 44 + .../use-callable-not-hasattr.md | 36 + .../python-code-style/assignment-names.md | 44 + .../rules/python-code-style/class-name.md | 93 ++ .../python-code-style/function-naming.md | 67 ++ .../python-code-style/max-class-lines.md | 138 +++ .../python-code-style/max-function-lines.md | 259 +++++ .../rules/python-design/function-too-long.md | 134 +++ .../http-response-from-request.md | 45 + .../http-response-with-json-dumps.md | 47 + .../jsonresponse-no-content-type.md | 46 + .../model-charfield-max-length.md | 36 + .../rules/python-django/model-help-text.md | 39 + .../rules/python-django/no-null-boolean.md | 35 + .../python-django/no-unicode-on-models.md | 38 + .../open-filename-from-request.md | 77 ++ .../python-django/os-system-from-request.md | 51 + .../python-django/subprocess-from-request.md | 59 ++ .../python-django/use-convenience-imports.md | 32 + .../python-flask/disable-sqlalchemy-text.md | 67 ++ .../html-format-from-user-input.md | 91 ++ .../python-flask/listen-all-interfaces.md | 47 + .../python-flask/no-render-template-string.md | 47 + .../open-file-unsanitized-data.md | 73 ++ .../os-system-unsanitized-data.md | 66 ++ .../rules/python-flask/secure-cookie.md | 42 + .../python-flask/sqlalchemy-injection.md | 64 ++ .../rules/python-flask/ssrf-requests.md | 96 ++ .../python-flask/urlopen-unsanitized-data.md | 62 ++ .../rules/python-flask/use-jsonify.md | 46 + .../rules/python-inclusive/comments.md | 57 ++ .../python-inclusive/function-definition.md | 62 ++ .../rules/python-inclusive/variable-name.md | 47 + .../arith-operator-not-functions.md | 60 ++ .../rules/python-pandas/avoid-inplace.md | 36 + .../comp-operator-not-function.md | 32 + .../rules/python-pandas/import-as-pd.md | 53 + .../python-pandas/isna-instead-of-isnull.md | 36 + .../rules/python-pandas/loc-not-ix.md | 40 + .../python-pandas/notna-instead-of-notnull.md | 32 + .../rules/python-pandas/pivot-table.md | 51 + .../use-read-csv-not-read-table.md | 32 + .../asyncio-subprocess-create-shell.md | 47 + .../asyncio-subprocess-exec.md | 46 + .../rules/python-security/avoid-random.md | 64 ++ .../python-security/aws-boto-credentials.md | 89 ++ .../deserialize-untrusted-data.md | 54 + .../python-security/file-write-others.md | 51 + .../python-security/hardcoded-tmp-file.md | 64 ++ .../html-string-from-parameters.md | 76 ++ .../insecure-hash-functions.md | 52 + .../rules/python-security/insecure-jwt.md | 53 + .../python-security/insecure-ssl-protocols.md | 74 ++ .../rules/python-security/jinja-autoescape.md | 70 ++ .../rules/python-security/mktemp.md | 49 + .../no-empty-array-as-parameter.md | 38 + .../rules/python-security/no-eval.md | 45 + .../rules/python-security/os-spawn.md | 57 ++ .../rules/python-security/os-system.md | 88 ++ .../rules/python-security/request-verify.md | 42 + .../rules/python-security/requests-http.md | 72 ++ .../rules/python-security/requests-timeout.md | 64 ++ .../python-security/ruamel-unsafe-yaml.md | 55 + .../sql-server-security-credentials.md | 86 ++ .../python-security/ssl-unverified-context.md | 52 + .../python-security/subprocess-shell-true.md | 43 + .../variable-sql-statement-injection.md | 145 +++ .../rules/python-security/yaml-load.md | 52 + .../tsx-react/jsx-no-comment-textnodes.md | 69 ++ .../rules/tsx-react/no-children-prop.md | 44 + .../tsx-react/no-danger-with-children.md | 43 + .../rules/tsx-react/no-deprecated.md | 73 ++ .../rules/tsx-react/no-render-return-value.md | 34 + .../rules/tsx-react/no-string-refs.md | 58 ++ .../rules/tsx-react/require-render-return.md | 52 + .../rules/tsx-react/tsx-key.md | 45 + .../rules/tsx-react/tsx-no-duplicate-key.md | 41 + .../rules/tsx-react/tsx-no-target-blank.md | 49 + .../typescript-best-practices/ban-types.md | 62 ++ .../boolean-prop-naming.md | 41 + .../for-direction.md | 83 ++ .../typescript-best-practices/new-parens.md | 84 ++ .../typescript-best-practices/no-alert.md | 80 ++ .../no-async-promise-executor.md | 35 + .../typescript-best-practices/no-caller.md | 36 + .../no-compare-neg-zero.md | 69 ++ .../no-cond-assign.md | 74 ++ .../typescript-best-practices/no-console.md | 35 + .../typescript-best-practices/no-debugger.md | 32 + .../no-delete-var.md | 32 + .../typescript-best-practices/no-dupe-keys.md | 68 ++ .../no-duplicate-enum-values.md | 108 ++ .../no-duplicate-type-constituents.md | 112 +++ .../no-empty-character-class.md | 52 + .../no-empty-pattern.md | 45 + .../typescript-best-practices/no-empty.md | 77 ++ .../typescript-best-practices/no-ex-assign.md | 38 + .../no-explicit-any.md | 175 ++++ .../no-extra-non-null-assertion.md | 58 ++ .../no-implied-eval.md | 180 ++++ .../no-inner-declarations.md | 71 ++ .../typescript-best-practices/no-iterator.md | 40 + .../no-loss-of-precision.md | 131 +++ .../typescript-best-practices/no-namespace.md | 73 ++ .../no-non-null-optional-chain.md | 53 + .../typescript-best-practices/no-proto.md | 41 + .../no-script-url.md | 40 + .../no-unnecessary-type-constraint.md | 74 ++ .../no-unsafe-assignment.md | 74 ++ .../no-unsafe-declaration-merging.md | 41 + .../no-unsafe-negation.md | 45 + .../no-var-requires.md | 51 + .../require-yield.md | 45 + .../triple-slash-reference.md | 36 + .../event-check-origin.md | 44 + .../inner-outer-html.md | 81 ++ .../insecure-websocket.md | 34 + .../local-storage-sensitive-data.md | 39 + .../manual-sanitization.md | 45 + .../postmessage-permissive-origin.md | 38 + .../react-dangerously-inner-html.md | 50 + .../regexp-non-literal.md | 35 + .../rules/typescript-code-style/array-type.md | 129 +++ .../typescript-code-style/assignment-name.md | 94 ++ .../typescript-code-style/ban-ts-comment.md | 39 + .../ban-tslint-comment.md | 40 + .../rules/typescript-code-style/class-name.md | 33 + .../rules/typescript-code-style/eqeqeq.md | 85 ++ .../func-name-matching.md | 195 ++++ .../rules/typescript-code-style/func-names.md | 96 ++ .../typescript-code-style/function-naming.md | 38 + .../typescript-code-style/max-class-lines.md | 258 +++++ .../max-function-lines.md | 952 ++++++++++++++++++ .../rules/typescript-code-style/max-params.md | 46 + .../typescript-code-style/method-name.md | 38 + .../no-array-constructor.md | 45 + .../no-confusing-non-null-assertion.md | 44 + .../typescript-code-style/no-div-regex.md | 33 + .../no-duplicate-imports.md | 42 + .../no-empty-interface.md | 51 + .../no-floating-decimal.md | 41 + .../no-inferrable-types.md | 111 ++ .../typescript-code-style/no-lonely-if.md | 122 +++ .../typescript-code-style/no-multi-assign.md | 72 ++ .../typescript-code-style/no-new-func.md | 54 + .../typescript-code-style/no-new-object.md | 60 ++ .../rules/typescript-code-style/no-new.md | 33 + .../typescript-code-style/no-return-assign.md | 84 ++ .../typescript-code-style/no-self-compare.md | 51 + .../no-useless-empty-export.md | 49 + .../rules/typescript-code-style/no-var.md | 62 ++ .../typescript-code-style/parameter-name.md | 37 + .../rules/typescript-code-style/radix.md | 84 ++ .../axios-avoid-insecure-http.md | 34 + .../unique-function-arguments.md | 40 + .../xml-no-external-entities.md | 43 + .../typescript-express/access-restriction.md | 46 + .../default-session-config.md | 50 + .../external-filename-upload.md | 53 + .../typescript-express/external-resource.md | 44 + .../typescript-express/hardcoded-secret.md | 69 ++ .../https-protocol-missing.md | 48 + .../insecure-allow-origin.md | 51 + .../typescript-express/insecure-cookie.md | 61 ++ .../typescript-express/jwt-not-revoked.md | 60 ++ .../typescript-express/missing-helmet.md | 53 + .../typescript-express/path-traversal.md | 57 ++ .../reduce-server-fingerprinting.md | 66 ++ .../typescript-express/xss-vulnerability.md | 45 + .../rules/typescript-inclusive/comments.md | 47 + .../typescript-inclusive/declarations.md | 50 + .../typescript-inclusive/formal-parameters.md | 42 + .../rules/typescript-inclusive/identifiers.md | 50 + .../rules/typescript-node-security/argon2.md | 38 + .../avoid-crypto-rc4.md | 32 + .../avoid-crypto-sha1.md | 32 + .../typescript-node-security/avoid-des.md | 34 + .../chmod-permissions.md | 42 + .../command-injection.md | 34 + .../crypto-avoid-weak-hash.md | 33 + .../detect-buffer-noassert.md | 115 +++ .../detect-child-process.md | 119 +++ .../detect-eval-with-expression.md | 42 + .../detect-new-buffer.md | 34 + .../detect-non-literal-fs-filename.md | 149 +++ .../detect-non-literal-regexp.md | 36 + .../detect-non-literal-require.md | 42 + .../detected-jwt-token.md | 38 + .../hardcoded-hmac-key.md | 47 + .../typescript-node-security/insecure-hash.md | 38 + .../insecure-jwt-secret-usage.md | 54 + .../jwt-hardcoded-secret.md | 40 + .../jwt-sensitive-data.md | 40 + .../jwt-weak-encryption.md | 35 + .../log-sensitive-data.md | 44 + .../oauth2-hardcoded-secret.md | 56 ++ .../typescript-node-security/sql-injection.md | 276 +++++ .../py/build/configurations/pull_config.yaml | 10 +- .../configurations/pull_config_preview.yaml | 12 +- 407 files changed, 24913 insertions(+), 22 deletions(-) rename content/en/{continuous_integration => }/dora_metrics/_index.md (99%) rename content/en/{continuous_integration => }/quality_gates/_index.md (99%) rename content/en/{continuous_integration => }/static_analysis/_index.md (99%) create mode 100644 content/en/static_analysis/circleci_orbs.md create mode 100644 content/en/static_analysis/github_actions.md rename content/en/{continuous_integration => }/static_analysis/rules/_index.md (99%) create mode 100644 content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/avoid-http.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/no-root-user.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/tag-image-version.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/yum-use-y.md create mode 100644 content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/for-direction.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/new-parens.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-alert.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-caller.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-console.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-debugger.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-empty.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-iterator.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-octal.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-proto.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-script-url.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-with.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/require-yield.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/use-isnan.md create mode 100644 content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md create mode 100644 content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/assignment-name.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/class-name.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/eqeqeq.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/func-name-matching.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/func-names.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/function-naming.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/max-class-lines.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/max-function-lines.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/max-params.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/method-name.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-div-regex.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-new-func.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-new-object.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-new.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-return-assign.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-self-compare.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/no-var.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/parameter-name.md create mode 100644 content/en/static_analysis/rules/javascript-code-style/radix.md create mode 100644 content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md create mode 100644 content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md create mode 100644 content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md create mode 100644 content/en/static_analysis/rules/javascript-express/access-restriction.md create mode 100644 content/en/static_analysis/rules/javascript-express/default-session-config.md create mode 100644 content/en/static_analysis/rules/javascript-express/external-filename-upload.md create mode 100644 content/en/static_analysis/rules/javascript-express/external-resource.md create mode 100644 content/en/static_analysis/rules/javascript-express/hardcoded-secret.md create mode 100644 content/en/static_analysis/rules/javascript-express/https-protocol-missing.md create mode 100644 content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md create mode 100644 content/en/static_analysis/rules/javascript-express/insecure-cookie.md create mode 100644 content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md create mode 100644 content/en/static_analysis/rules/javascript-express/missing-helmet.md create mode 100644 content/en/static_analysis/rules/javascript-express/path-traversal.md create mode 100644 content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md create mode 100644 content/en/static_analysis/rules/javascript-express/xss-vulnerability.md create mode 100644 content/en/static_analysis/rules/javascript-inclusive/comments.md create mode 100644 content/en/static_analysis/rules/javascript-inclusive/declarations.md create mode 100644 content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md create mode 100644 content/en/static_analysis/rules/javascript-inclusive/identifiers.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/argon2.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/avoid-des.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/command-injection.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-child-process.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/insecure-hash.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/sql-injection.md create mode 100644 content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md create mode 100644 content/en/static_analysis/rules/jsx-react/jsx-key.md create mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md create mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md create mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md create mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md create mode 100644 content/en/static_analysis/rules/jsx-react/no-children-prop.md create mode 100644 content/en/static_analysis/rules/jsx-react/no-danger-with-children.md create mode 100644 content/en/static_analysis/rules/jsx-react/no-deprecated.md create mode 100644 content/en/static_analysis/rules/jsx-react/no-render-return-value.md create mode 100644 content/en/static_analysis/rules/jsx-react/no-string-refs.md create mode 100644 content/en/static_analysis/rules/jsx-react/require-render-return.md create mode 100644 content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md create mode 100644 content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md create mode 100644 content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md create mode 100644 content/en/static_analysis/rules/python-best-practices/any-type-disallow.md create mode 100644 content/en/static_analysis/rules/python-best-practices/argument-same-name.md create mode 100644 content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md create mode 100644 content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md create mode 100644 content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md create mode 100644 content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md create mode 100644 content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md create mode 100644 content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md create mode 100644 content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md create mode 100644 content/en/static_analysis/rules/python-best-practices/condition-similar-block.md create mode 100644 content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md create mode 100644 content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md create mode 100644 content/en/static_analysis/rules/python-best-practices/equal-basic-types.md create mode 100644 content/en/static_analysis/rules/python-best-practices/exception-inherit.md create mode 100644 content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md create mode 100644 content/en/static_analysis/rules/python-best-practices/function-already-exists.md create mode 100644 content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md create mode 100644 content/en/static_analysis/rules/python-best-practices/generic-exception-last.md create mode 100644 content/en/static_analysis/rules/python-best-practices/get-set-arguments.md create mode 100644 content/en/static_analysis/rules/python-best-practices/if-return-no-else.md create mode 100644 content/en/static_analysis/rules/python-best-practices/import-modules-twice.md create mode 100644 content/en/static_analysis/rules/python-best-practices/import-single-module.md create mode 100644 content/en/static_analysis/rules/python-best-practices/init-call-parent.md create mode 100644 content/en/static_analysis/rules/python-best-practices/init-method-required.md create mode 100644 content/en/static_analysis/rules/python-best-practices/init-no-return-value.md create mode 100644 content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md create mode 100644 content/en/static_analysis/rules/python-best-practices/logging-no-format.md create mode 100644 content/en/static_analysis/rules/python-best-practices/method-hidden.md create mode 100644 content/en/static_analysis/rules/python-best-practices/nested-blocks.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-assert.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-bare-except.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-bare-raise.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-base-exception.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-datetime-today.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-double-not.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-equal-unary.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-exit.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-generic-exception.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-if-true.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md create mode 100644 content/en/static_analysis/rules/python-best-practices/no-silent-exception.md create mode 100644 content/en/static_analysis/rules/python-best-practices/open-add-flag.md create mode 100644 content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md create mode 100644 content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md create mode 100644 content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md create mode 100644 content/en/static_analysis/rules/python-best-practices/return-outside-function.md create mode 100644 content/en/static_analysis/rules/python-best-practices/self-assignment.md create mode 100644 content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md create mode 100644 content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md create mode 100644 content/en/static_analysis/rules/python-best-practices/static-method-no-self.md create mode 100644 content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md create mode 100644 content/en/static_analysis/rules/python-best-practices/too-many-while.md create mode 100644 content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md create mode 100644 content/en/static_analysis/rules/python-best-practices/unreachable-code.md create mode 100644 content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md create mode 100644 content/en/static_analysis/rules/python-code-style/assignment-names.md create mode 100644 content/en/static_analysis/rules/python-code-style/class-name.md create mode 100644 content/en/static_analysis/rules/python-code-style/function-naming.md create mode 100644 content/en/static_analysis/rules/python-code-style/max-class-lines.md create mode 100644 content/en/static_analysis/rules/python-code-style/max-function-lines.md create mode 100644 content/en/static_analysis/rules/python-design/function-too-long.md create mode 100644 content/en/static_analysis/rules/python-django/http-response-from-request.md create mode 100644 content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md create mode 100644 content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md create mode 100644 content/en/static_analysis/rules/python-django/model-charfield-max-length.md create mode 100644 content/en/static_analysis/rules/python-django/model-help-text.md create mode 100644 content/en/static_analysis/rules/python-django/no-null-boolean.md create mode 100644 content/en/static_analysis/rules/python-django/no-unicode-on-models.md create mode 100644 content/en/static_analysis/rules/python-django/open-filename-from-request.md create mode 100644 content/en/static_analysis/rules/python-django/os-system-from-request.md create mode 100644 content/en/static_analysis/rules/python-django/subprocess-from-request.md create mode 100644 content/en/static_analysis/rules/python-django/use-convenience-imports.md create mode 100644 content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md create mode 100644 content/en/static_analysis/rules/python-flask/html-format-from-user-input.md create mode 100644 content/en/static_analysis/rules/python-flask/listen-all-interfaces.md create mode 100644 content/en/static_analysis/rules/python-flask/no-render-template-string.md create mode 100644 content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md create mode 100644 content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md create mode 100644 content/en/static_analysis/rules/python-flask/secure-cookie.md create mode 100644 content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md create mode 100644 content/en/static_analysis/rules/python-flask/ssrf-requests.md create mode 100644 content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md create mode 100644 content/en/static_analysis/rules/python-flask/use-jsonify.md create mode 100644 content/en/static_analysis/rules/python-inclusive/comments.md create mode 100644 content/en/static_analysis/rules/python-inclusive/function-definition.md create mode 100644 content/en/static_analysis/rules/python-inclusive/variable-name.md create mode 100644 content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md create mode 100644 content/en/static_analysis/rules/python-pandas/avoid-inplace.md create mode 100644 content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md create mode 100644 content/en/static_analysis/rules/python-pandas/import-as-pd.md create mode 100644 content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md create mode 100644 content/en/static_analysis/rules/python-pandas/loc-not-ix.md create mode 100644 content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md create mode 100644 content/en/static_analysis/rules/python-pandas/pivot-table.md create mode 100644 content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md create mode 100644 content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md create mode 100644 content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md create mode 100644 content/en/static_analysis/rules/python-security/avoid-random.md create mode 100644 content/en/static_analysis/rules/python-security/aws-boto-credentials.md create mode 100644 content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md create mode 100644 content/en/static_analysis/rules/python-security/file-write-others.md create mode 100644 content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md create mode 100644 content/en/static_analysis/rules/python-security/html-string-from-parameters.md create mode 100644 content/en/static_analysis/rules/python-security/insecure-hash-functions.md create mode 100644 content/en/static_analysis/rules/python-security/insecure-jwt.md create mode 100644 content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md create mode 100644 content/en/static_analysis/rules/python-security/jinja-autoescape.md create mode 100644 content/en/static_analysis/rules/python-security/mktemp.md create mode 100644 content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md create mode 100644 content/en/static_analysis/rules/python-security/no-eval.md create mode 100644 content/en/static_analysis/rules/python-security/os-spawn.md create mode 100644 content/en/static_analysis/rules/python-security/os-system.md create mode 100644 content/en/static_analysis/rules/python-security/request-verify.md create mode 100644 content/en/static_analysis/rules/python-security/requests-http.md create mode 100644 content/en/static_analysis/rules/python-security/requests-timeout.md create mode 100644 content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md create mode 100644 content/en/static_analysis/rules/python-security/sql-server-security-credentials.md create mode 100644 content/en/static_analysis/rules/python-security/ssl-unverified-context.md create mode 100644 content/en/static_analysis/rules/python-security/subprocess-shell-true.md create mode 100644 content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md create mode 100644 content/en/static_analysis/rules/python-security/yaml-load.md create mode 100644 content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md create mode 100644 content/en/static_analysis/rules/tsx-react/no-children-prop.md create mode 100644 content/en/static_analysis/rules/tsx-react/no-danger-with-children.md create mode 100644 content/en/static_analysis/rules/tsx-react/no-deprecated.md create mode 100644 content/en/static_analysis/rules/tsx-react/no-render-return-value.md create mode 100644 content/en/static_analysis/rules/tsx-react/no-string-refs.md create mode 100644 content/en/static_analysis/rules/tsx-react/require-render-return.md create mode 100644 content/en/static_analysis/rules/tsx-react/tsx-key.md create mode 100644 content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md create mode 100644 content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/ban-types.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/for-direction.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/new-parens.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-alert.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-caller.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-console.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-debugger.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-empty.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-iterator.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-namespace.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-proto.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-script-url.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/require-yield.md create mode 100644 content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md create mode 100644 content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/array-type.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/assignment-name.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/class-name.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/eqeqeq.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/func-name-matching.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/func-names.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/function-naming.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/max-class-lines.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/max-function-lines.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/max-params.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/method-name.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-div-regex.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-new-func.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-new-object.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-new.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-return-assign.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-self-compare.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/no-var.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/parameter-name.md create mode 100644 content/en/static_analysis/rules/typescript-code-style/radix.md create mode 100644 content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md create mode 100644 content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md create mode 100644 content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md create mode 100644 content/en/static_analysis/rules/typescript-express/access-restriction.md create mode 100644 content/en/static_analysis/rules/typescript-express/default-session-config.md create mode 100644 content/en/static_analysis/rules/typescript-express/external-filename-upload.md create mode 100644 content/en/static_analysis/rules/typescript-express/external-resource.md create mode 100644 content/en/static_analysis/rules/typescript-express/hardcoded-secret.md create mode 100644 content/en/static_analysis/rules/typescript-express/https-protocol-missing.md create mode 100644 content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md create mode 100644 content/en/static_analysis/rules/typescript-express/insecure-cookie.md create mode 100644 content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md create mode 100644 content/en/static_analysis/rules/typescript-express/missing-helmet.md create mode 100644 content/en/static_analysis/rules/typescript-express/path-traversal.md create mode 100644 content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md create mode 100644 content/en/static_analysis/rules/typescript-express/xss-vulnerability.md create mode 100644 content/en/static_analysis/rules/typescript-inclusive/comments.md create mode 100644 content/en/static_analysis/rules/typescript-inclusive/declarations.md create mode 100644 content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md create mode 100644 content/en/static_analysis/rules/typescript-inclusive/identifiers.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/argon2.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/avoid-des.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/command-injection.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-child-process.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/insecure-hash.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md create mode 100644 content/en/static_analysis/rules/typescript-node-security/sql-injection.md diff --git a/config/_default/menus/menus.en.yaml b/config/_default/menus/menus.en.yaml index 4d3311bec3fea..dea51276097e8 100644 --- a/config/_default/menus/menus.en.yaml +++ b/config/_default/menus/menus.en.yaml @@ -2617,37 +2617,37 @@ main: parent: cd_explorer weight: 303 - name: DORA Metrics - url: continuous_integration/dora_metrics/ + url: dora_metrics/ pre: ci parent: software_delivery_heading - identifier: ci_explorer_dora_metrics + identifier: dora_metrics weight: 170000 - name: Static Analysis - url: continuous_integration/static_analysis/ + url: static_analysis/ pre: ci parent: software_delivery_heading - identifier: ci_static_analysis + identifier: static_analysis weight: 180000 - name: Rules - url: continuous_integration/static_analysis/rules - parent: ci_static_analysis - identifier: ci_static_analysis_rules + url: static_analysis/rules + parent: static_analysis + identifier: static_analysis_rules weight: 101 - name: CircleCI Orbs - url: continuous_integration/static_analysis/circleci_orbs - parent: ci_static_analysis - identifier: ci_static_analysis_circleci_orbs + url: static_analysis/circleci_orbs + parent: static_analysis + identifier: static_analysis_circleci_orbs weight: 102 - name: GitHub Actions - url: continuous_integration/static_analysis/github_actions - parent: ci_static_analysis - identifier: ci_static_analysis_github_actions + url: static_analysis/github_actions + parent: static_analysis + identifier: static_analysis_github_actions weight: 103 - name: Quality Gates - url: continuous_integration/quality_gates/ + url: quality_gates/ pre: ci parent: software_delivery_heading - identifier: ci_quality_gates + identifier: quality_gates weight: 190000 - name: Database Monitoring url: database_monitoring/ diff --git a/content/en/continuous_integration/dora_metrics/_index.md b/content/en/dora_metrics/_index.md similarity index 99% rename from content/en/continuous_integration/dora_metrics/_index.md rename to content/en/dora_metrics/_index.md index f42d07df804a8..739e7ca275289 100644 --- a/content/en/continuous_integration/dora_metrics/_index.md +++ b/content/en/dora_metrics/_index.md @@ -2,6 +2,8 @@ title: DORA Metrics kind: documentation description: Learn how to use DORA metrics to improve and measure software development. +aliases: +- /continuous_integration/dora_metrics is_beta: true further_reading: - link: "/continuous_integration/tests" diff --git a/content/en/continuous_integration/quality_gates/_index.md b/content/en/quality_gates/_index.md similarity index 99% rename from content/en/continuous_integration/quality_gates/_index.md rename to content/en/quality_gates/_index.md index 38565d8a82fd4..4327a46fe5f47 100644 --- a/content/en/continuous_integration/quality_gates/_index.md +++ b/content/en/quality_gates/_index.md @@ -3,6 +3,8 @@ title: Quality Gates kind: documentation description: Learn how to use Quality Gates in your pipeline. is_beta: true +aliases: +- /continuous_integration/quality_gates further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/static_analysis/_index.md b/content/en/static_analysis/_index.md similarity index 99% rename from content/en/continuous_integration/static_analysis/_index.md rename to content/en/static_analysis/_index.md index 0450f4664144e..240ce6b186216 100644 --- a/content/en/continuous_integration/static_analysis/_index.md +++ b/content/en/static_analysis/_index.md @@ -2,6 +2,8 @@ title: Static Analysis kind: documentation description: Learn about Datadog Static Analysis to scan code for quality issues and security vulnerabilities before your code reaches production. +aliases: +- /continuous_integration/static_analysis/ is_beta: true further_reading: - link: "https://www.datadoghq.com/blog/monitor-ci-pipelines/" diff --git a/content/en/static_analysis/circleci_orbs.md b/content/en/static_analysis/circleci_orbs.md new file mode 100644 index 0000000000000..007a018ac3942 --- /dev/null +++ b/content/en/static_analysis/circleci_orbs.md @@ -0,0 +1,102 @@ +--- +aliases: +- /continuous_integration/static_analysis/circleci_orbs +dependencies: +- https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md +description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. +kind: documentation +title: Static Analysis and CircleCI Orbs +--- +[![CircleCI Build Status](https://circleci.com/gh/DataDog/datadog-static-analyzer-circleci-orb.svg?style=shield "CircleCI Build Status")](https://circleci.com/gh/DataDog/datadog-static-analyzer-circleci-orb) [![CircleCI Orb Version](https://badges.circleci.com/orbs/DataDog/datadog-static-analyzer-circleci-orb.svg)](https://circleci.com/developer/orbs/orb/DataDog/datadog-static-analyzer-circleci-orb) [![GitHub License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/DataDog/datadog-static-analyzer-circleci-orb/main/LICENSE) [![CircleCI Community](https://img.shields.io/badge/community-CircleCI%20Discuss-343434.svg)](https://discuss.circleci.com/c/ecosystem/orbs) + + +Run a Datadog Static Analysis in your CircleCI workflows. + +## Requirements + +To use the Datadog static analyzer, you need to add a `static-analysis.datadog.yml` file to your repositories root directory that specifies what rulesets to use. + +```yaml +rulesets: + - + - +``` + +#### Example for Python + +You can see an example for repositories based on Python: + +```yaml +rulesets: + - python-security + - python-code-style + - python-best-practices +``` + +## Workflow + +Create a file in `.circleci` to run a Datadog static analysis. + +Here's a sample workflow file. + +```yaml +version: 2.1 +orbs: + datadog-static-analysis: datadog/datadog-static-analyzer-circleci-orb@1.0.0 +jobs: + run-static-analysis-job: + docker: + - image: cimg/node:current + steps: + - checkout + - datadog-static-analysis/analyze: + service: my-service +workflows: + main: + jobs: + - run-static-analysis-job +``` + +## Environment Variables + +These environment variables should be set in the [CircleCI Project Settings](https://circleci.com/docs/set-environment-variable/#set-an-environment-variable-in-a-project) page. + +| Name | Description | Required | Default | +|--------------|----------------------------------------------------------------------------------------------------------------------------|----------|-----------------| +| `DD_API_KEY` | Your Datadog API key. This key is created by your [Datadog organization](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys) and should be stored as a secret. | True | | +| `DD_APP_KEY` | Your Datadog Application key. This key is created by your [Datadog organization](https://docs.datadoghq.com/account_management/api-app-keys/) and should be stored as a secret. | True | | + +## Inputs + +To customize your workflow, you can set the following parameters for an analysis. + +| Name | Description | Required | Default | +|--------------|----------------------------------------------------------------------------------------------------------------------------|----------|-----------------| +| `service` | The service you want your results tagged with. | True | | +| `env` | The environment you want your results tagged with. | False | `none` | +| `site` | The [Datadog site](https://docs.datadoghq.com/getting_started/site/) | False | `datadoghq.com` | + +## Resources + +[CircleCI Orb Registry Page](https://circleci.com/developer/orbs/orb/DataDog/datadog-static-analyzer-circleci-orb) - The official registry page of this orb for all versions, executors, commands, and jobs described. + +[CircleCI Orb Docs](https://circleci.com/docs/orb-intro/#section=configuration) - Docs for using, creating, and publishing CircleCI Orbs. + +### How to Contribute + +We welcome [issues](https://github.com/DataDog/datadog-static-analyzer-circleci-orb/issues) to and [pull requests](https://github.com/DataDog/datadog-static-analyzer-circleci-orb/pulls) against this repository! + +### How to Publish An Update +1. Merge pull requests with desired changes to the main branch. + - For the best experience, squash-and-merge and use [Conventional Commit Messages](https://conventionalcommits.org/). +2. Find the current version of the orb. + - You can run `circleci orb info DataDog/datadog-static-analyzer-circleci-orb | grep "Latest"` to see the current version. +3. Create a [new Release](https://github.com/DataDog/datadog-static-analyzer-circleci-orb/releases/new) on GitHub. + - Click "Choose a tag" and _create_ a new [semantically versioned](http://semver.org/) tag. (ex: v1.0.0) + - We will have an opportunity to change this before we publish if needed after the next step. +4. Click _"+ Auto-generate release notes"_. + - This will create a summary of all of the merged pull requests since the previous release. + - If you have used _[Conventional Commit Messages](https://conventionalcommits.org/)_ it will be easy to determine what types of changes were made, allowing you to ensure the correct version tag is being published. +5. Now ensure the version tag selected is semantically accurate based on the changes included. +6. Click _"Publish Release"_. + - This will push a new tag and trigger your publishing pipeline on CircleCI. diff --git a/content/en/static_analysis/github_actions.md b/content/en/static_analysis/github_actions.md new file mode 100644 index 0000000000000..b1f9479e235f7 --- /dev/null +++ b/content/en/static_analysis/github_actions.md @@ -0,0 +1,72 @@ +--- +aliases: +- /continuous_integration/static_analysis/github_actions +dependencies: +- https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md +description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. +kind: documentation +title: Static Analysis and GitHub Actions +--- +Run a Datadog Static Analysis in your Github Action workflows. + +## Requirements + +To use the Datadog static analyzer, you need to add a `static-analysis.datadog.yml` file to your repositories root directory that specifies what rulesets to use. + +```yaml +rulesets: + - + - +``` + +#### Example for Python + +You can see an example for repositories based on Python: + +```yaml +rulesets: + - python-security + - python-code-style + - python-best-practices +``` + +## Workflow + +Create a file in `.github/workflows` to run a Datadog static analysis. + +Here's a sample workflow file. + +```yaml +on: [push] + +jobs: + check-quality: + runs-on: ubuntu-latest + name: Datadog Static Analyzer + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Check code meets quality standards + id: datadog-static-analysis + uses: DataDog/datadog-static-analyzer-github-action@v1.0.0 + with: + dd_app_key: ${{ secrets.DD_APP_KEY }} + dd_api_key: ${{ secrets.DD_API_KEY }} + dd_service: "my-service" + dd_env: "ci" +``` + +> You **must** set your Datadog API and Application Keys as secrets in your GitHub repository. For more information, see [API and Application Keys][1] + +## Inputs + +| Name | Description | Required | Default | +|--------------|----------------------------------------------------------------------------------------------------------------------------|----------|-----------------| +| `dd_api_key` | Your Datadog API key. This key is created by your [Datadog organization][1] and should be stored as a [secret][2]. | True | | +| `dd_app_key` | Your Datadog Application key. This key is created by your [Datadog organization][1] and should be stored as a [secret][2]. | True | | +| `dd_service` | The service you want your results tagged with. | True | | +| `dd_env` | The environment you want your results tagged with. | False | `none` | +| `dd_site` | The [Datadog site](https://docs.datadoghq.com/getting_started/site/) | False | `datadoghq.com` | + +[1]: https://docs.datadoghq.com/account_management/api-app-keys/ +[2]: https://docs.github.com/en/actions/security-guides/encrypted-secrets diff --git a/content/en/continuous_integration/static_analysis/rules/_index.md b/content/en/static_analysis/rules/_index.md similarity index 99% rename from content/en/continuous_integration/static_analysis/rules/_index.md rename to content/en/static_analysis/rules/_index.md index ccfc294a23faa..e9adda4145101 100644 --- a/content/en/continuous_integration/static_analysis/rules/_index.md +++ b/content/en/static_analysis/rules/_index.md @@ -3,6 +3,8 @@ title: Static Analysis Rules kind: documentation description: View rules for multiple languages for Static Analysis. is_beta: true +aliases: +- /continuous_integration/static_analysis/rules docker_best_practices_data: - link: "/continuous_integration/static_analysis/rules/docker-best-practices/absolute-workdir" tag: "absolute-workdir" diff --git a/content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md b/content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md new file mode 100644 index 0000000000000..8f981943e644d --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/absolute-workdir + language: Docker + severity: Warning +title: Use absolute workdir +--- +## Metadata +**ID:** `docker-best-practices/absolute-workdir` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Best Practices + +## Description +When using a relative `WORKDIR`, you may run into problems since you are dependent on previous `WORKDIR` instructions. Using an absolute `WORKDIR` ensures you have the right path no matter where the instruction is positioned. + +## Non-Compliant Code Examples +```docker +FROM busybox +WORKDIR usr/src/app +``` + +## Compliant Code Examples +```docker +FROM busybox +WORKDIR /usr/src/app +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md b/content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md new file mode 100644 index 0000000000000..e7018d2630c49 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: docker-best-practices/alias-must-be-unique + language: Docker + severity: Warning +title: FROM aliases must be unique +--- +## Metadata +**ID:** `docker-best-practices/alias-must-be-unique` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Error Prone + +## Description +When using multiple images in a Dockerfile, aliases must be unique. + +## Non-Compliant Code Examples +```docker +FROM awesomeimage:version as build +RUN stuff +FROM otherawesomeimage:version1 as foobar +RUN plop +FROM otherawesomeimage:version2 as build +RUN more_stuff +``` + +## Compliant Code Examples +```docker +FROM awesomeimage:version as build +RUN stuff +FROM otherawesomeimage:version as another-alias +RUN more_stuff +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md b/content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md new file mode 100644 index 0000000000000..e480e382d3737 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/apt-get-yes + language: Docker + severity: Warning +title: Always use -y with apt-get install +--- +## Metadata +**ID:** `docker-best-practices/apt-get-yes` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Best Practices + +## Description +When using `apt-get` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. + +## Non-Compliant Code Examples +```docker +RUN apt-get install gcc +``` + +## Compliant Code Examples +```docker +RUN apt-get install -y gcc +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md b/content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md new file mode 100644 index 0000000000000..81f0c7e55de5f --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/apt-pin-version + language: Docker + severity: Notice +title: Always pin versions in apt-get install +--- +## Metadata +**ID:** `docker-best-practices/apt-pin-version` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When using `apt-get install`, pin the version to avoid unwanted upgrades and undefined behavior. + +## Non-Compliant Code Examples +```docker +FROM busybox +RUN apt-get install python + +RUN apt-get update && \ + apt-get install -y --no-install-recommends openjdk-19-jdk && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/ /var/cache/oracle* +``` + +## Compliant Code Examples +```docker +FROM busybox +RUN apt-get install python=3.11 +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md b/content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md new file mode 100644 index 0000000000000..98c1c70e284e6 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: docker-best-practices/avoid-chmod-777 + language: Docker + severity: Warning +title: Do not give wide permissions on files +--- +## Metadata +**ID:** `docker-best-practices/avoid-chmod-777` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Security + +## Description +Make sure you do not give too many permissions with copying or adding a file. Adding write permissions to all means that any other users may modify the files. + + +## Non-Compliant Code Examples +```docker +ADD --chmod=777 src dst +COPY --chmod=777 src dst +``` + +## Compliant Code Examples +```docker +ADD --chmod=755 src dst +COPY --chmod=755 src dst +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md b/content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md new file mode 100644 index 0000000000000..25841be370916 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/avoid-commands-not-relevant + language: Docker + severity: Notice +title: Avoid commands not made for containers +--- +## Metadata +**ID:** `docker-best-practices/avoid-commands-not-relevant` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Some commands do not make sense to use when building a container. They require user inputs which cannot work when building a container. Avoid such commands in a Dockerfile. + +## Non-Compliant Code Examples +```docker +FROM busybox +RUN top +RUN vim +``` + +## Compliant Code Examples +```docker +FROM busybox +RUN mycommand foo bar +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/avoid-http.md b/content/en/static_analysis/rules/docker-best-practices/avoid-http.md new file mode 100644 index 0000000000000..de00969599157 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/avoid-http.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: docker-best-practices/avoid-http + language: Docker + severity: Warning +title: Avoid fetching data from HTTP endpoint +--- +## Metadata +**ID:** `docker-best-practices/avoid-http` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Security + +## Description +Always use `https` links instead of `http`. Do not use clear-text protocols as they lack encryption and authentication. + +## Non-Compliant Code Examples +```docker +RUN cd /tmp && wget http://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml +RUN cd /tmp && curl -O http://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml +RUN foobar http://domain.tld +``` + +## Compliant Code Examples +```docker +RUN cd /tmp && wget https://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml +RUN cd /tmp && curl -O https://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md b/content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md new file mode 100644 index 0000000000000..104adda55229b --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/dnf-use-y + language: Docker + severity: Warning +title: Always use -y with dnf install +--- +## Metadata +**ID:** `docker-best-practices/dnf-use-y` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Best Practices + +## Description +When using `dnf` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. + +## Non-Compliant Code Examples +```docker +RUN dnf install httpd-2.4.46 +``` + +## Compliant Code Examples +```docker +RUN dnf install -y httpd-2.4.46 +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md b/content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md new file mode 100644 index 0000000000000..94d6915897364 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: docker-best-practices/expose-admin-ports + language: Docker + severity: Warning +title: Do not expose sensitive ports +--- +## Metadata +**ID:** `docker-best-practices/expose-admin-ports` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Security + +## Description +Never expose admin ports such as the SSH port `22` in your container. It increases the surface of attack of your containers. + +## Non-Compliant Code Examples +```docker +FROM debian:jessie +EXPOSE 22 +``` + +## Compliant Code Examples +```docker +FROM debian:jessie +EXPOSE 443 +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md b/content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md new file mode 100644 index 0000000000000..07a6909ebee0b --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/expose-valid-port + language: Docker + severity: Notice +title: Expose a valid UNIX port number +--- +## Metadata +**ID:** `docker-best-practices/expose-valid-port` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +The `EXPOSE` instruction should take a valid UNIX port range. + +## Non-Compliant Code Examples +```docker +EXPOSE 1001232323 +``` + +## Compliant Code Examples +```docker +EXPOSE 8080 +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md b/content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md new file mode 100644 index 0000000000000..f6e771e2412fa --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: docker-best-practices/image-avoid-digest + language: Docker + severity: Warning +title: Do not use the digest to pull an image +--- +## Metadata +**ID:** `docker-best-practices/image-avoid-digest` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Security + +## Description +Do not use a digest to pull an image. A digest is immutable and if a vulnerability is found in this image, your container is likely to be impacted. + +A tag is mutable and any security fixes are applied when you rebuild the image. + +## Non-Compliant Code Examples +```docker +FROM image@sha256:239898ab989898 +``` + +## Compliant Code Examples +```docker +FROM image:tag +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md b/content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md new file mode 100644 index 0000000000000..80c94131ae61a --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/maintainer-deprecated + language: Docker + severity: Notice +title: The maintainer entry is deprecated +--- +## Metadata +**ID:** `docker-best-practices/maintainer-deprecated` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Use `LABEL` instead of `MAINTAINER` to report the maintainer of a Dockerfile. + +## Non-Compliant Code Examples +```docker +MAINTAINER Jean Bar +``` + +## Compliant Code Examples +```docker +LABEL maintainer="Jean Bar " +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md b/content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md new file mode 100644 index 0000000000000..f53ea2bdb3efe --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/multiple-cmd + language: Docker + severity: Notice +title: Do not use multiple CMD +--- +## Metadata +**ID:** `docker-best-practices/multiple-cmd` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not use multiple `CMD` instructions, only the last one is used. + +## Non-Compliant Code Examples +```docker +FROM awesomeimage +CMD run_server1 +CMD run_server2 +``` + +## Compliant Code Examples +```docker +FROM awesomeimage +CMD run_server +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md b/content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md new file mode 100644 index 0000000000000..665bcf0376144 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/multiple-entrypoint + language: Docker + severity: Notice +title: Do not use multiple CMD +--- +## Metadata +**ID:** `docker-best-practices/multiple-entrypoint` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not use multiple `ENTRYPOINT` instructions, only the last one is used. + +## Non-Compliant Code Examples +```docker +FROM awesomeimage +ENTRYPOINT /foo/bar +ENTRYPOINT /foo/baz +``` + +## Compliant Code Examples +```docker +FROM awesomeimage +ENTRYPOINT /foo/bar +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md b/content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md new file mode 100644 index 0000000000000..97931d0920d1c --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/multiple-healthcheck + language: Docker + severity: Notice +title: Do not use multiple HEALTHCHECK +--- +## Metadata +**ID:** `docker-best-practices/multiple-healthcheck` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +A Dockerfile with multiple `HEALTHCHECK` instructions is confusing. A container should only have one `HEALTHCHECK` instruction. + +## Non-Compliant Code Examples +```docker +HEALTHCHECK CMD foo +HEALTHCHECK CMD bar +``` + +## Compliant Code Examples +```docker +HEALTHCHECK CMD foo +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/no-root-user.md b/content/en/static_analysis/rules/docker-best-practices/no-root-user.md new file mode 100644 index 0000000000000..30db3fb8033ef --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/no-root-user.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: docker-best-practices/no-root-user + language: Docker + severity: Warning +title: Last user should not be root +--- +## Metadata +**ID:** `docker-best-practices/no-root-user` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Security + +## Description +Do not use `root` as the last user because your container runs with the `root` user. Always use a user with lower privileges. + +## Non-Compliant Code Examples +```docker +CMD foo +USER plop +CMD plip +USER root +``` + +## Compliant Code Examples +```docker +CMD foo +USER root +CMD plip +USER normaluser +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md b/content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md new file mode 100644 index 0000000000000..9bdf41e7eb8ba --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/pip-no-cache + language: Docker + severity: Notice +title: Do not use cache when installing packages +--- +## Metadata +**ID:** `docker-best-practices/pip-no-cache` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When installing Python packages with `pip`, always pin the version. + +## Non-Compliant Code Examples +```docker +FROM busybox +RUN pip install django +RUN pip3 install django +``` + +## Compliant Code Examples +```docker +FROM busybox +RUN pip install --no-cache-dir django +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md b/content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md new file mode 100644 index 0000000000000..5bcc0c791b869 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/pip-pin-versions + language: Docker + severity: Notice +title: Always pin versions with pip +--- +## Metadata +**ID:** `docker-best-practices/pip-pin-versions` + +**Language:** Docker + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When installing Python packages with `pip`, always pin the version. + +## Non-Compliant Code Examples +```docker +FROM busybox +RUN pip install django +``` + +## Compliant Code Examples +```docker +FROM busybox +RUN pip install django==1.9 +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/tag-image-version.md b/content/en/static_analysis/rules/docker-best-practices/tag-image-version.md new file mode 100644 index 0000000000000..a9226b9ac2723 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/tag-image-version.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/tag-image-version + language: Docker + severity: Warning +title: Always tag the version of an image +--- +## Metadata +**ID:** `docker-best-practices/tag-image-version` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Always tag the version of an image. You can never assume that `latest` is a specific version. + +## Non-Compliant Code Examples +```docker +FROM debian + +``` + +## Compliant Code Examples +```docker +FROM debian:unstable + +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/yum-use-y.md b/content/en/static_analysis/rules/docker-best-practices/yum-use-y.md new file mode 100644 index 0000000000000..2c18085d5f9f3 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/yum-use-y.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/yum-use-y + language: Docker + severity: Warning +title: Always use -y with yum install +--- +## Metadata +**ID:** `docker-best-practices/yum-use-y` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Best Practices + +## Description +When using `yum` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. + +## Non-Compliant Code Examples +```docker +RUN yum install gcc +``` + +## Compliant Code Examples +```docker +RUN yum install -y gcc +``` diff --git a/content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md b/content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md new file mode 100644 index 0000000000000..190ab34012f80 --- /dev/null +++ b/content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: docker-best-practices/zypper-use-y + language: Docker + severity: Warning +title: Always use -y with zypper install +--- +## Metadata +**ID:** `docker-best-practices/zypper-use-y` + +**Language:** Docker + +**Severity:** Warning + +**Category:** Best Practices + +## Description +When using `zypper` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. + + +## Non-Compliant Code Examples +```docker +RUN zypper install httpd-2.4.46 + +``` + +## Compliant Code Examples +```docker +RUN zypper install -y httpd-2.4.46 +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/for-direction.md b/content/en/static_analysis/rules/javascript-best-practices/for-direction.md new file mode 100644 index 0000000000000..734809e4cae1b --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/for-direction.md @@ -0,0 +1,83 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/for-direction + language: JavaScript + severity: Error +title: Check for loop is moving in the right direction +--- +## Metadata +**ID:** `javascript-best-practices/for-direction` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +This rule prevents you from creating conditions in which a `for` loop might end up in an infinite loop. If you need an infinite loop, use `while` statements. + +## Non-Compliant Code Examples +```javascript +// test if '++', '--' +for(var i = 0; i < 10; i--){} +for(var i = 0; i <= 10; i--){} +for(var i = 10; i > 10; i++){} +for(var i = 10; i >= 0; i++){} + +// test if '+=', '-=' +for(var i = 0; i < 10; i-=1){} +for(var i = 0; i <= 10; i-=1){} +for(var i = 10; i > 10; i+=1){} +for(var i = 10; i >= 0; i+=1){} +for(var i = 0; i < 10; i+=-1){} +for(var i = 0; i <= 10; i+=-1){} +for(var i = 10; i > 10; i-=-1){} +for(var i = 10; i >= 0; i-=-1){} +``` + +## Compliant Code Examples +```javascript +// test if '++', '--' +for(var i = 0; i < 10; i++){} +for(var i = 0; i <= 10; i++){} +for(var i = 10; i > 0; i--){} +for(var i = 10; i >= 0; i--){} + +// test if '+=', '-=', +for(var i = 0; i < 10; i+=1){} +for(var i = 0; i <= 10; i+=1){} +for(var i = 0; i < 10; i-=-1){} +for(var i = 0; i <= 10; i-=-1){} +for(var i = 10; i > 0; i-=1){} +for(var i = 10; i >= 0; i-=1){} +for(var i = 10; i > 0; i+=-1){} +for(var i = 10; i >= 0; i+=-1){} + +// test if no update. +for(var i = 10; i > 0;){} +for(var i = 10; i >= 0;){} +for(var i = 10; i < 0;){} +for(var i = 10; i <= 0;){} +for(var i = 10; i <= 0; j++){} +for(var i = 10; i <= 0; j--){} +for(var i = 10; i >= 0; j++){} +for(var i = 10; i >= 0; j--){} +for(var i = 10; i >= 0; j += 2){} +for(var i = 10; i >= 0; j -= 2){} +for(var i = 10; i >= 0; i |= 2){} +for(var i = 10; i >= 0; i %= 2){} +for(var i = 0; i < MAX; i += STEP_SIZE); +for(var i = 0; i < MAX; i -= STEP_SIZE); +for(var i = 10; i > 0; i += STEP_SIZE); + +// other cond-expressions. +for(var i = 0; i !== 10; i+=1){} +for(var i = 0; i === 10; i+=1){} +for(var i = 0; i == 10; i+=1){} +for(var i = 0; i != 10; i+=1){} +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/new-parens.md b/content/en/static_analysis/rules/javascript-best-practices/new-parens.md new file mode 100644 index 0000000000000..4303ee6366538 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/new-parens.md @@ -0,0 +1,85 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/new-parens + language: JavaScript + severity: Notice +title: Invoking a constructor must use parentheses +--- +## Metadata +**ID:** `javascript-best-practices/new-parens` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +This rule enforces the consistent use of parentheses in `new` statements. In JavaScript, you can omit parentheses when the constructor has no arguments, but you should always use them for consistency. + +## Non-Compliant Code Examples +```javascript +// Default (Always) +var a = new Date; +var a = new Date +var a = new (Date); +var a = new (Date) +var a = (new Date) + +// This `()` is `CallExpression`'s. This is a call of the result of `new Date`. +var a = (new Date)() +var a = new foo.Bar; +var a = (new Foo).bar; + +// Explicit always +var a = new Date; +var a = new foo.Bar; +var a = (new Foo).bar; +var a = new new Foo() + +// OPTION never not supported +// Never +// var a = new Date(); +// var a = new Date() +// var a = new (Date)(); +// var a = new (Date)() +// var a = (new Date()) +// var a = (new Date())() +// var a = new foo.Bar(); +// var a = (new Foo()).bar; +// var a = new new Foo() +``` + +## Compliant Code Examples +```javascript +// Default (Always) +var a = new Date(); +var a = new Date(function() {}); +var a = new (Date)(); +var a = new ((Date))(); +var a = (new Date()); +var a = new foo.Bar(); +var a = (new Foo()).bar; + +// Explicit Always +var a = new Date(); +var a = new foo.Bar(); +var a = (new Foo()).bar; + +// OPTION never not supported +// Never +// var a = new Date; +// var a = new Date(function() {}); +// var a = new (Date); +// var a = new ((Date)); +// var a = (new Date); +// var a = new foo.Bar; +// var a = (new Foo).bar; +// var a = new Person('Name') +// var a = new Person('Name', 12) +// var a = new ((Person))('Name'); +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-alert.md b/content/en/static_analysis/rules/javascript-best-practices/no-alert.md new file mode 100644 index 0000000000000..5b36eed55c703 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-alert.md @@ -0,0 +1,80 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-alert + language: JavaScript + severity: Notice +title: Avoid the use of alert, confirm, and prompt +--- +## Metadata +**ID:** `javascript-best-practices/no-alert` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +JavaScript’s `alert`, `confirm`, and `prompt` functions present obtrusive UI elements that prevent further user actions by taking control of the focus. These UI elements cannot be styled. + +## Non-Compliant Code Examples +```javascript +alert(foo) +window.alert(foo) +window['alert'](foo) +confirm(foo) +window.confirm(foo) +window['confirm'](foo) +prompt(foo) +window.prompt(foo) +window['prompt'](foo) +function alert() {} window.alert(foo) +var alert = function() {}; +window.alert(foo) +function foo(alert) { window.alert(); } +function foo() { alert(); } +function foo() { var alert = function() {}; } +alert(); +this.alert(foo) +this['alert'](foo) +function foo() { var window = bar; window.alert(); } +window.alert(); +globalThis['alert'](foo) +globalThis.alert(); +function foo() { var globalThis = bar; globalThis.alert(); } +globalThis.alert(); + +// Optional chaining +window?.alert(foo); +(window?.alert)(foo); +``` + +## Compliant Code Examples +```javascript +a[o.k](1) +foo.alert(foo) +foo.confirm(foo) +foo.prompt(foo) +// global overrides are not recommened +// and wont be supported by this rule +// function alert() {} alert(); +// var alert = function() {}; alert(); +// function foo() { var alert = bar; alert(); } +// function foo(alert) { alert(); } +// var alert = function() {}; function test() { alert(); } +// function foo() { var alert = function() {}; function test() { alert(); } } +// function confirm() {} confirm(); +// function prompt() {} prompt(); +window[alert](); +// function foo() { this.alert(); } +// function foo() { var window = bar; window.alert(); } +// globalThis.alert(); +// globalThis['alert'](); +// globalThis.alert(); +// var globalThis = foo; globalThis.alert(); +// function foo() { var globalThis = foo; globalThis.alert(); } +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md b/content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md new file mode 100644 index 0000000000000..bdf1841a288da --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-async-promise-executor + language: JavaScript + severity: Error +title: Promise executor cannot be an async function +--- +## Metadata +**ID:** `javascript-best-practices/no-async-promise-executor` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +An async Promise executor won't surface exceptions if it fails. If you are already awaiting results in the executor, the Promise itself might not be required; please review your implementation. + +## Non-Compliant Code Examples +```javascript +new Promise(async function foo(resolve, reject) {}) +new Promise(async (resolve, reject) => {}) +``` + +## Compliant Code Examples +```javascript +new Promise((resolve, reject) => {}) +new Promise((resolve, reject) => {}, async function unrelated() {}) +new Foo(async (resolve, reject) => {}) +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-caller.md b/content/en/static_analysis/rules/javascript-best-practices/no-caller.md new file mode 100644 index 0000000000000..c7b9ba4426da9 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-caller.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-best-practices/no-caller + language: JavaScript + severity: Warning +title: Avoid the use of arguments.caller or arguments.callee +--- +## Metadata +**ID:** `javascript-best-practices/no-caller` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +`arguments.caller` and `arguments.callee` has been deprecated and forbidden in ECMAScript 5 strict mode. + +## Non-Compliant Code Examples +```javascript +var x = arguments.callee; +var x = arguments.caller; +``` + +## Compliant Code Examples +```javascript +var x = arguments.length +var x = arguments +var x = arguments[0] +var x = arguments[caller] +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md b/content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md new file mode 100644 index 0000000000000..688c2c6423002 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md @@ -0,0 +1,60 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-case-declarations + language: JavaScript + severity: Warning +title: Avoid lexical declarations in case clauses +--- +## Metadata +**ID:** `javascript-best-practices/no-case-declarations` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Lexical declaration in switch cases are leaked throughout all other cases, which is undesired behavior. Scope your lexical declarations using `{}`. + +## Non-Compliant Code Examples +```javascript +switch (a) { + case 1: + {} + function f() {} + break; +} +switch (a) { + case 1: + case 2: + let x; +} +switch (a) { case 1: let x = 1; break; } +switch (a) { default: let x = 2; break; } +switch (a) { case 1: const x = 1; break; } +switch (a) { default: const x = 2; break; } +switch (a) { case 1: function f() {} break; } +switch (a) { default: function f() {} break; } +switch (a) { case 1: class C {} break; } +switch (a) { default: class C {} break; } +``` + +## Compliant Code Examples +```javascript +switch (a) { case 1: { let x = 1; break; } default: { let x = 2; break; } } +switch (a) { case 1: { const x = 1; break; } default: { const x = 2; break; } } +switch (a) { case 1: { function f() {} break; } default: { function f() {} break; } } +switch (a) { case 1: { class C {} break; } default: { class C {} break; } } +switch (a) { + case 1: + case 2: {} +} +switch (a) { + case 1: var x; +} +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md b/content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md new file mode 100644 index 0000000000000..5db0ee0786c26 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md @@ -0,0 +1,69 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-compare-neg-zero + language: JavaScript + severity: Error +title: Direct comparison with -0 detected +--- +## Metadata +**ID:** `javascript-best-practices/no-compare-neg-zero` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +In JavaScript, `-0` and `+0` are considered to be equal (`(-0 === +0) // true`). However, they behave differently in some operations. For instance, `1/-0` results in `-Infinity`, while `1/+0` results in `+Infinity`. Directly comparing with `-0` can produce results that are hard to understand, and may lead to bugs. + +## Non-Compliant Code Examples +```javascript +x === -0; +-0 === x; +x == -0; +-0 == x; +x > -0; +-0 > x; +x >= -0; +-0 >= x; +x < -0; +-0 < x; +x <= -0; +-0 <= x; +``` + +## Compliant Code Examples +```javascript +x === 0 +0 === x +x == 0 +0 == x +x === '0' +'0' === x +x == '0' +'0' == x +x === '-0' +'-0' === x +x == '-0' +'-0' == x +x === -1 +-1 === x +x < 0 +0 < x +x <= 0 +0 <= x +x > 0 +0 > x +x >= 0 +0 >= x +x != 0 +0 != x +x !== 0 +0 !== x +Object.is(x, -0) +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md b/content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md new file mode 100644 index 0000000000000..d1908d2e3421f --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md @@ -0,0 +1,74 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-cond-assign + language: JavaScript + severity: Error +title: Avoid assignment operators in conditional expressions +--- +## Metadata +**ID:** `javascript-best-practices/no-cond-assign` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +While there might be valid reasons to use an assignment operation in a condition, it is very easy to mistake `=` with the more usual intended `==`. This rule prevents such mistakes, as it is easier to intentionally disable the rule than identify the error. + +## Non-Compliant Code Examples +```javascript +var x; if (x = 0) { var b = 1; } +var x; while (x = 0) { var b = 1; } +var x = 0, y; do { y = x; } while (x = x + 1); +var x; for(; x+=1 ;){}; +var x; if ((x) = (0)); +if (someNode || (someNode = parentNode)) { } +if (someNode || (someNode = parentNode)) { } +while (someNode || (someNode = parentNode)) { } +do { } while (someNode || (someNode = parentNode)); +for (; typeof l === 'undefined' ? (l = 0) : l; i++) { } +if (x = 0) { } +while (x = 0) { } +do { } while (x = x + 1); +for(; x = y; ) { } +var x; var b = (x = 0) ? 1 : 0; +var x; var b = x && (y = 0) ? 1 : 0; +(((3496.29)).bkufyydt = 2e308) ? foo : bar; + + +if ((someNode = someNode.parentNode) !== null) { } +if ((someNode = someNode.parentNode) !== null) { } +if (someNode || (someNode = parentNode)) { } +while (someNode || (someNode = parentNode)) { } +do { } while (someNode || (someNode = parentNode)); +for (;someNode || (someNode = parentNode);); +``` + +## Compliant Code Examples +```javascript +var x = 0; if (x == 0) { var b = 1; } +var x = 0; if (x == 0) { var b = 1; } +var x = 5; while (x < 5) { x = x + 1; } +if ((a = b)); +while ((a = b)); +do {} while ((a = b)); +for (;(a = b);); +for (;;) {} +if ((function(node) { return node = parentNode; })(someNode)) { } +if ((function(node) { return node = parentNode; })(someNode)) { } +if ((node => node = parentNode)(someNode)) { } +if ((node => node = parentNode)(someNode)) { } +if (function(node) { return node = parentNode; }) { } +if (function(node) { return node = parentNode; }) { } +x = 0; +var x; var b = (x === 0) ? 1 : 0; +switch (foo) { case a = b: bar(); } +switch (foo) { case a = b: bar(); } +switch (foo) { case baz + (a = b): bar(); } +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-console.md b/content/en/static_analysis/rules/javascript-best-practices/no-console.md new file mode 100644 index 0000000000000..944a7d8e7981e --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-console.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-console + language: JavaScript + severity: Warning +title: Avoid leaving console debug statements +--- +## Metadata +**ID:** `javascript-best-practices/no-console` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Debugging with `console` is not considered a bad practice, but it's easy to forget about `console` statements and leave them in production code. There is no need to pollute production builds with debugging statements. + +## Non-Compliant Code Examples +```javascript +console.log(foo) +console.error(foo) +console.info(foo) +console.warn(foo) +``` + +## Compliant Code Examples +```javascript +Console.info(foo) +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-debugger.md b/content/en/static_analysis/rules/javascript-best-practices/no-debugger.md new file mode 100644 index 0000000000000..0b4a81ef104c6 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-debugger.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-debugger + language: JavaScript + severity: Error +title: Disallow the use of debugger +--- +## Metadata +**ID:** `javascript-best-practices/no-debugger` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +The `debugger` statement is used to intentionally stop execution and start debugging at the point where the statement appears in the code. While it can be valuable during development and debugging, it can cause unwanted behaviors if it's present in production code. + +## Non-Compliant Code Examples +```javascript +if (foo) debugger +``` + +## Compliant Code Examples +```javascript +var test = { debugger: 1 }; test.debugger; +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md b/content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md new file mode 100644 index 0000000000000..c3286a917ed1f --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-delete-var + language: JavaScript + severity: Error +title: Avoid using delete on variables directly +--- +## Metadata +**ID:** `javascript-best-practices/no-delete-var` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +The `delete` operator is designed to remove properties from objects in JavaScript. When used correctly, it can help manage object properties. However, using the `delete` operator on anything other than object properties can lead to unpredictable behavior. + +## Non-Compliant Code Examples +```javascript +delete x +``` + +## Compliant Code Examples +```javascript +delete x.prop; +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md new file mode 100644 index 0000000000000..0b83288170b2c --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-dupe-args + language: JavaScript + severity: Error +title: Function parameters redeclared +--- +## Metadata +**ID:** `javascript-best-practices/no-dupe-args` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +In JavaScript, it's syntactically valid to define multiple parameters with the same name in a function definition. However, doing so is considered bad practice as the last argument value will override the preceding argument value which can lead to issues that are hard to debug. + +## Non-Compliant Code Examples +```javascript +function a(a, b, b) {} +function a(a, a, a) {} +function a(a, b, a) {} +function a(a, b, a, b) {} +var a = function(a, b, b) {} +var a = function(a, a, a) {} +var a = function(a, b, a) {} +var a = function(a, b, a, b) {} +``` + +## Compliant Code Examples +```javascript +function a(a, b, c){} +var a = function(a, b, c){} +function a({a, b}, {c, d}){} +function a([ , a]) {} +function foo([[a, b], [c, d]]) {} +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md new file mode 100644 index 0000000000000..916091da2846e --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md @@ -0,0 +1,92 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-dupe-class-members + language: JavaScript + severity: Error +title: Avoid duplicate class members +--- +## Metadata +**ID:** `javascript-best-practices/no-dupe-class-members` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +JavaScript allows multiple class members with the same identifier, and the last duplicate class member takes precedence over previous declarations, which is undesired behavior. Disallow duplicate class members. + +## Non-Compliant Code Examples +```javascript +class A { foo() {} foo() {} } +!class A { foo() {} foo() {} }; +class A { 'foo'() {} 'foo'() {} } +class A { 10() {} 1e1() {} } +class A { ['foo']() {} ['foo']() {} } +class A { static ['foo']() {} static foo() {} } +class A { set 'foo'(value) {} set ['foo'](val) {} } +class A { ''() {} ['']() {} } +class A { [`foo`]() {} [`foo`]() {} } +class A { static get [`foo`]() {} static get ['foo']() {} } +class A { foo() {} [`foo`]() {} } +class A { get [`foo`]() {} 'foo'() {} } +class A { static 'foo'() {} static [`foo`]() {} } +class A { ['constructor']() {} ['constructor']() {} } +class A { static [`constructor`]() {} static constructor() {} } +class A { static constructor() {} static 'constructor'() {} } +class A { [123]() {} [123]() {} } +class A { [0x10]() {} 16() {} } +class A { [100]() {} [1e2]() {} } +class A { [123.00]() {} [`123`]() {} } +class A { static '65'() {} static [0o101]() {} } +class A { [123n]() {} 123() {} } +class A { [null]() {} 'null'() {} } +class A { foo() {} foo() {} foo() {} } +class A { static foo() {} static foo() {} } +class A { foo() {} get foo() {} } +class A { set foo(value) {} foo() {} } +class A { foo; foo; } +``` + +## Compliant Code Examples +```javascript +class A { foo() {} bar() {} } +class A { static foo() {} foo() {} } +class A { get foo() {} set foo(value) {} } +class A { static foo() {} get foo() {} set foo(value) {} } +class A { foo() { } } class B { foo() { } } +class A { [foo]() {} foo() {} } +class A { 'foo'() {} 'bar'() {} baz() {} } +class A { *'foo'() {} *'bar'() {} *baz() {} } +class A { get 'foo'() {} get 'bar'() {} get baz() {} } +class A { 1() {} 2() {} } +class A { ['foo']() {} ['bar']() {} } +class A { [`foo`]() {} [`bar`]() {} } +class A { [12]() {} [123]() {} } +class A { [1.0]() {} ['1.0']() {} } +class A { [0x1]() {} [`0x1`]() {} } +class A { [null]() {} ['']() {} } +class A { get ['foo']() {} set ['foo'](value) {} } +class A { ['foo']() {} static ['foo']() {} } + +// computed "constructor" key doesn't create constructor +class A { ['constructor']() {} constructor() {} } +class A { 'constructor'() {} [`constructor`]() {} } +class A { constructor() {} get [`constructor`]() {} } +class A { 'constructor'() {} set ['constructor'](value) {} } + +// not assumed to be statically-known values +class A { ['foo' + '']() {} ['foo']() {} } +class A { [`foo${''}`]() {} [`foo`]() {} } +class A { [-1]() {} ['-1']() {} } + +// private and public +class A { foo; static foo; } +class A { foo; #foo; } +class A { '#foo'; #foo; } +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md new file mode 100644 index 0000000000000..c3465ed5fbda2 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md @@ -0,0 +1,68 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-best-practices/no-dupe-keys + language: JavaScript + severity: Error +title: Avoid duplicate keys in object literals +--- +## Metadata +**ID:** `javascript-best-practices/no-dupe-keys` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +Object literals should not have duplicate keys. If you define an object with duplicate keys, the last one will overwrite any preceding ones. + +## Non-Compliant Code Examples +```javascript +var x = { a: b, ['a']: b }; +var x = { y: 1, y: 2 }; +var x = { '': 1, '': 2 }; +var x = { '': 1, [``]: 2 }; +var foo = { 0x1: 1, 1: 2}; +// should be captured by no-octal +// var x = { 012: 1, 10: 2 }; +var x = { 0b1: 1, 1: 2 }; +var x = { 0o1: 1, 1: 2 }; +var x = { 1n: 1, 1: 2 }; +var x = { 1_0: 1, 10: 2 }; +var x = { "z": 1, z: 2 }; +var foo = { + bar: 1, + bar: 1, + bar() {} +} +var x = { a: 1, get ['a']() {} }; +var x = { a: 1, set a(value) {} }; +var x = { a: 1, b: { a: 2 }, get b() {} }; +var x = ({ '/(?0)/': 1, [/(?0)/]: 2 }) +``` + +## Compliant Code Examples +```javascript +var foo = { __proto__: 1, two: 2}; +var x = { foo: 1, bar: 2 }; +var x = { '': 1, bar: 2 }; +var x = { '': 1, ' ': 2 }; +var x = { '': 1, [null]: 2 }; +var x = { '': 1, [a]: 2 }; +var x = { [a]: 1, [a]: 2 }; ++{ get a() { }, set a(b) { } }; +var x = { a: b, [a]: b }; +var x = { a: b, ...c } +var x = { get a() {}, set a (value) {} }; +var x = { a: 1, b: { a: 2 } }; +var x = ({ null: 1, [/(?0)/]: 2 }) +var {a, a} = obj +// should be captured by no-octal +// var x = { 012: 1, 12: 2 }; +var x = { 1_0: 1, 1: 2 }; +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md b/content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md new file mode 100644 index 0000000000000..2e16df7c4c046 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md @@ -0,0 +1,73 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-duplicate-case + language: JavaScript + severity: Error +title: Avoid duplicate case labels +--- +## Metadata +**ID:** `javascript-best-practices/no-duplicate-case` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +It is easy to copy and paste a switch statement case, and leave behind duplicated test cases. + +## Non-Compliant Code Examples +```javascript +var a = 1; switch (a) {case 1: break; case 1: break; case 2: break; default: break;} +var a = '1'; switch (a) {case '1': break; case '1': break; case '2': break; default: break;} +var a = 1, one = 1; switch (a) {case one: break; case one: break; case 2: break; default: break;} +var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p.p.p1: break; case p.p.p1: break; default: break;} +var a = 1, f = function(b) { return b ? { p1: 1 } : { p1: 2 }; }; switch (a) {case f(true).p1: break; case f(true).p1: break; default: break;} +var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a + 1).p1: break; default: break;} +var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a === 1 ? 2 : 3).p1: break; case f(a === 1 ? 2 : 3).p1: break; default: break;} +var a = 1, f1 = function() { return { p1: 1 } }; switch (a) {case f1().p1: break; case f1().p1: break; default: break;} +var a = [1, 2]; switch(a.toString()){case ([1, 2]).toString():break; case ([1, 2]).toString():break; default:break;} +switch (a) { case a: case a: } +switch (a) { case a: break; case b: break; case a: break; case c: break; case a: break; } +var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a+1).p1: break; default: break;} +// limitations +var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p.p.p1: break; case p. p // comment + .p1: break; default: break;} +var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p .p + /* comment */ + .p1: break; case p.p.p1: break; default: break;} +var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p .p + /* comment */ + .p1: break; case p. p // comment + .p1: break; default: break;} +var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) { + case p.p.p1: break; case p. p // comment + .p1: break; case p .p + /* comment */ + .p1: break; default: break;} +var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f( + a + 1 // comment + ).p1: break; case f(a+1) + .p1: break; default: break;} +``` + +## Compliant Code Examples +```javascript +var a = 1; switch (a) {case 1: break; case 2: break; default: break;} +var a = 1; switch (a) {case 1: break; case '1': break; default: break;} +var a = 1; switch (a) {case 1: break; case true: break; default: break;} +var a = 1; switch (a) {default: break;} +var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p.p.p1: break; case p.p.p2: break; default: break;} +var a = 1, f = function(b) { return b ? { p1: 1 } : { p1: 2 }; }; switch (a) {case f(true).p1: break; case f(true, false).p1: break; default: break;} +var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a + 2).p1: break; default: break;} +var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a == 1 ? 2 : 3).p1: break; case f(a === 1 ? 2 : 3).p1: break; default: break;} +var a = 1, f1 = function() { return { p1: 1 } }, f2 = function() { return { p1: 2 } }; switch (a) {case f1().p1: break; case f2().p1: break; default: break;} +var a = [1,2]; switch(a.toString()){case ([1,2]).toString():break; case ([1]).toString():break; default:break;} +switch(a) { case a: break; } switch(a) { case a: break; } +switch(a) { case toString: break; +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md b/content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md new file mode 100644 index 0000000000000..b0d42b4f8f5ef --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-empty-character-class + language: JavaScript + severity: Error +title: Avoid empty character classes in regular expressions +--- +## Metadata +**ID:** `javascript-best-practices/no-empty-character-class` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +In regular expressions, empty character classes do not match anything, and were likely used in error. + +## Non-Compliant Code Examples +```javascript +var foo = /^abc[]/; +var foo = /foo[]bar/; +if (foo.match(/^abc[]/)) {} +if (/^abc[]/.test(foo)) {} +var foo = /[]]/; +var foo = /\[[]/; +var foo = /\\[\\[\\]a-z[]/; +var foo = /[]]/d; +``` + +## Compliant Code Examples +```javascript +var foo = /^abc[a-zA-Z]/; +var regExp = new RegExp("^abc[]"); +var foo = /^abc/; +var foo = /[\\[]/; +var foo = /[\\]]/; +var foo = /[a-zA-Z\\[]/; +var foo = /[[]/; +var foo = /[\\[a-z[]]/; +var foo = /[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\^\\$\\|]/g; +var foo = /\\s*:\\s*/gim; +var foo = /[\\]]/uy; +var foo = /[\\]]/s; +var foo = /[\\]]/d; +var foo = /\[]/ +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md b/content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md new file mode 100644 index 0000000000000..c7d5f31c8449d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-empty-pattern + language: JavaScript + severity: Error +title: Avoid empty destructuring patterns +--- +## Metadata +**ID:** `javascript-best-practices/no-empty-pattern` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +An empty destructuring pattern doesn't provide any value and might be confusing, as it looks similar to the default assignment. + +## Non-Compliant Code Examples +```javascript +var {} = foo +var [] = foo +var {a: {}} = foo +var {a, b: {}} = foo +var {a: []} = foo +function foo({}) {} +function foo([]) {} +function foo({a: {}}) {} +function foo({a: []}) {} +``` + +## Compliant Code Examples +```javascript +var {a = {}} = foo; +var {a, b = {}} = foo; +var {a = []} = foo; +function foo({a = {}}) {} +function foo({a = []}) {} +var [a] = foo +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-empty.md b/content/en/static_analysis/rules/javascript-best-practices/no-empty.md new file mode 100644 index 0000000000000..cadfdec0c64d6 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-empty.md @@ -0,0 +1,77 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-empty + language: JavaScript + severity: Error +title: Avoid empty block statements +--- +## Metadata +**ID:** `javascript-best-practices/no-empty` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +Empty or non-functional blocks in the code can be misleading and lead to maintenance difficulties. They can also lead to a false sense of security or functionality. While they may not directly introduce security issues, their presence can suggest that some logic or error handling is implemented when it is not. + +## Non-Compliant Code Examples +```javascript +try {} catch (ex) {throw ex} +try { foo() } catch (ex) {} +try { foo() } catch (ex) {throw ex} finally {} +if (foo) {} +while (foo) {} +for (;foo;) {} +switch(foo) {} +switch (foo) { /* empty */ } +try {} catch (ex) {} +try { foo(); } catch (ex) {} finally {} +try {} catch (ex) {} finally {} +try { foo(); } catch (ex) {} finally {} +(function() { }()) +var foo = () => {} +function foo() { } +function foo() { + +} +``` + +## Compliant Code Examples +```javascript +if (foo) { bar() } +while (foo) { bar() } +for (;foo;) { bar() } +try { foo() } catch (ex) { foo() } +switch(foo) {case 'foo': break;} +if (foo) {/* empty */} +while (foo) {/* empty */} +for (;foo;) {/* empty */} +try { foo() } catch (ex) {/* empty */} +try { foo() } catch (ex) {// empty +} +try { foo() } finally {// empty +} +try { foo() } finally {// test +} +try { foo() } finally { + + // hi i am off no use +} +try { foo() } catch (ex) {/* test111 */} +if (foo) { bar() } else { // nothing in me +} +if (foo) { bar() } else { /**/ +} +if (foo) { bar() } else { // +} +function foo() { + const test = {}; +} +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md b/content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md new file mode 100644 index 0000000000000..665f740be514c --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-ex-assign + language: JavaScript + severity: Error +title: Avoid reassigning exceptions in catch clauses +--- +## Metadata +**ID:** `javascript-best-practices/no-ex-assign` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +Catching an exception and assigning a different value to the error parameter will overwrite the reference to the original error data, which will be lost since there is no `arguments` object in a catch clause. + +## Non-Compliant Code Examples +```javascript +try { } catch (e) { e = 10; } +try { } catch (ex) { ex = 10; } +try { } catch (ex) { [ex] = []; } +try { } catch (ex) { ({x: ex = 0} = {}); } +try { } catch ({message}) { message = 10; } +``` + +## Compliant Code Examples +```javascript +try { } catch (e) { three = 2 + 1; } +try { } catch ({e}) { this.something = 2; } +function foo() { try { } catch (e) { return false; } } +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md b/content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md new file mode 100644 index 0000000000000..d48c4a9887afb --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md @@ -0,0 +1,180 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-best-practices/no-implied-eval + language: JavaScript + severity: Warning +title: Prevent the use methods similar to eval() +--- +## Metadata +**ID:** `javascript-best-practices/no-implied-eval` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +JavaScript methods like `setTimeout()`, `setInterval()`, or `execScript()` can accept a string of code as their first argument. This code will be executed at runtime, opening a vector for potential attacks. + +It is generally considered a bad practice to execute code at runtime. This rule considers these methods as implied evaluations when their parameter is a piece of code. + +## Non-Compliant Code Examples +```javascript +setTimeout("x = 1;"); +setTimeout("x = 1;", 100); +setInterval("x = 1;"); +execScript("x = 1;"); +// const s = 'x=1'; setTimeout(s, 100); +setTimeout(String('x=1'), 100); + +// member expressions +window.setTimeout('foo'); +window.setInterval('foo'); +window['setTimeout']('foo'); +window['setInterval']('foo'); +window[`setInterval`]('foo'); +window.window['setInterval']('foo'); +global.setTimeout('foo'); +global.setInterval('foo'); +global['setTimeout']('foo'); +global['setInterval']('foo'); +global[`setInterval`]('foo'); +global.global['setInterval']('foo'); +globalThis.setTimeout('foo'); +globalThis.setInterval('foo'); + +// template literals +setTimeout(`foo${bar}`); +window.setTimeout(`foo${bar}`); +window.window.setTimeout(`foo${bar}`); +global.global.setTimeout(`foo${bar}`); + +// string concatenation +setTimeout('foo' + bar); +setTimeout(foo + 'bar'); +setTimeout(`foo` + bar); +setTimeout(1 + ';' + 1); +window.setTimeout('foo' + bar); +window.setTimeout(foo + 'bar'); +window.setTimeout(`foo` + bar); +window.setTimeout(1 + ';' + 1); +window.window.setTimeout(1 + ';' + 1); +global.setTimeout('foo' + bar); +global.setTimeout(foo + 'bar'); +global.setTimeout(`foo` + bar); +global.setTimeout(1 + ';' + 1); +global.global.setTimeout(1 + ';' + 1); +globalThis.setTimeout('foo' + bar); + +// gives the correct node when dealing with nesting +setTimeout('foo' + (function() { + setTimeout(helper); + execScript('str'); + return 'bar'; +})()); + +window.setTimeout('foo' + (function() { + setTimeout(helper); + window.execScript('str'); + return 'bar'; +})()); + +global.setTimeout('foo' + (function() { + setTimeout(helper); + global.execScript('str'); + return 'bar'; +})()); + +// Optional chaining +window?.setTimeout('code', 0); +(window?.setTimeout)('code', 0); +``` + +## Compliant Code Examples +```javascript +setTimeout(); + +setTimeout; +setTimeout = foo; +window.setTimeout; +window.setTimeout = foo; +window['setTimeout']; +window['setTimeout'] = foo; +global.setTimeout; +global.setTimeout = foo; +global['setTimeout']; +global['setTimeout'] = foo; +globalThis['setTimeout'] = foo; + +window[`SetTimeOut`]('foo', 100); +global[`SetTimeOut`]('foo', 100); +global[`setTimeout${foo}`]('foo', 100); +global[`setTimeout${foo}`]('foo', 100); +globalThis[`setTimeout${foo}`]('foo', 100); + +// normal usage +setTimeout(function() { x = 1; }, 100); +setInterval(function() { x = 1; }, 100) +execScript(function() { x = 1; }, 100) +window.setTimeout(function() { x = 1; }, 100); +window.setInterval(function() { x = 1; }, 100); +window.execScript(function() { x = 1; }, 100); +window.setTimeout(foo, 100); +window.setInterval(foo, 100); +window.execScript(foo, 100); +global.setTimeout(function() { x = 1; }, 100); +global.setInterval(function() { x = 1; }, 100); +global.execScript(function() { x = 1; }, 100); +global.setTimeout(foo, 100); +global.setInterval(foo, 100); +global.execScript(foo, 100); +globalThis.setTimeout(foo, 100); + +// only checks on top-level statements or window.* +foo.setTimeout('hi') + +// identifiers are fine +setTimeout(foo, 10) +setInterval(1, 10) +execScript(2) + +// as are function expressions +setTimeout(function() {}, 10) + +// setInterval +foo.setInterval('hi') +setInterval(foo, 10) +setInterval(function() {}, 10) + +// execScript +foo.execScript('hi') +execScript(foo) +execScript(function() {}) + +// a binary plus on non-strings doesn't guarantee a string +// setTimeout(foo + bar, 10) + +// doesn't check anything but the first argument +setTimeout(foobar, 'buzz') +setTimeout(foobar, foo + 'bar') + +// only checks immediate subtrees of the argument +setTimeout(function() { return 'foobar'; }, 10) + +// https://github.com/eslint/eslint/issues/7821 +setTimeoutFooBar('Foo Bar') + +foo.window.setTimeout('foo', 100); +foo.global.setTimeout('foo', 100); +// var window; window.setTimeout('foo', 100); +// var global; global.setTimeout('foo', 100); +// function foo(window) { window.setTimeout('foo', 100); } +// function foo(global) { global.setTimeout('foo', 100); } +foo('', window.setTimeout); +foo('', global.setTimeout); +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md b/content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md new file mode 100644 index 0000000000000..b101b96c00c7f --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md @@ -0,0 +1,149 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-best-practices/no-import-assign + language: JavaScript + severity: Error +title: Prevent assigning to imported bindings +--- +## Metadata +**ID:** `javascript-best-practices/no-import-assign` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +Imported modules must be immutable. Assignments to the imported bindings are forbidden. + +## Non-Compliant Code Examples +```javascript +import mod1 from 'mod'; mod1 = 0 +import mod2 from 'mod'; mod2 += 0 +import mod3 from 'mod'; mod3++ +import mod4 from 'mod'; for (mod4 in foo); +import mod5 from 'mod'; for (mod5 of foo); +import mod6 from 'mod'; [mod6] = foo +import mod7 from 'mod'; [mod7 = 0] = foo +import mod8 from 'mod'; [...mod8] = foo +import mod9 from 'mod'; ({ bar: mod9 } = foo) +import mod10 from 'mod'; ({ bar: mod10 = 0 } = foo) +import mod11 from 'mod'; ({ ...mod11 } = foo) +import {named1} from 'mod'; named1 = 0 +import {named2} from 'mod'; named2 += 0 +import {named3} from 'mod'; named3++ +import {named4} from 'mod'; for (named4 in foo); +import {named5} from 'mod'; for (named5 of foo); +import {named6} from 'mod'; [named6] = foo +import {named7} from 'mod'; [named7 = 0] = foo +import {named8} from 'mod'; [...named8] = foo +import {named9} from 'mod'; ({ bar: named9 } = foo) +import {named10} from 'mod'; ({ bar: named10 = 0 } = foo) +import {named11} from 'mod'; ({ ...named11 } = foo) +import {named12 as foo} from 'mod'; foo = 0; named12 = 0 +import * as mod1 from 'mod'; mod1 = 0 +import * as mod2 from 'mod'; mod2 += 0 +import * as mod3 from 'mod'; mod3++ +import * as mod4 from 'mod'; for (mod4 in foo); +import * as mod5 from 'mod'; for (mod5 of foo); +import * as mod6 from 'mod'; [mod6] = foo +import * as mod7 from 'mod'; [mod7 = 0] = foo +import * as mod8 from 'mod'; [...mod8] = foo +import * as mod9 from 'mod'; ({ bar: mod9 } = foo) +import * as mod10 from 'mod'; ({ bar: mod10 = 0 } = foo) +import * as mod11 from 'mod'; ({ ...mod11 } = foo) +import * as mod1 from 'mod'; mod1.named = 0 +import * as mod2 from 'mod'; mod2.named += 0 +import * as mod3 from 'mod'; mod3.named++ +import * as mod4 from 'mod'; for (mod4.named in foo); +import * as mod5 from 'mod'; for (mod5.named of foo); +import * as mod6 from 'mod'; [mod6.named] = foo +import * as mod7 from 'mod'; [mod7.named = 0] = foo +import * as mod8 from 'mod'; [...mod8.named] = foo +import * as mod9 from 'mod'; ({ bar: mod9.named } = foo) +import * as mod10 from 'mod'; ({ bar: mod10.named = 0 } = foo) +import * as mod11 from 'mod'; ({ ...mod11.named } = foo) +import * as mod12 from 'mod'; delete mod12.named +import * as mod from 'mod'; Object.assign(mod, obj) +import * as mod from 'mod'; Object.defineProperty(mod, key, d) +import * as mod from 'mod'; Object.defineProperties(mod, d) +import * as mod from 'mod'; Object.setPrototypeOf(mod, proto) +import * as mod from 'mod'; Object.freeze(mod) +import * as mod from 'mod'; Reflect.defineProperty(mod, key, d) +import * as mod from 'mod'; Reflect.deleteProperty(mod, key) +import * as mod from 'mod'; Reflect.set(mod, key, value) +import * as mod from 'mod'; Reflect.setPrototypeOf(mod, proto) +import mod, * as mod_ns from 'mod'; mod.prop = 0; mod_ns.prop = 0 +// Optional chaining +import * as mod from 'mod'; Object?.defineProperty(mod, key, d) +import * as mod from 'mod'; (Object?.defineProperty)(mod, key, d) +import * as mod from 'mod'; delete mod?.prop +``` + +## Compliant Code Examples +```javascript +import mod from 'mod'; mod.prop = 0 +import mod from 'mod'; mod.prop += 0 +import mod from 'mod'; mod.prop++ +import mod from 'mod'; delete mod.prop +import mod from 'mod'; for (mod.prop in foo); +import mod from 'mod'; for (mod.prop of foo); +import mod from 'mod'; [mod.prop] = foo; +import mod from 'mod'; [...mod.prop] = foo; +import mod from 'mod'; ({ bar: mod.prop } = foo); +import mod from 'mod'; ({ ...mod.prop } = foo); +import {named} from 'mod'; named.prop = 0 +import {named} from 'mod'; named.prop += 0 +import {named} from 'mod'; named.prop++ +import {named} from 'mod'; delete named.prop +import {named} from 'mod'; for (named.prop in foo); +import {named} from 'mod'; for (named.prop of foo); +import {named} from 'mod'; [named.prop] = foo; +import {named} from 'mod'; [...named.prop] = foo; +import {named} from 'mod'; ({ bar: named.prop } = foo); +import {named} from 'mod'; ({ ...named.prop } = foo); +import * as mod from 'mod'; mod.named.prop = 0 +import * as mod from 'mod'; mod.named.prop += 0 +import * as mod from 'mod'; mod.named.prop++ +import * as mod from 'mod'; delete mod.named.prop +import * as mod from 'mod'; for (mod.named.prop in foo); +import * as mod from 'mod'; for (mod.named.prop of foo); +import * as mod from 'mod'; [mod.named.prop] = foo; +import * as mod from 'mod'; [...mod.named.prop] = foo; +import * as mod from 'mod'; ({ bar: mod.named.prop } = foo); +import * as mod from 'mod'; ({ ...mod.named.prop } = foo); +import * as mod from 'mod'; obj[mod] = 0 +import * as mod from 'mod'; obj[mod.named] = 0 +import * as mod from 'mod'; for (var foo in mod.named); +import * as mod from 'mod'; for (var foo of mod.named); +import * as mod from 'mod'; [bar = mod.named] = foo; +import * as mod from 'mod'; ({ bar = mod.named } = foo); +import * as mod from 'mod'; ({ bar: baz = mod.named } = foo); +import * as mod from 'mod'; ({ [mod.named]: bar } = foo); +import * as mod from 'mod'; var obj = { ...mod.named }; +import * as mod from 'mod'; var obj = { foo: mod.named }; +// scoped import name re-use not covered +// import mod from 'mod'; { let mod = 0; mod = 1 } +// import * as mod from 'mod'; { let mod = 0; mod = 1 } +// import * as mod from 'mod'; { let mod = 0; mod.named = 1 } +import {} from 'mod' +import 'mod' +import mod from 'mod'; Object.assign(mod, obj); +import {named} from 'mod'; Object.assign(named, obj); +import * as mod from 'mod'; Object.assign(mod.prop, obj); +import * as mod from 'mod'; Object.assign(obj, mod, other); +import * as mod from 'mod'; Object[assign](mod, obj); +import * as mod from 'mod'; Object.getPrototypeOf(mod); +import * as mod from 'mod'; Reflect.set(obj, key, mod); +// Object redeclare not analyzed +// import * as mod from 'mod'; { var Object; Object.assign(mod, obj); } +// import * as mod from 'mod'; var Object; Object.assign(mod, obj); +import * as mod from 'mod'; Object.seal(mod, obj) +import * as mod from 'mod'; Object.preventExtensions(mod) +import * as mod from 'mod'; Reflect.preventExtensions(mod) +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md b/content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md new file mode 100644 index 0000000000000..d677fc08f542c --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md @@ -0,0 +1,71 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-best-practices/no-inner-declarations + language: JavaScript + severity: Warning +title: Avoid variable or function declaration in nested blocks +--- +## Metadata +**ID:** `javascript-best-practices/no-inner-declarations` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Function declarations in JavaScript are generally not block scoped. This rule prevents function declarations inside nested blocks like `if` statements. Move your declarations to the root of your program, body, or class. + +## Non-Compliant Code Examples +```javascript +if (test) { function doSomething() { } } +if (foo) var a; +if (foo) /* some comments */ var a; +if (foo){ function f(){ if(bar){ var a; } } } +if (foo) function f(){ if(bar) var a; } +if (foo) { var fn = function(){} } +if (foo) function f(){} +function bar() { if (foo) var a; } +if (foo){ var a; } +class C { method() { if(test) { var foo; } } } +class C { static { if (test) { function foo() {} } } } +class C { static { if (test) { var foo; } } } +class C { static { if (test) { if (anotherTest) { var foo; } } } } +``` + +## Compliant Code Examples +```javascript +function doSomething() { } +function doSomething() { function somethingElse() { } } +(function() { function doSomething() { } }()); +function decl() { var fn = function expr() { }; } +function decl(arg) { var fn; if (arg) { fn = function() { }; } } +var x = {doSomething() {function doSomethingElse() {}}} +function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } +function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } +if (test) { let x = 1; } +if (test) { const x = 1; } +function doSomething() { while (test) { var foo; } } +var foo; +var foo = 42; +function doSomething() { var foo; } +(function() { var foo; }()); +foo(() => { function bar() { } }); +var fn = () => {var foo;} +var x = {doSomething() {var foo;}} +export var foo; +export function bar() {} +export default function baz() {} +exports.foo = () => {} +exports.foo = function(){} +module.exports = function foo(){} +class C { method() { function foo() {} } } +class C { method() { var x; } } +class C { static { function foo() {} } } +class C { static { var x; } } +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-iterator.md b/content/en/static_analysis/rules/javascript-best-practices/no-iterator.md new file mode 100644 index 0000000000000..8540584e3969d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-iterator.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-best-practices/no-iterator + language: JavaScript + severity: Warning +title: Avoid the use of the __iterator__ property +--- +## Metadata +**ID:** `javascript-best-practices/no-iterator` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +The `__iterator__` property was exclusive to the SpiderMonkey engine. Avoid using it as other JavaScript engines do not implement it. + +## Non-Compliant Code Examples +```javascript +var a = test.__iterator__; +Foo.prototype.__iterator__ = function() {}; +var a = test['__iterator__']; +var a = test[`__iterator__`]; +test[`__iterator__`] = function () {}; +``` + +## Compliant Code Examples +```javascript +var a = test[__iterator__]; +var __iterator__ = null; +foo[`__iterator`] = null; +foo[`__iterator__ +`] = null; +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md b/content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md new file mode 100644 index 0000000000000..951aaa8d803c1 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md @@ -0,0 +1,132 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-loss-of-precision + language: JavaScript + severity: Error +title: Avoid numbers that lose precision +--- +## Metadata +**ID:** `javascript-best-practices/no-loss-of-precision` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +JavaScript uses double-precision, floating-point numbers in accordance with the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754). This means numbers are only accurate until a certain amount of digits. Adding more digits will make the number lose precision, as the added digits will be lost in the conversion to the `Number` type, causing unexpected behavior. + +## Non-Compliant Code Examples +```javascript + +var x = 9007199254740993 +var x = 9007199254740.993e3 +var x = 9.007199254740993e15 +var x = -9007199254740993 +var x = 900719.9254740994 +var x = -900719.9254740994 +var x = 900719925474099_3 +var x = 90_0719925_4740.9_93e3 +var x = 9.0_0719925_474099_3e15 +var x = -9_00719_9254_740993 +var x = 900_719.92_54740_994 +var x = -900_719.92_5474_0994 +var x = 5123000000000000000000000000001 +var x = -5123000000000000000000000000001 +var x = 1230000000000000000000000.0 +var x = 1.0000000000000000000000123var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 +var x = 2e999 +var x = .1230000000000000000000000 +var x = 0b100000000000000000000000000000000000000000000000000001 +var x = 0B100000000000000000000000000000000000000000000000000001 +var x = 0o400000000000000001 +var x = 0O400000000000000001 +var x = 0400000000000000001 +var x = 0x20000000000001 +var x = 0X20000000000001 +var x = 5123_00000000000000000000000000_1 +var x = -5_12300000000000000000000_0000001 +var x = 123_00000000000000000000_00.0_0 +var x = 1.0_00000000000000000_0000123 +var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 +var x = 2e9_99 +var x = .1_23000000000000_00000_0000_0 +var x = 0b1_0000000000000000000000000000000000000000000000000000_1 +var x = 0B10000000000_0000000000000000000000000000_000000000000001 +var x = 0o4_00000000000000_001 +var x = 0O4_0000000000000000_1 +var x = 0x2_0000000000001 +var x = 0X200000_0000000_1 +``` + +## Compliant Code Examples +```javascript +var x = 12345 +var x = 123.456 +var x = -123.456 +var x = -123456 +var x = 123e34 +var x = 123.0e34 +var x = 123e-34 +var x = -123e34 +var x = -123e-34 +var x = 12.3e34 +var x = 12.3e-34 +var x = -12.3e34 +var x = -12.3e-34 +var x = 12300000000000000000000000 +var x = -12300000000000000000000000 +var x = 0.00000000000000000000000123 +var x = -0.00000000000000000000000123 +var x = 9007199254740991 +var x = 0 +var x = 0.0 +var x = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000 +var x = -0 +var x = 123.0000000000000000000000 +var x = 0e5 +var x = 12_34_56 +var x = 12_3.4_56 +var x = -12_3.4_56 +var x = -12_34_56 +var x = 12_3e3_4 +var x = 123.0e3_4 +var x = 12_3e-3_4 +var x = 12_3.0e-3_4 +var x = -1_23e-3_4 +var x = -1_23.8e-3_4 +var x = 1_230000000_00000000_00000_000 +var x = -1_230000000_00000000_00000_000 +var x = 0.0_00_000000000_000000000_00123 +var x = -0.0_00_000000000_000000000_00123 +var x = 0e5_3 + +var x = 0b11111111111111111111111111111111111111111111111111111 +var x = 0b111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 +var x = 0B11111111111111111111111111111111111111111111111111111 +var x = 0B111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 +var x = 0o377777777777777777 +var x = 0o3_77_777_777_777_777_777 +var x = 0O377777777777777777 + +var x = 0377777777777777777 +var x = 0x1FFFFFFFFFFFFF +var x = 0X1FFFFFFFFFFFFF +var x = true +var x = 'abc' +var x = '' +var x = null +var x = undefined +var x = {} +var x = ['a', 'b'] +var x = new Date() +var x = '9007199254740993' + +var x = 0x1FFF_FFFF_FFF_FFF +var x = 0X1_FFF_FFFF_FFF_FFF +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md b/content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md new file mode 100644 index 0000000000000..dbe622c33d93c --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-new-symbol + language: JavaScript + severity: Error +title: Avoid new statements with the Symbol object +--- +## Metadata +**ID:** `javascript-best-practices/no-new-symbol` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +Symbol is intended to be called as a function. Do not instantiate with new statements. + +## Non-Compliant Code Examples +```javascript +var foo = new Symbol('foo'); +function bar() { return function Symbol() {}; } var baz = new Symbol('baz'); +``` + +## Compliant Code Examples +```javascript +var foo = Symbol('foo'); +new foo(Symbol); +new foo(bar, Symbol) +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-octal.md b/content/en/static_analysis/rules/javascript-best-practices/no-octal.md new file mode 100644 index 0000000000000..5620267cd6914 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-octal.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-octal + language: JavaScript + severity: Error +title: Avoid using octal literals to prevent unexpected behavior +--- +## Metadata +**ID:** `javascript-best-practices/no-octal` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +In JavaScript, numbers that start with a leading zero (`0`) are considered octal (base-8) literals. However, octal literals can lead to unintended and unexpected behavior, especially for developers who are not familiar with this notation or when used accidentally. + +## Non-Compliant Code Examples +```javascript +var a = 01234; +a = 1 + 01234; +00; +08; +09.1; +09e1; +09.1e1; +018; +019.1; +019e1; +019.1e1; +``` + +## Compliant Code Examples +```javascript +var a = 'hello world'; +0x1234 +0X5; +a = 0; +0.1 +0.5e1 +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-proto.md b/content/en/static_analysis/rules/javascript-best-practices/no-proto.md new file mode 100644 index 0000000000000..f32be8a06a8c1 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-proto.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-best-practices/no-proto + language: JavaScript + severity: Warning +title: Avoid the use of the __proto__ property +--- +## Metadata +**ID:** `javascript-best-practices/no-proto` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +The `__proto__` property has been deprecated as of ECMAScript 3.1. + +Use a suitable alternative to `__proto__` like `Object.getPrototypeOf` and `Object.setPrototypeOf` instead. + +## Non-Compliant Code Examples +```javascript +var a = test.__proto__; +var a = test['__proto__']; +var a = test[`__proto__`]; +test[`__proto__`] = function () {}; +``` + +## Compliant Code Examples +```javascript +var a = test[__proto__]; +var __proto__ = null; +foo[`__proto`] = null; +foo[`__proto__\n`] = null; +class C { #__proto__; foo() { this.#__proto__; } } +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-script-url.md b/content/en/static_analysis/rules/javascript-best-practices/no-script-url.md new file mode 100644 index 0000000000000..9d1ebe2748950 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-script-url.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-script-url + language: JavaScript + severity: Notice +title: Avoid using JavaScript in URLs +--- +## Metadata +**ID:** `javascript-best-practices/no-script-url` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +JavaScript URLs are evaluated the same way `eval` is executed. This can lead to arbitrary code execution. + +## Non-Compliant Code Examples +```javascript +var a = 'javascript:void(0);'; +var a = 'javascript:'; +var a = `javascript:`; +var a = `JavaScript:`; +``` + +## Compliant Code Examples +```javascript +var a = 'Hello World!'; +var a = 10; +var url = 'xjavascript:' +var url = `xjavascript:` +var url = `${foo}javascript:` +var a = foo`javaScript:`; +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md b/content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md new file mode 100644 index 0000000000000..5aba62c85b514 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-unsafe-negation + language: JavaScript + severity: Warning +title: Avoid negating the left operand of relational operators +--- +## Metadata +**ID:** `javascript-best-practices/no-unsafe-negation` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Negation of the left-hand side of an expression is often unintended. + +## Non-Compliant Code Examples +```javascript +!a in b +(!a in b) +!(a) in b +!a instanceof b +(!a instanceof b) +!(a) instanceof b +``` + +## Compliant Code Examples +```javascript +a in b +a in b === false +!(a in b); +(!a) in b +a instanceof b +a instanceof b === false; +!(a instanceof b); +(!a) instanceof b; + +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-with.md b/content/en/static_analysis/rules/javascript-best-practices/no-with.md new file mode 100644 index 0000000000000..d7279282e4986 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/no-with.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/no-with + language: JavaScript + severity: Error +title: The with statement can lead to ambiguous code +--- +## Metadata +**ID:** `javascript-best-practices/no-with` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +The `with` statement in JavaScript is used to add a given object's properties as variables in a specific block of code. While it may seem convenient, the `with` statement has several pitfalls and can lead to hard-to-diagnose problems. + +## Non-Compliant Code Examples +```javascript +with(foo) { bar() } +``` + +## Compliant Code Examples +```javascript +foo.bar() +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/require-yield.md b/content/en/static_analysis/rules/javascript-best-practices/require-yield.md new file mode 100644 index 0000000000000..bb704297c8fd8 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/require-yield.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/require-yield + language: JavaScript + severity: Error +title: Require yield in generator functions +--- +## Metadata +**ID:** `javascript-best-practices/require-yield` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +Generator functions must yield at some point. Otherwise, use a normal function. + +## Non-Compliant Code Examples +```javascript +function* foo() { return 0; } +(function* foo() { return 0; })(); +var obj = { *foo() { return 0; } } +class A { *foo() { return 0; } } +function* foo() { function* bar() { yield 0; } } +function* foo() { function* bar() { return 0; } yield 0; } +``` + +## Compliant Code Examples +```javascript +function foo() { return 0; } +function* foo() { yield 0; } +function* foo() { } +(function* foo() { yield 0; })(); +(function* foo() { })(); +var obj = { *foo() { yield 0; } }; +var obj = { *foo() { } }; +class A { *foo() { yield 0; } }; +class A { *foo() { } } +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/use-isnan.md b/content/en/static_analysis/rules/javascript-best-practices/use-isnan.md new file mode 100644 index 0000000000000..15f5a3ea6e2f6 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/use-isnan.md @@ -0,0 +1,91 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-best-practices/use-isnan + language: JavaScript + severity: Error +title: Avoid direct comparison with NaN +--- +## Metadata +**ID:** `javascript-best-practices/use-isnan` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +In JavaScript, `NaN` (Not-a-Number) is a unique value that is not equal to anything, including itself. This means any direct comparison with `NaN` using equality (`==`, `===`) or inequality (`!=`, `!==`) operators will always return `false`. + +## Non-Compliant Code Examples +```javascript +123 == NaN; +123 === NaN; +NaN === "abc"; +NaN =="abc"; +123 != NaN; +123 !== NaN; +NaN !== "abc"; +NaN != "abc"; +NaN < "abc"; +"abc" < NaN; +NaN > "abc"; +"abc" > NaN; +NaN <= "abc"; +"abc" <= NaN; +NaN >= "abc"; +"abc" >= NaN; +123 == Number.NaN; +123 === Number.NaN; +Number.NaN === "abc"; +Number.NaN == "abc"; +123 != Number.NaN; +123 !== Number.NaN; +Number.NaN !== "abc"; +Number.NaN != "abc"; +Number.NaN < "abc"; +"abc" < Number.NaN; +Number.NaN > "abc"; +"abc" > Number.NaN; +Number.NaN <= "abc"; +"abc" <= Number.NaN; +Number.NaN >= "abc"; +"abc" >= Number.NaN; +x === Number?.NaN; +x === Number['NaN']; +``` + +## Compliant Code Examples +```javascript +var x = NaN; +isNaN(NaN) === true; +isNaN(123) !== true; +Number.isNaN(NaN) === true; +Number.isNaN(123) !== true; +foo(NaN + 1); +foo(1 + NaN); +foo(NaN - 1) +foo(1 - NaN) +foo(NaN * 2) +foo(2 * NaN) +foo(NaN / 2) +foo(2 / NaN) +var x; if (x = NaN) { } +var x = Number.NaN; +isNaN(Number.NaN) === true; +Number.isNaN(Number.NaN) === true; +foo(Number.NaN + 1); +foo(1 + Number.NaN); +foo(Number.NaN - 1) +foo(1 - Number.NaN) +foo(Number.NaN * 2) +foo(2 * Number.NaN) +foo(Number.NaN / 2) +foo(2 / Number.NaN) +var x; if (x = Number.NaN) { } +x === Number[NaN]; +``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md b/content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md new file mode 100644 index 0000000000000..5c6294c946507 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md @@ -0,0 +1,87 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-best-practices/valid-typeof + language: JavaScript + severity: Warning +title: Compare typeof expressions against valid strings +--- +## Metadata +**ID:** `javascript-best-practices/valid-typeof` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Always compare typeof expressions against strings and make sure they are the correct values. + +## Non-Compliant Code Examples +```javascript +typeof foo === 'strnig'; +'strnig' === typeof foo; +if (typeof bar === 'umdefined') {}; +typeof foo !== 'strnig'; +'strnig' !== typeof foo; +if (typeof bar !== 'umdefined') {}; +typeof foo != 'strnig'; +'strnig' != typeof foo; +if (typeof bar != 'umdefined') {}; +typeof foo == 'strnig'; +'strnig' == typeof foo; +if (typeof bar == 'umdefined') {}; +if (typeof bar === `umdefined`) {}; +typeof foo == 'invalid string'; +if (typeof bar !== undefined) {}; +typeof foo == Object; +typeof foo == {}; +typeof foo === undefined; +undefined === typeof foo; +undefined == typeof foo; +typeof foo === `undefined${foo}`; +typeof foo === `${string}`; +``` + +## Compliant Code Examples +```javascript +typeof foo === 'string'; +typeof foo === 'object'; +typeof foo === 'function'; +typeof foo === 'undefined'; +typeof foo === 'boolean'; +typeof foo === 'number'; +typeof foo === 'bigint'; +'string' === typeof foo; +'object' === typeof foo; +'function' === typeof foo; +'undefined' === typeof foo; +'boolean' === typeof foo; +'number' === typeof foo; +typeof foo === typeof bar; +typeof foo === baz; +typeof foo !== someType; +typeof bar != someType; +someType === typeof bar; +someType == typeof bar; +typeof foo == 'string'; +typeof(foo) === 'string'; +typeof(foo) !== 'string'; +typeof(foo) == 'string'; +typeof(foo) != 'string'; +var oddUse = typeof foo + 'thing'; +// since we don't have optios we are enforcing to always compare agaisnt strings +// function f(undefined) { typeof x === undefined }; +typeof foo === 'number'; +typeof foo === "number"; +var baz = typeof foo + 'thing'; +typeof foo === typeof bar; +typeof foo === `string`; +`object` === typeof foo; +// not supported by this rule, we cannot pretend that somethingElse will complete 'string' +// typeof foo === `str${somethingElse}`; +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md b/content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md new file mode 100644 index 0000000000000..ff558ab857aea --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/event-check-origin + language: JavaScript + severity: Warning +title: Check origin of events +--- +## Metadata +**ID:** `javascript-browser-security/event-check-origin` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Not checking the rule origin can lead to XSS attacks. Always check the event origin. + +#### Learn More + + - [XSS and CSS Cheat Sheet from OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) + +## Non-Compliant Code Examples +```javascript +window.addEventListener('message', (event) => { + processing(); +}) +``` + +## Compliant Code Examples +```javascript +window.addEventListener('message', (event) => { + if (event.origin != 'https://app.domain.tld') { + throw new Error('invalid origin') + } + + processing(); +}) +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md b/content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md new file mode 100644 index 0000000000000..5959b63447f71 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md @@ -0,0 +1,81 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/inner-outer-html + language: JavaScript + severity: Warning +title: Do not modify innerHTML or outerHTML +--- +## Metadata +**ID:** `javascript-browser-security/inner-outer-html` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Properties like `innerHTML` and `outerHTML` should not be modified directly unless such modifications are clearly reviewed. Modifying `innerHTML` or `outerHTML` using user inputs that has not been validated can lead to XSS injection. + +#### Learn More + + - [Why InnerHTML Is a Bad Idea and How to Avoid It?](https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/) + - [CWE-79 - Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) + + +## Non-Compliant Code Examples +```javascript +function nonCompliant(argument) { + const content = '
' + argument + '
'; + document.write(content); +} +``` + +```javascript +function nonCompliant(myArgument) { + document.body.outerHTML = myArgument; +} +``` + +```javascript +if (typeof(SERVER_DOMAIN) === 'undefined') { + window.location.replace("/unconfigured.html"); +} + +const RECEIVE_URL = SERVER_DOMAIN + "/challenge_scoreboard.html" + "?origin=" + get_domain(); + +var window_ref = null; + +document.getElementById("username").focus(); + +function store_username() { + var username; + var username_obj; + + username_obj = document.getElementById("username"); + username = username_obj.value + + var welcome; + welcome = document.getElementById("welcome"); + welcome.innerHTML = "Welcome " + html_encode (username); + + var set_username; + set_username = document.getElementById("set_username"); + set_username.style.display="none"; + + var game; + game = document.getElementById("game"); + game.style.display="inline"; + + start_game(); + // have to do time out so the window can open + setTimeout (function () {send_username(username);}, 1000); + + return false; +} + +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md b/content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md new file mode 100644 index 0000000000000..36d4f3e1ceaa2 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/insecure-websocket + language: JavaScript + severity: Warning +title: Websockets must use SSL connections +--- +## Metadata +**ID:** `javascript-browser-security/insecure-websocket` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always use secure websocket communication. When using websocket, use addresses that are SSL-enabled. + + + +## Non-Compliant Code Examples +```javascript +const client = new WebSocket('ws://app.domain.tld') +``` + +## Compliant Code Examples +```javascript +const client = new WebSocket('wss://app.domain.tld') +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md b/content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md new file mode 100644 index 0000000000000..a3a2dc2bcf012 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/local-storage-sensitive-data + language: JavaScript + severity: Warning +title: Do not store sensitive data to local storage +--- +## Metadata +**ID:** `javascript-browser-security/local-storage-sensitive-data` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not store sensitive data in `localStorage` and keep the data safe from any malicious software that could read this data. + +#### Learn More + - [CWE-312 - Cleartext Storage of Sensitive Information](https://cwe.mitre.org/data/definitions/312.html) + +## Non-Compliant Code Examples +```javascript +localStorage.setItem('user', email) + +localStorage.setItem('user', user.email) +``` + +## Compliant Code Examples +```javascript +localStorage.setItem('user', uuid) + +localStorage.setItem('user', user.id) +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md b/content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md new file mode 100644 index 0000000000000..311afe79206d1 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/manual-sanitization + language: JavaScript + severity: Warning +title: Avoid manual sanitization of inputs +--- +## Metadata +**ID:** `javascript-browser-security/manual-sanitization` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Never sanitize HTML input manually. It can lead to vulnerabilities. Use dedicated modules such as `sanitize-html` to sanitize user inputs. + +## Non-Compliant Code Examples +```javascript +const sanitizedInput = input + .replaceAll('<', '<') + .replaceAll('>', '>'); +const html = `${sanitizedInput}`; + +const sanitizedInput2 = input + .replaceAll('bla', '<') + .replaceAll('foo', '>'); + +const sanitizedInput3 = input + .replaceAll('<', '<') + .replaceAll('>', 'gt;'); +``` + +## Compliant Code Examples +```javascript +import sanitizeHtml from 'sanitize-html'; + +const html = sanitizeHtml(`${input}`); +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md b/content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md new file mode 100644 index 0000000000000..39b24dcdc08a5 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/postmessage-permissive-origin + language: JavaScript + severity: Warning +title: Specify origin in postMessage +--- +## Metadata +**ID:** `javascript-browser-security/postmessage-permissive-origin` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always specify the origin of the message for security reasons and to avoid spoofing attacks. Always specify an exact target origin, not `*`, when you use `postMessage` to send data to other windows. + +#### Learn More + + - [window.postMessage documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) + +## Non-Compliant Code Examples +```javascript +window.postMessage(message, '*') + +``` + +## Compliant Code Examples +```javascript +window.postMessage(message, 'https://app.domain.tld') + +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md b/content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md new file mode 100644 index 0000000000000..0f96150da260f --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/react-dangerously-inner-html + language: JavaScript + severity: Warning +title: Do not inject unsanitized HTML +--- +## Metadata +**ID:** `javascript-browser-security/react-dangerously-inner-html` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always sanitize HTML data before injecting it in the DOM. Use libraries such as [DOMPurify](https://github.com/cure53/DOMPurify) before using it. + +## Non-Compliant Code Examples +```javascript +const App = () => { + const data = `lorem ipsum`; + + return ( +
+
+ ); +} +``` + +## Compliant Code Examples +```javascript +const App = () => { + const data = `lorem ipsum`; + + return ( +
+ ); +} +``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md b/content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md new file mode 100644 index 0000000000000..f36debd7d319d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-browser-security/regexp-non-literal + language: JavaScript + severity: Warning +title: Do not use variable for regular expressions +--- +## Metadata +**ID:** `javascript-browser-security/regexp-non-literal` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Regular expressions should not use a variable as an argument since an attacker may inject values and cause a regular expression denial of service (ReDoS). Instead, use a library like [recheck](https://www.npmjs.com/package/recheck) to check that no ReDoS can be triggered by a regular expression. + +## Non-Compliant Code Examples +```javascript +const foo = new RegExp(req.something); +const bar = new RegExp(variable); +``` + +## Compliant Code Examples +```javascript +const foo = new RegExp(`^\\d+-${topicId}$`); +const foo = new RegExp(/something/); +const foo = new RegExp("weofiwje"); +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/assignment-name.md b/content/en/static_analysis/rules/javascript-code-style/assignment-name.md new file mode 100644 index 0000000000000..d54a7156594d3 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/assignment-name.md @@ -0,0 +1,95 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/assignment-name + language: JavaScript + severity: Notice +title: Assigment name should use camelCase +--- +## Metadata +**ID:** `javascript-code-style/assignment-name` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that variables and properties names use `camelCase` and not `snake_case` or `PascalCase`. + +## Non-Compliant Code Examples +```javascript +var a = { + MyProp: "should be camelCase", + foo_bar: 0, + #Priv: 2, +}; +const my_var = {}; +let FooBar = {}; +const { a_b, ...Bla } = c; +const [a_b, ...Bla] = c; + +``` + +## Compliant Code Examples +```javascript +/* The BenefitsDAO must be constructed with a connected database object */ +function BenefitsDAO(db) { + + "use strict"; + + /* If this constructor is called without the "new" operator, "this" points + * to the global object. Log a warning and call it correctly. */ + if (false === (this instanceof BenefitsDAO)) { + console.log("Warning: BenefitsDAO constructor called without 'new' operator"); + return new BenefitsDAO(db); + } + + const usersCol = db.collection("users"); + const Users = db.collections("something"); + + this.getAllNonAdminUsers = callback => { + usersCol.find({ + "isAdmin": { + $ne: true + } + }).toArray((err, users) => callback(null, users)); + }; + + this.updateBenefits = (userId, startDate, callback) => { + usersCol.update({ + _id: parseInt(userId) + }, { + $set: { + benefitStartDate: startDate + } + }, + (err, result) => { + if (!err) { + console.log("Updated benefits"); + return callback(null, result); + } + + return callback(err, null); + } + ); + }; +} + +module.exports = { BenefitsDAO }; +``` + +```javascript +const a = { myProp: "", #priv: 1 }; +const myVar = {}; +const { a } = c; +const { a, ...b } = c; +const [a, ...b] = c; +process.env.PCKG_OS_NAME; +const md5 = 'foo'; +const PCKG_OS_NAME = 'foo'; +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/class-name.md b/content/en/static_analysis/rules/javascript-code-style/class-name.md new file mode 100644 index 0000000000000..8ed7ee6a7e4fe --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/class-name.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/class-name + language: JavaScript + severity: Warning +title: Class name should be PascalCase +--- +## Metadata +**ID:** `javascript-code-style/class-name` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Code Style + +## Description +Class names should be `PascalCase` and not `camelCase` or `snake_case`. + +## Non-Compliant Code Examples +```javascript +class _runtimeMetricsStatus {} +class runtimeMetricsStatus {} +``` + +## Compliant Code Examples +```javascript +class MyClass {} +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/eqeqeq.md b/content/en/static_analysis/rules/javascript-code-style/eqeqeq.md new file mode 100644 index 0000000000000..c6117f669cccb --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/eqeqeq.md @@ -0,0 +1,85 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/eqeqeq + language: JavaScript + severity: Notice +title: Enforce the use of === and !== +--- +## Metadata +**ID:** `javascript-code-style/eqeqeq` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +In JavaScript, `==` and `!=` comparisons do type coercion, which can be confusing and may introduce potential errors. Use the type-safe equality operators `===` and `!==` instead. + +## Non-Compliant Code Examples +```javascript +a == b +a != b +typeof a == 'number' +typeof a == 'number' +'string' != typeof a +true == true +2 == 3 +2 == 3 +'hello' != 'world' +'hello' != 'world' +a == null +a == null +null != a +true == 1 +0 != '1' +'wee' == /wee/ +typeof a == 'number' +'string' != typeof a +'hello' != 'world' +2 == 3 +true == true +true == null +true != null +null == null +null != null +a +== +b +(a) == b +(a) != b +a == (b) +a != (b) +(a) == (b) +(a == b) == (c) +(a != b) != (c) +a == b; +a!=b; +(a + b) == c; +(a + b) != c; +((1) ) == (2); + +``` + +## Compliant Code Examples +```javascript +a === b +a !== b +a === b +a !== null +a === null +a !== null +null === null +null !== null + +// https://github.com/eslint/eslint/issues/8020 +foo === /abc/u + +// bigint +foo === 1n +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/func-name-matching.md b/content/en/static_analysis/rules/javascript-code-style/func-name-matching.md new file mode 100644 index 0000000000000..2220769b4197d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/func-name-matching.md @@ -0,0 +1,195 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/func-name-matching + language: JavaScript + severity: Notice +title: Function names must match the name of the assignation. +--- +## Metadata +**ID:** `javascript-code-style/func-name-matching` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Use the same name between your function declaration and the variable or property to which it is assigned. + +## Non-Compliant Code Examples +```javascript +let foo = function bar() {}; +let foo = function bar() {}; +foo = function bar() {}; +foo &&= function bar() {}; +obj.foo ||= function bar() {}; +obj['foo'] ??= function bar() {}; +obj.foo = function bar() {}; +obj.bar.foo = function bar() {}; +obj['foo'] = function bar() {}; +let obj = {foo: function bar() {}}; +let obj = {'foo': function bar() {}}; +({['foo']: function bar() {}}); +// NOT SUPPORTED +// module.exports = function foo(name) {}; +// module.exports = function foo(name) {}; +// module.exports = function exports(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function exports(name) {}; +// Object.defineProperty(foo, 'bar', { value: function baz() {} }); +// Object.defineProperties(foo, { bar: { value: function baz() {} } }); +// Object.create(proto, { bar: { value: function baz() {} } }); +// var obj = { value: function foo(name) {} }; +// Object.defineProperty(foo, 'bar', { value: function bar() {} }); +// Object.defineProperties(foo, { bar: { value: function bar() {} } }); +// Object.create(proto, { bar: { value: function bar() {} } }); +// Reflect.defineProperty(foo, 'bar', { value: function baz() {} }); +// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }); +foo({ value: function bar() {} }); +(obj?.aaa).foo = function bar() {}; +// Object?.defineProperty(foo, 'bar', { value: function baz() {} }); +// (Object?.defineProperty)(foo, 'bar', { value: function baz() {} }); +// Object?.defineProperty(foo, 'bar', { value: function bar() {} }); +// (Object?.defineProperty)(foo, 'bar', { value: function bar() {} }); +// Object?.defineProperties(foo, { bar: { value: function baz() {} } }); +// (Object?.defineProperties)(foo, { bar: { value: function baz() {} } }); +// Object?.defineProperties(foo, { bar: { value: function bar() {} } }); +// (Object?.defineProperties)(foo, { bar: { value: function bar() {} } }); +class C { x = function y() {}; } +class C { 'x' = function y() {}; } +class C { ['x'] = function y() {}; } +class C { static x = function y() {}; } +(class { x = function y() {}; }) +var obj = { '\u1885': function foo() {} }; + +``` + +## Compliant Code Examples +```javascript +var foo; +var foo = function foo() {}; +var foo = function foo() {}; +var foo = function() {} +var foo = () => {} +foo = function foo() {}; +foo = function foo() {}; +foo &&= function foo() {}; +obj.foo ||= function foo() {}; +obj['foo'] ??= function foo() {}; +obj.foo = function foo() {}; +obj.foo = function foo() {}; +obj.foo = function() {}; +obj.foo = function() {}; +obj.bar.foo = function foo() {}; +obj.bar.foo = function foo() {}; +obj['foo'] = function foo() {}; +obj['foo'] = function foo() {}; +// This are not equal not sure why eslint skips them +// obj['foo//bar'] = function foo() {}; +// obj['foo//bar'] = function foo() {}; +// obj['foo//bar'] = function foo() {}; +obj[foo] = function bar() {}; +obj[foo] = function bar() {}; +var obj = {foo: function foo() {}}; +var obj = {foo: function foo() {}}; +var obj = {'foo': function foo() {}}; +var obj = {'foo': function foo() {}}; +var obj = {foo: function() {}}; +var obj = {foo: function() {}}; +var obj = {foo: function() {}}; +var obj = {[foo]: function bar() {}} +var obj = {['x' + 2]: function bar() {}}; +obj['x' + 2] = function bar(){}; +var [ bar ] = [ function bar(){} ]; +function a(foo = function bar() {}) {} +// NOT SUPPORTED +// module.exports = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module.exports = function foo(name) {}; +// module.exports = function foo(name) {}; +// module.exports = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function foo(name) {}; +({['foo']: function foo() {}}) +({['foo']: function foo() {}}) +({[foo]: function bar() {}}) +({[null]: function foo() {}}) +({[1]: function foo() {}}) +({[true]: function foo() {}}) +({[`x`]: function foo() {}}) +({[/abc/]: function foo() {}}) +({[[1, 2, 3]]: function foo() {}}) +({[{x: 1}]: function foo() {}}) +[] = function foo() {} +({} = function foo() {}) +[a] = function foo() {} +({a} = function foo() {}) +var [] = function foo() {} +var {} = function foo() {} +var [a] = function foo() {} +var {a} = function foo() {} +({ value: function value() {} }) +obj.foo = function foo() {}; +obj.bar.foo = function foo() {}; +var obj = {foo: function foo() {}}; +var obj = {foo: function() {}}; +var obj = { value: function value() {} } +// NOT SUPPORTED +// Object.defineProperty(foo, 'bar', { value: function bar() {} }) +// Object.defineProperties(foo, { bar: { value: function bar() {} } }) +// Object.create(proto, { bar: { value: function bar() {} } }) +// Object.defineProperty(foo, 'b' + 'ar', { value: function bar() {} }) +// Object.defineProperties(foo, { ['bar']: { value: function bar() {} } }) +// Object.create(proto, { ['bar']: { value: function bar() {} } }) +// Object.defineProperty(foo, 'bar', { value() {} }) +// Object.defineProperties(foo, { bar: { value() {} } }) +// Object.create(proto, { bar: { value() {} } }) +// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }) +// Reflect.defineProperty(foo, 'b' + 'ar', { value: function baz() {} }) +// Reflect.defineProperty(foo, 'bar', { value() {} }) +foo({ value: function value() {} }) +class C { x = function () {}; } +class C { x = function () {}; } +class C { 'x' = function () {}; } +class C { #x = function () {}; } +class C { #x = function () {}; } +class C { [x] = function () {}; } +class C { [x] = function () {}; } +class C { ['x'] = function () {}; } +class C { x = function x() {}; } +class C { 'x' = function x() {}; } +class C { #x = function x() {}; } +class C { #x = function x() {}; } +class C { #x = function y() {}; } +class C { #x = function y() {}; } +class C { [x] = function x() {}; } +class C { [x] = function x() {}; } +class C { [x] = function y() {}; } +class C { [x] = function y() {}; } +class C { ['x'] = function x() {}; } +class C { 1 = function x0() {}; } +class C { 1 = function x1() {}; } +class C { [1] = function x0() {}; } +class C { [1] = function x1() {}; } +class C { [f()] = function g() {}; } +class C { [f()] = function f() {}; } +class C { static x = function x() {}; } +class C { x = (function y() {})(); } +class C { x = (function x() {})(); } +(class { x = function x() {}; }) +class C { #x; foo() { this.#x = function x() {}; } } +class C { #x; foo() { this.#x = function x() {}; } } +class C { #x; foo() { this.#x = function y() {}; } } +class C { #x; foo() { this.#x = function y() {}; } } +class C { #x; foo() { a.b.#x = function x() {}; } } +class C { #x; foo() { a.b.#x = function x() {}; } } +class C { #x; foo() { a.b.#x = function y() {}; } } +class C { #x; foo() { a.b.#x = function y() {}; } } +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/func-names.md b/content/en/static_analysis/rules/javascript-code-style/func-names.md new file mode 100644 index 0000000000000..56d7921ad23e4 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/func-names.md @@ -0,0 +1,96 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/func-names + language: JavaScript + severity: Notice +title: Enforce named function expressions +--- +## Metadata +**ID:** `javascript-code-style/func-names` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +It is easier to debug your application code when you avoid anonymous functions so that the stack trace can show you meaningful error messages. This rule enforces all your function to be consistently declared with a name. + +## Non-Compliant Code Examples +```javascript +Foo.prototype.bar = function() {}; +(function(){}()) +f(function(){}) +var a = new Date(function() {}); +var test = function(d, e, f) {}; +new function() {} +Foo.prototype.bar = function() {}; +(function(){}()) +f(function(){}) +var a = new Date(function() {}); +new function() {} +var {foo} = function(){}; +({ a: obj.prop = function(){} } = foo); +[obj.prop = function(){}] = foo; +var { a: [b] = function(){} } = foo; +function foo({ a } = function(){}) {}; +export default function() {} +export default function() {} +export default (function(){}); +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +(function*() {}()) +var foo = bar(function *() {}); +(function*() {}()) +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +class C { foo = function() {} } +class C { [foo] = function() {} } +class C { #foo = function() {} } +``` + +## Compliant Code Examples +```javascript +Foo.prototype.bar = function bar(){}; +Foo.prototype.bar = () => {}; +function foo(){} +function test(d, e, f) {} +new function bar(){} +exports = { get foo() { return 1; }, set bar(val) { return val; } }; +({ foo() { return 1; } }); +class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} +function foo() {} +var a = function foo() {}; +class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} +({ foo() {} }); +function foo() {} +var a = function foo() { foo(); }; +class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} +({ foo() {} }); +export default function foo() {} +export default function foo() {} +export default function foo() {} +var foo = bar(function *baz() {}); +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/function-naming.md b/content/en/static_analysis/rules/javascript-code-style/function-naming.md new file mode 100644 index 0000000000000..3393ff12736c7 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/function-naming.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/function-naming + language: JavaScript + severity: Notice +title: Function name should use camelCase or PascalCase +--- +## Metadata +**ID:** `javascript-code-style/function-naming` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that the function uses `camelCase` or `PascalCase` in case it is an `Object`. Generator functions should always be `camelCase`. + +## Non-Compliant Code Examples +```javascript +function My_Class() {} +function get_value() {} +function* GetValue() {} +function *get_value() {} +``` + +## Compliant Code Examples +```javascript +function MyClass() {} +function getValue() {} +function* getValue() {} +function *getValue() {} +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/max-class-lines.md b/content/en/static_analysis/rules/javascript-code-style/max-class-lines.md new file mode 100644 index 0000000000000..ce6be6365666d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/max-class-lines.md @@ -0,0 +1,258 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/max-class-lines + language: JavaScript + severity: Warning +title: Classes must be less than 100 lines +--- +## Metadata +**ID:** `javascript-code-style/max-class-lines` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Code Style + +## Description +A class must stay short (less than 100 lines) to be easy to understand. If your class or function is more than 100 lines, you should refactor your code and ensure that your class is less than 100 lines. + +## Non-Compliant Code Examples +```javascript +class DummyClass { + constructor() { + this.name = "John"; + this.age = 30; + this.email = "john@example.com"; + this.address = "123 Main St"; + this.phone = "555-1234"; + this.salary = 50000; + this.skills = ["JavaScript", "HTML", "CSS"]; + this.projects = [ + { name: "Project 1", duration: 6 }, + { name: "Project 2", duration: 4 }, + { name: "Project 3", duration: 8 } + ]; + this.status = "active"; + + // Initialize more properties... + // ... + // ... + } + + sayHello() { + console.log(`Hello, my name is ${this.name}.`); + } + + calculateSalary() { + let total = this.salary; + for (let project of this.projects) { + total += project.duration * 1000; + } + return total; + } + + updateEmail(newEmail) { + if (newEmail.includes("@")) { + this.email = newEmail; + console.log("Email updated successfully."); + } else { + console.log("Invalid email format."); + } + } + + addSkill(skill) { + this.skills.push(skill); + console.log("Skill added."); + } + + removeSkill(skill) { + const index = this.skills.indexOf(skill); + if (index !== -1) { + this.skills.splice(index, 1); + console.log("Skill removed."); + } else { + console.log("Skill not found."); + } + } + + promote() { + if (this.status === "active") { + this.salary *= 1.1; + console.log("Promoted successfully."); + } else { + console.log("Cannot promote an inactive employee."); + } + } + + resign() { + if (this.status === "active") { + this.status = "inactive"; + console.log("Resigned successfully."); + } else { + console.log("Already inactive."); + } + } + + // More methods... + // ... + // ... + + // Long method 1 + longMethod1() { + // Implementation goes here... + // ... + // ... + } + + // Long method 2 + longMethod2() { + // Implementation goes here... + // ... + // ... + } + + // Long method 3 + longMethod3() { + // Implementation goes here... + // ... + // ... + } + + // Long method 4 + longMethod4() { + // Implementation goes here... + // ... + // ... + } + + // Long method 5 + longMethod5() { + // Implementation goes here... + // ... + // ... + } + + // More long methods... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final method + finalMethod() { + // Implementation goes here... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + } +} + +``` + +## Compliant Code Examples +```javascript +class DummyClass { + constructor() { + this.name = "John"; + this.age = 30; + this.email = "john@example.com"; + this.address = "123 Main St"; + this.phone = "555-1234"; + this.salary = 50000; + this.skills = ["JavaScript", "HTML", "CSS"]; + this.projects = [ + { name: "Project 1", duration: 6 }, + { name: "Project 2", duration: 4 }, + { name: "Project 3", duration: 8 } + ]; + this.status = "active"; + } + + sayHello() { + console.log(`Hello, my name is ${this.name}.`); + } + + calculateSalary() { + let total = this.salary; + for (let project of this.projects) { + total += project.duration * 1000; + } + return total; + } +} + +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/max-function-lines.md b/content/en/static_analysis/rules/javascript-code-style/max-function-lines.md new file mode 100644 index 0000000000000..bdbd3a71d5fb0 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/max-function-lines.md @@ -0,0 +1,952 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/max-function-lines + language: JavaScript + severity: Warning +title: Functions must be less than 200 lines +--- +## Metadata +**ID:** `javascript-code-style/max-function-lines` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Code Style + +## Description +This rule ensures that a function is not too long. A function should be less than 200 lines, or it will be hard to understand. + +## Non-Compliant Code Examples +```javascript +function dummyFunction() { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; +} + +() => { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; +} + +const dummyFunction = function() { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; +} + +class A { + dummyFunction() { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; + } +} +``` + +## Compliant Code Examples +```javascript +function myTest() { + // less than 200 lines +} + +() => { + // less than 200 lines +} + +class A { + foo() { + // less than 200 lines + } +} +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/max-params.md b/content/en/static_analysis/rules/javascript-code-style/max-params.md new file mode 100644 index 0000000000000..cb1b6eeefb1d9 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/max-params.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/max-params + language: JavaScript + severity: Notice +title: Enforce a maximum number of parameters in a function +--- +## Metadata +**ID:** `javascript-code-style/max-params` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Having too many parameters can make your code hard to read. The parameters must be used in appropriate order. Forgetting the order of parameters can cause mistakes. + +Too many parameters is a code smell. You should refactor your code in smaller reusable bits. While it may be valid to require more than four parameters, you should use object destructuring. + +## Non-Compliant Code Examples +```javascript +function test(a, b, c, d) {} +var test = function(a, b, c, d, e) {}; +var test = (a, b, c, d) => {}; +(function(a, b, c, d) {}); + +// object property options +function test(a, b, c, d) {} +``` + +## Compliant Code Examples +```javascript +function test(d, e, f) {} +var test = function(a, b, c) {}; +var test = (a, b, c) => {}; +var test = function test(a, b, c) {}; + +// object property options +var test = function(a, b, c) {}; +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/method-name.md b/content/en/static_analysis/rules/javascript-code-style/method-name.md new file mode 100644 index 0000000000000..796934c2f46a4 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/method-name.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/method-name + language: JavaScript + severity: Notice +title: Method name should use camelCase +--- +## Metadata +**ID:** `javascript-code-style/method-name` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that method names use `camelCase` and not `snake_case` or `PascalCase`. + +## Non-Compliant Code Examples +```javascript +const a = { GetValue() {} } +class A { set_value() {} } +class A { *set_value() {} } +class A { #set_value() {} } +class A { #SetValue() {} } +``` + +## Compliant Code Examples +```javascript +const a = { getValue() {} } +class A { setValue() {} } +class A { #fooBla() {} } +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md b/content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md new file mode 100644 index 0000000000000..3339c7f635a70 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-code-style/no-array-constructor + language: JavaScript + severity: Warning +title: Avoid Array constructors +--- +## Metadata +**ID:** `javascript-code-style/no-array-constructor` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Array literal notation cannot be redefined. It is preferred over the Array constructor. + +The Array constructor is a common source of errors as it might behave unexpectedly when used with a single parameter. It creates an array with of N length instead of initializing an Array with the provided param. + + +## Non-Compliant Code Examples +```javascript +new Array(); +new Array; +new Array(x, y); +new Array(0, 1, 2); +``` + +## Compliant Code Examples +```javascript +new Array(x) +Array(x) +new Array(9) +Array(9) +new foo.Array() +foo.Array() +new Array.foo +Array.foo() +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-div-regex.md b/content/en/static_analysis/rules/javascript-code-style/no-div-regex.md new file mode 100644 index 0000000000000..27a9f99f26386 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-div-regex.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-code-style/no-div-regex + language: JavaScript + severity: Notice +title: Avoid equal signs at the beginning of regular expressions +--- +## Metadata +**ID:** `javascript-code-style/no-div-regex` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Error Prone + +## Description +At the start of a regular expression literal, the characters `/=` can be mistaken for a division assignment operator. + +## Non-Compliant Code Examples +```javascript +var f = function() { return /=foo/; }; +``` + +## Compliant Code Examples +```javascript +var f = function() { return /foo/ig.test('bar'); }; +var f = function() { return /\\=foo/; }; +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md b/content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md new file mode 100644 index 0000000000000..4c85eb60df2fa --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/no-duplicate-imports + language: JavaScript + severity: Warning +title: Avoid duplicate module imports +--- +## Metadata +**ID:** `javascript-code-style/no-duplicate-imports` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Single imports are easier to read and maintain you can see everything being imported from a module in one line. + +## Non-Compliant Code Examples +```javascript +import { merge } from 'module'; +import something from 'another-module'; +import { find } from 'module'; + +import something from 'something'; +import { find } from 'something'; +``` + +## Compliant Code Examples +```javascript +import { merge, find } from 'module'; +import something from 'another-module'; + +// not mergeable +import { merge } from 'something'; +import * as something from 'something'; +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md b/content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md new file mode 100644 index 0000000000000..fe0a41431fb7f --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/no-floating-decimal + language: JavaScript + severity: Notice +title: Avoid leading or trailing decimal points in numbers +--- +## Metadata +**ID:** `javascript-code-style/no-floating-decimal` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +To prevent confusion between the dot operator and the decimal point, always use a leading number when writing floating point numbers. + +## Non-Compliant Code Examples +```javascript +var x = .5; +var x = -.5; +var x = 2.; +var x = -2.; +typeof.2 +for(foo of.2); +``` + +## Compliant Code Examples +```javascript +var x = 2.5; +var x = "2.5"; +var t = { + ecmaVersion: 2018, +} +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md b/content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md new file mode 100644 index 0000000000000..4c5943ae33a29 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md @@ -0,0 +1,122 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/no-lonely-if + language: JavaScript + severity: Notice +title: Avoid if statements as the only statement in else blocks +--- +## Metadata +**ID:** `javascript-code-style/no-lonely-if` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Prefers `else if` statement instead of an lonely `if` statement. Using `else if` statements` is a cleaner code practice. + +## Non-Compliant Code Examples +```javascript +if (a) {;} else { if (b) {;} } + +if (a) { + foo(); +} else { + if (b) { + bar(); + } +} + +if (a) { + foo(); +} else /* comment */ { + if (b) { + bar(); + } +} + + +if (a) { + foo(); +} else { + /* otherwise, do the other thing */ if (b) { + bar(); + } +} + +if (a) { + foo(); +} else { + if /* this comment is ok */ (b) { + bar(); + } +} + +if (a) { + foo(); +} else { + if (b) { + bar(); + } /* this comment will prevent this test case from being autofixed. */ +} +if (foo) {} else { if (bar) baz(); } + +// Not fixed; removing the braces would cause a SyntaxError. +if (foo) {} else { if (bar) baz() } qux(); + +// This is fixed because there is a semicolon after baz(). +if (foo) {} else { if (bar) baz(); } qux(); + +// Not fixed; removing the braces would change the semantics due to ASI. +if (foo) { +} else { + if (bar) baz() +} +[1, 2, 3].forEach(foo); + +// Not fixed; removing the braces would change the semantics due to ASI. +if (foo) { +} else { + if (bar) baz++ +} +foo; + +// This is fixed because there is a semicolon after baz++ +if (foo) { +} else { + if (bar) baz++; +} +foo; + +// Not fixed; bar() would be interpreted as a template literal tag +if (a) { + foo(); +} else { + if (b) bar() +} +`template literal`; + +if (a) { + foo(); +} else { + if (b) { + bar(); + } else if (c) { + baz(); + } else { + qux(); + } +} +``` + +## Compliant Code Examples +```javascript +if (a) {;} else if (b) {;} +if (a) {;} else { if (b) {;} ; } +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md b/content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md new file mode 100644 index 0000000000000..f8f2ec267bb4b --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md @@ -0,0 +1,72 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/no-multi-assign + language: JavaScript + severity: Notice +title: Avoid the use of chained assignment expressions +--- +## Metadata +**ID:** `javascript-code-style/no-multi-assign` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Assigning multiple variables at once can be hard to understand. Make one expression per assignment instead. + +## Non-Compliant Code Examples +```javascript +var a = b = c; +var a = b = c = d; +let foo = bar = cee = 100; +a=b=c=d=e; +a=b=c; +a +=b +=c; +var a = (b) = (((c))); +var a = ((b)) = (c); +var a = b = ( (c * 12) + 2); +var a = +((b)) + = (c); +a = b = '=' + c + 'foo'; +a = b = 7 * 12 + 5; +const x = {}; +const y = x.one = 1; +let a, b;a = b = 1; +let x, y;x = y = 'baz'; +const a = b = 1; +class C { field = foo = 0 } +class C { field = foo = 0 } +``` + +## Compliant Code Examples +```javascript +var a, b, c, +d = 0; +var a = 1; var b = 2; var c = 3; +var d = 0; +var a = 1 + (b === 10 ? 5 : 4); +const a = 1, b = 2, c = 3; +const a = 1; +const b = 2; +const c = 3; +for(var a = 0, b = 0;;){} +for(let a = 0, b = 0;;){} +for(const a = 0, b = 0;;){} +export let a, b; +export let a, + b = 0; +// ignore non declaration option not supported +// const x = {};const y = {};x.one = y.one = 1; +// let a, b;a = b = 1 +class C { [foo = 0] = 0 } +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-new-func.md b/content/en/static_analysis/rules/javascript-code-style/no-new-func.md new file mode 100644 index 0000000000000..535201a134fbe --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-new-func.md @@ -0,0 +1,54 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/no-new-func + language: JavaScript + severity: Warning +title: Avoid new operators with the Function object +--- +## Metadata +**ID:** `javascript-code-style/no-new-func` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +The Function constructor can lead to code similar to `eval` executions. Use function declarations instead of the Function constructor. + +## Non-Compliant Code Examples +```javascript +var a = new Function("b", "c", "return b+c"); +var a = Function("b", "c", "return b+c"); +var a = Function.call(null, "b", "c", "return b+c"); +var a = Function.apply(null, ["b", "c", "return b+c"]); +var a = Function.bind(null, "b", "c", "return b+c")(); +var a = Function.bind(null, "b", "c", "return b+c"); +var a = Function["call"](null, "b", "c", "return b+c"); +var a = (Function?.call)(null, "b", "c", "return b+c"); +const fn = () => { class Function {} }; new Function('', ''); +var fn = function () { function Function() {} }; Function('', ''); +``` + +## Compliant Code Examples +```javascript +var a = new _function("b", "c", "return b+c"); +var a = _function("b", "c", "return b+c"); +// Scoped re assign not supported +// class Function {}; new Function() +// const fn = () => { class Function {}; new Function() } +// function Function() {}; Function() +// var fn = function () { function Function() {}; Function() } +// var x = function Function() { Function(); } +call(Function) +new Class(Function) +foo[Function]() +foo(Function.bind) +Function.toString() +Function[call]() +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-new-object.md b/content/en/static_analysis/rules/javascript-code-style/no-new-object.md new file mode 100644 index 0000000000000..c98e95a79f29e --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-new-object.md @@ -0,0 +1,61 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/no-new-object + language: JavaScript + severity: Notice +title: Avoid Object constructors +--- +## Metadata +**ID:** `javascript-code-style/no-new-object` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +For consistency, always use the shorter object literal notation `{}`. + +## Non-Compliant Code Examples +```javascript +var foo = new Object() +new Object(); +const a = new Object() + +``` + +## Compliant Code Examples +```javascript +// Scoped re declare not supported +var myObject = {}; +var myObject = new CustomObject(); +var foo = new foo.Object() +// var Object = function Object() {}; +// new Object(); +var x = something ? MyClass : Object; +var y = new x(); + +// class Object { +// constructor(){ + +// } +// } +// new Object(); + +// import { Object } from './' +// new Object(); + +const init = (canvas, context, t) => + drawDoughnutChart( + canvas, + t('Chats'), + context, + labels.map((l) => t(l)), + Object.values(initialData), + ); +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-new.md b/content/en/static_analysis/rules/javascript-code-style/no-new.md new file mode 100644 index 0000000000000..3a408e1f32114 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-new.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/no-new + language: JavaScript + severity: Notice +title: Avoid new operators outside of assignments or comparisons +--- +## Metadata +**ID:** `javascript-code-style/no-new` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +A lonely instance is almost always useless. Do not create objects without assigning them to a variable that you will use later. + +## Non-Compliant Code Examples +```javascript +new Date() +``` + +## Compliant Code Examples +```javascript +var a = new Date() +var a; if (a === new Date()) { a = false; } +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-return-assign.md b/content/en/static_analysis/rules/javascript-code-style/no-return-assign.md new file mode 100644 index 0000000000000..7e08d53cbb6be --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-return-assign.md @@ -0,0 +1,84 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-code-style/no-return-assign + language: JavaScript + severity: Notice +title: Avoid assignment operators in return statements +--- +## Metadata +**ID:** `javascript-code-style/no-return-assign` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Error Prone + +## Description +JavaScript allows return statements to do assignment operations. Because it is hard to differentiate between an assignment and a comparison when written as part of the return statement, avoid using return statements. + +## Non-Compliant Code Examples +```javascript +function x() { return result = a * b; }; +function x() { return (result) = (a * b); }; +function x() { return result = a * b; }; +function x() { return (result) = (a * b); }; +() => { return result = a * b; }; +() => result = a * b; +function x() { return result = a * b; }; +// Allow parens option not supported +// function x() { return (result = a * b); }; +// function x() { return result || (result = a * b); }; +function foo(){ + return a = b +} +function doSomething() { + return foo = bar && foo > 0; +} +function doSomething() { + return foo = function(){ + return (bar = bar1) + } +} +function doSomething() { + return foo = () => a +} +function doSomething() { + return () => a = () => b +} +function foo(a){ + return function bar(b){ + return a = b + } +} +const foo = (a) => (b) => a = b; + +``` + +## Compliant Code Examples +```javascript +module.exports = {'a': 1}; +var result = a * b; +function x() { var result = a * b; return result; } +function x() { return (result = a * b); } +function x() { var result = a * b; return result; } +function x() { return (result = a * b); } +function x() { var result = a * b; return result; } +function x() { return function y() { result = a * b }; } +() => { return (result = a * b); } +() => (result = a * b) +const foo = (a,b,c) => ((a = b), c) +function foo(){ + return (a = b) +} +function bar(){ + return function foo(){ + return (a = b) && c + } +} +const foo = (a) => (b) => (a = b) +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-self-compare.md b/content/en/static_analysis/rules/javascript-code-style/no-self-compare.md new file mode 100644 index 0000000000000..9bd32bb1d45e9 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-self-compare.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-code-style/no-self-compare + language: JavaScript + severity: Warning +title: Avoid comparisons where both sides are exactly the same +--- +## Metadata +**ID:** `javascript-code-style/no-self-compare` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Comparing a variable to itself is most likely a mistake. + +## Non-Compliant Code Examples +```javascript +if (x === x) { } +if (x !== x) { } +if (x > x) { } +if ('x' > 'x') { } +do {} while (x === x) +x === x +x !== x +x == x +x != x +x > x +x < x +x >= x +x <= x +foo.bar().baz.qux >= foo.bar().baz.qux +class C { #field; foo() { this.#field === this.#field; } } +``` + +## Compliant Code Examples +```javascript +if (x === y) { } +if (1 === 2) { } +y=x*x +foo.bar.baz === foo.bar.qux +class C { #field; foo() { this.#field === this['#field']; } } +class C { #field; foo() { this['#field'] === this.#field; } } +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-var.md b/content/en/static_analysis/rules/javascript-code-style/no-var.md new file mode 100644 index 0000000000000..f9f6ddbc1c025 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/no-var.md @@ -0,0 +1,62 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/no-var + language: JavaScript + severity: Notice +title: Require let or const instead of var +--- +## Metadata +**ID:** `javascript-code-style/no-var` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Block scoped lexical declarations like `let` and `const` are preferred over `var`. Block scope is common in many other programming languages and helps programmers avoid mistakes. + +## Non-Compliant Code Examples +```javascript +var foo = bar; +var foo = bar, toast = most; +var foo = bar; let toast = most; +for (var a of b) { console.log(a); } +for (var a in b) { console.log(a); } +for (let a of b) { var c = 1; console.log(c); } +for (var i = 0; i < list.length; ++i) { foo(i) } +for (var i = 0; i < 10; ++i) {}; +for (var a of b) { arr.push(() => a); } +for (let a of b) { var c; console.log(c); c = 'hello'; } +var a = a; +var {a = a} = {}; +var {a = b, b} = {}; +let {a, b = a} = {}; +var a = b, b = 1; +let a = b; var b = 1; +function foo() { a } var a = 1; foo(); +if (foo) var bar = 1; +var foo = 1; +{ var foo = 1 } +if (true) { var foo = 1 } +var foo = 1; +declare var foo = 2; +function foo() { var let; } +function foo() { var { let } = {}; } +function foo() { a } +var a = 1; foo(); + +``` + +## Compliant Code Examples +```javascript +const JOE = 'schmoe'; +let moo = 'car'; +const JOE = 'schmoe'; +let moo = 'car'; +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/parameter-name.md b/content/en/static_analysis/rules/javascript-code-style/parameter-name.md new file mode 100644 index 0000000000000..224a4a7d62b24 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/parameter-name.md @@ -0,0 +1,37 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-code-style/parameter-name + language: JavaScript + severity: Notice +title: Parameter name should use camelCase +--- +## Metadata +**ID:** `javascript-code-style/parameter-name` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that parameter names use `camelCase` and not `snake_case` or `PascalCase`. + +## Non-Compliant Code Examples +```javascript +const a = { setValue(NewValue, event_info) {} } +class A { setValue(NewValue, event_info) {} } +function setValue(NewValue, event_info) {} +const a = function(NewValue, event_info) {} +``` + +## Compliant Code Examples +```javascript +const a = { getValue() {} } +class A { setValue(newValue) {} } +class B { setValue(md5, valid5String) {} } +``` diff --git a/content/en/static_analysis/rules/javascript-code-style/radix.md b/content/en/static_analysis/rules/javascript-code-style/radix.md new file mode 100644 index 0000000000000..b9659fd12d6b9 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-code-style/radix.md @@ -0,0 +1,84 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: javascript-code-style/radix + language: JavaScript + severity: Notice +title: Consistent use of the radix argument using parseInt +--- +## Metadata +**ID:** `javascript-code-style/radix` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When utilizing the `parseInt()` function, many often skip the second parameter (the radix), allowing the function to deduce the number type based on the initial argument. By default, `parseInt()` can recognize both decimal and hexadecimal numbers, the latter through the `0x` prefix. However, before ECMAScript 5, the function also mistakenly recognized octal numbers, leading to issues as many developers presumed a starting `0` would be disregarded. + +## Non-Compliant Code Examples +```javascript +parseInt(); +parseInt(); +parseInt("10"); +parseInt("10",); +parseInt((0, "10")); +parseInt((0, "10"),); +parseInt("10", null); +parseInt("10", undefined); +parseInt("10", true); +parseInt("10", "foo"); +parseInt("10", "123"); +parseInt("10", 1); +parseInt("10", 37); +parseInt("10", 10.5); +Number.parseInt(); +Number.parseInt(); +Number.parseInt("10"); +Number.parseInt("10", 1); +Number.parseInt("10", 37); +Number.parseInt("10", 10.5); +parseInt?.("10"); +Number.parseInt?.("10"); +Number?.parseInt("10"); +(Number?.parseInt)("10"); + +``` + +## Compliant Code Examples +```javascript +parseInt("10", 10); +parseInt("10", 2); +parseInt("10", 36); +parseInt("10", 0x10); +parseInt("10", 1.6e1); +parseInt("10", 10.0); +parseInt("10", foo); +Number.parseInt("10", foo); +parseInt("10", 10); +parseInt("10", 8); +parseInt("10", foo); +parseInt +Number.foo(); +Number[parseInt](); +class C { #parseInt; foo() { Number.#parseInt(); } } +class C { #parseInt; foo() { Number.#parseInt(foo); } } +class C { #parseInt; foo() { Number.#parseInt(foo, 'bar'); } } +class C { #parseInt; foo() { Number.#parseInt(foo, 10); } } + +// shadowed not supported +// Ignores if it's shadowed or disabled. +// var parseInt; parseInt(); +// var parseInt; parseInt(foo); +// var parseInt; parseInt(foo, 10); +// var Number; Number.parseInt(); +// var Number; Number.parseInt(foo); +// var Number; Number.parseInt(foo, 10); +// /* globals parseInt:off */ parseInt(foo); +// Number.parseInt(foo, 10); +``` diff --git a/content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md b/content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md new file mode 100644 index 0000000000000..ee02662c52725 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-common-security/axios-avoid-insecure-http + language: JavaScript + severity: Warning +title: Avoid insecure HTTP requests with Axios +--- +## Metadata +**ID:** `javascript-common-security/axios-avoid-insecure-http` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Avoid connecting to `http` services. Use `https` services for security reasons. + +## Non-Compliant Code Examples +```javascript +const dataFromBackend = axios.get('http://backend.my.app') + +``` + +## Compliant Code Examples +```javascript +const dataFromBackend = axios.get('https://backend.my.app') + +``` diff --git a/content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md b/content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md new file mode 100644 index 0000000000000..8cc13eab0e20e --- /dev/null +++ b/content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-common-security/unique-function-arguments + language: JavaScript + severity: Warning +title: Function argument names should be unique +--- +## Metadata +**ID:** `javascript-common-security/unique-function-arguments` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +A function's parameter names should all be unique. Otherwise, a latter parameter will overwrite the former parameter. This behavior can lead to unintended bugs and it difficult to debug in the future. + +## Non-Compliant Code Examples +```javascript +function addition(foo, bar, foo) { + console.log(foo + bar + foo); +} + +addition(1, 2, 3); // outputs 8 +``` + +## Compliant Code Examples +```javascript +function addition(foo, bar, baz) { + console.log(foo + bar + baz); +} + +addition(1, 2, 3); // outputs 6 +``` diff --git a/content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md b/content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md new file mode 100644 index 0000000000000..7d3637d95d17a --- /dev/null +++ b/content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-common-security/xml-no-external-entities + language: JavaScript + severity: Warning +title: Do not use external XML entities +--- +## Metadata +**ID:** `javascript-common-security/xml-no-external-entities` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Process external entities in XML files may lead to XXE attack. Do not load external entities unless they have been explicitly checked. + +## Non-Compliant Code Examples +```javascript +var libxmljs = require('libxmljs'); +var fs = require('fs'); + +var xml = fs.readFileSync('file.xml', 'utf8'); +libxmljs.parseXmlString(xml, { + noent: true, +}); +``` + +## Compliant Code Examples +```javascript +var libxmljs = require('libxmljs'); +var fs = require('fs'); + +var xml = fs.readFileSync('file.xml', 'utf8'); +libxmljs.parseXmlString(xml); + +``` diff --git a/content/en/static_analysis/rules/javascript-express/access-restriction.md b/content/en/static_analysis/rules/javascript-express/access-restriction.md new file mode 100644 index 0000000000000..3d5615bb3ba53 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/access-restriction.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/access-restriction + language: JavaScript + severity: Warning +title: Limit exposure to sensitive directories and files +--- +## Metadata +**ID:** `javascript-express/access-restriction` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Exposing a directory listing could present an attacker an opportunity to access source code or other sensitive data through a file structure exploit. Restricting access to non-sensitive directories and files is strongly suggested. + +#### Learn More +- [Express Serve index middleware](https://expressjs.com/en/resources/middleware/serve-index.html) + + +## Non-Compliant Code Examples +```javascript +const express = require("express") +const serveIndex = require("serve-index") + +const app = express() + +app.use(serveIndex()) +``` + +## Compliant Code Examples +```javascript +const express = require("express") +const serveIndex = require("serve-index") + +const app = express() + +app.use(serveIndex("/public")) +``` diff --git a/content/en/static_analysis/rules/javascript-express/default-session-config.md b/content/en/static_analysis/rules/javascript-express/default-session-config.md new file mode 100644 index 0000000000000..004aa7cfe9a7b --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/default-session-config.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/default-session-config + language: JavaScript + severity: Warning +title: Enforce overriding default config +--- +## Metadata +**ID:** `javascript-express/default-session-config` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Avoid leaving your session cookies open to exploits or unauthorized access, by overriding default values. + +Setting the `name` value to something generic is better than using the default value. + +#### Learn More +- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) + +## Non-Compliant Code Examples +```javascript +const session = require('express-session') + +app.use( + session({ + secret: "secret" + }) +) +``` + +## Compliant Code Examples +```javascript +const session = require('express-session') + +app.use( + session({ + secret: "secret", + name: 'sessionId' + }) +) +``` diff --git a/content/en/static_analysis/rules/javascript-express/external-filename-upload.md b/content/en/static_analysis/rules/javascript-express/external-filename-upload.md new file mode 100644 index 0000000000000..4d9a525b5f9a0 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/external-filename-upload.md @@ -0,0 +1,57 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/external-filename-upload + language: JavaScript + severity: Warning +title: Avoid using unsanitized user input with sendFile +--- +## Metadata +**ID:** `javascript-express/external-filename-upload` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Using unsanitized user input in a `sendFile` method can allow attackers to access unintended resources. + +Set the `root` option directly in your `sendFile` options will make this rule not report a violation. + +#### Learn More +- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile) + +## Non-Compliant Code Examples +```javascript +app.post("/upload", (req, res) => { + res.sendFile(req.params.filename) + + // options passed, but no root set + res.sendFile(req.params.filename, { maxAge: 0 }) + + // options passed, but no root set, and a callback is set + res.sendFile(req.params.filename, { maxAge: 0 }, (err) => console.log(err)) +}) +``` + +## Compliant Code Examples +```javascript +app.post("/upload", (req, res) => { + res.sendFile("foo") + + const options = { maxAge: 0, root: path.join(__dirname, "upload") } + + // options with root set + res.sendFile(req.params.filename, options) + res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }) + + // options with root set (and a callback is set) + res.sendFile(req.params.filename, options, (err) => console.log(err)) + res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }, (err) => console.log(err)) +}) +``` diff --git a/content/en/static_analysis/rules/javascript-express/external-resource.md b/content/en/static_analysis/rules/javascript-express/external-resource.md new file mode 100644 index 0000000000000..5a1ef1e4fa466 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/external-resource.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/external-resource + language: JavaScript + severity: Warning +title: Avoid rendering resource based on unsanitized user input +--- +## Metadata +**ID:** `javascript-express/external-resource` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Rendering resources based on unsanitized user input should be avoided. At a minimum, one should use a safelist to restrict the potential resources that are exposed. + +## Non-Compliant Code Examples +```javascript +app.get("/", (req, res) => { + res.render(req.body.path) + res.render(req.cookies.path) + res.render(req.headers.path) + res.render(req.params.path) + res.render(req.query.path) +}) +``` + +## Compliant Code Examples +```javascript +app.get("/", (req, res) => { + const path = req.body.path + if (["posts", "pages"].includes(path)) { + return res.render(`${path}/success`) + } + res.render("error-page") +}) +``` diff --git a/content/en/static_analysis/rules/javascript-express/hardcoded-secret.md b/content/en/static_analysis/rules/javascript-express/hardcoded-secret.md new file mode 100644 index 0000000000000..e0728d9692ce0 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/hardcoded-secret.md @@ -0,0 +1,69 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/hardcoded-secret + language: JavaScript + severity: Warning +title: Avoid using a hard-coded secret +--- +## Metadata +**ID:** `javascript-express/hardcoded-secret` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not store secrets in plaintext where they are used. Instead use environment variables (`process.env.`) or better yet, use a key management service (KMS) linked below that includes encryption. + +#### Learn More +- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password) +- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs) +- [AWS Key Management Service](https://aws.amazon.com/kms/) + +## Non-Compliant Code Examples +```javascript +import session from "express-session" +import { expressjwt } from "express-jwt" + +app.use( + session({ + name: "session-name", + secret: "not-secret-secret", + secret: `${isProd ? "prod-secret" : "dev-secret"}`, + }) +) + +app.use( + expressjwt({ + name: "session-name", + secret: "not-secret-secret", + secret: `${isProd ? "prod-secret" : "dev-secret"}`, + }) +) +``` + +## Compliant Code Examples +```javascript +import session from "express-session" +import { expressjwt } from "express-jwt" + +app.use( + session({ + name: "session-name", + secret: process.env.SECRET + }) +) + +app.use( + expressjwt({ + name: "session-name", + secret: process.env.SECRET + }) +) +``` diff --git a/content/en/static_analysis/rules/javascript-express/https-protocol-missing.md b/content/en/static_analysis/rules/javascript-express/https-protocol-missing.md new file mode 100644 index 0000000000000..26a5177a95114 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/https-protocol-missing.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/https-protocol-missing + language: JavaScript + severity: Warning +title: Use `https` protocol over `http` +--- +## Metadata +**ID:** `javascript-express/https-protocol-missing` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-tls): + +> If your app deals with or transmits sensitive data, use [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS) to secure the connection and the data. This technology encrypts data before it is sent from the client to the server, thus preventing some common (and easy) hacks. + +This rule will detect the usage of non `https.createServer()` usage. + +## Non-Compliant Code Examples +```javascript +var http = require('http'); +var express = require('express'); +var app = express(); + +var httpServer = http.createServer(app) +httpServer.listen(8080); +``` + +## Compliant Code Examples +```javascript +var https = require('https'); +var express = require('express'); +var app = express(); + +var httpsServer = https.createServer(app) +httpsServer.listen(8080); +``` diff --git a/content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md b/content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md new file mode 100644 index 0000000000000..22a1ec7c06bb2 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/insecure-allow-origin + language: JavaScript + severity: Warning +title: Avoid using an insecure Access-Control-Allow-Origin header +--- +## Metadata +**ID:** `javascript-express/insecure-allow-origin` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Setting an Access-Control-Allow-Origin header with an unverified user-defined input can lead to sharing sensitive data with an unintended user. + +If this is unavoidable, consider comparing the input against a safe-list. + +#### Learn More + +- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing) + + +## Non-Compliant Code Examples +```javascript +app.get('/', function (req, res) { + res.set('Access-Control-Allow-Origin', req.headers.foo) + res.set({ "foo": "bar", 'Access-Control-Allow-Origin': req.query.foo }) + res.header('Access-Control-Allow-Origin', req.params.foo) + res.setHeader('Access-Control-Allow-Origin', req.body.foo); + res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': req.cookies.foo }) +}); +``` + +## Compliant Code Examples +```javascript +app.get('/', function (req, res) { + res.set('Access-Control-Allow-Origin', "foo_url") + res.set({ "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) + res.header('Access-Control-Allow-Origin', "foo_url") + res.setHeader('Access-Control-Allow-Origin', "foo_url"); + res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) +}); +``` diff --git a/content/en/static_analysis/rules/javascript-express/insecure-cookie.md b/content/en/static_analysis/rules/javascript-express/insecure-cookie.md new file mode 100644 index 0000000000000..41437cf1512ba --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/insecure-cookie.md @@ -0,0 +1,62 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/insecure-cookie + language: JavaScript + severity: Warning +title: Avoid setting insecure cookie settings +--- +## Metadata +**ID:** `javascript-express/insecure-cookie` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +When using cookies in your application, one should ensure appropriate security options are set to lessen the risk of exploits and unauthorized users. + +This rule will detect when `secure` and `httpOnly` are set to `false` in a multitude of ways. + +#### Learn More + +- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) + +## Non-Compliant Code Examples +```javascript +const cookie = { + secure: false, + httpOnly: false, +} + +const options = { + cookie: { + secure: false, + httpOnly: false, + } +} + +cookieSession({ secure: false }) +``` + +## Compliant Code Examples +```javascript +const cookie = { + secure: true, + httpOnly: true, +} + +const options = { + cookie: { + secure: true, + httpOnly: true, + } +} + +cookieSession({ secure: true }) +``` diff --git a/content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md b/content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md new file mode 100644 index 0000000000000..ce347e4e9df06 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md @@ -0,0 +1,93 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/jwt-not-revoked + language: JavaScript + severity: Warning +title: Ensure an isRevoked method is used for tokens +--- +## Metadata +**ID:** `javascript-express/jwt-not-revoked` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Consider a method to revoke JWTs, especially when they contain sensitive information, to ensure they remain short-lived. + +#### Learn More +- [ExpressJWT revoking documentation](https://github.com/auth0/express-jwt#revoked-tokens) + +## Non-Compliant Code Examples +```javascript +const { expressjwt: jwt } = require("express-jwt") + +app.get( + "/protected", + jwt({ + secret: "shhhhhhared-secret", + algorithms: ["HS256"] + }), + function (req, res) { + if (!req.auth.admin) return res.sendStatus(401); + res.sendStatus(200); + } +); +``` + +```javascript +import { expressjwt } from "express-jwt"; + +app.get( + "/protected", + expressjwt({ + secret: "shhhhhhared-secret", + algorithms: ["HS256"], + }), + function (req, res) { + if (!req.auth.admin) return res.sendStatus(401); + res.sendStatus(200); + } +); +``` + +## Compliant Code Examples +```javascript +const { expressjwt } = require("express-jwt") + +app.get( + "/protected", + expressjwt({ + secret: "shhhhhhared-secret", + algorithms: ["HS256"], + isRevoked: isRevokedCallback, + }), + function (req, res) { + if (!req.auth.admin) return res.sendStatus(401); + res.sendStatus(200); + } +); +``` + +```javascript +import { expressjwt as jwt } from "express-jwt"; + +app.get( + "/protected", + jwt({ + secret: "shhhhhhared-secret", + algorithms: ["HS256"], + isRevoked: isRevokedCallback, + }), + function (req, res) { + if (!req.auth.admin) return res.sendStatus(401); + res.sendStatus(200); + } +); +``` diff --git a/content/en/static_analysis/rules/javascript-express/missing-helmet.md b/content/en/static_analysis/rules/javascript-express/missing-helmet.md new file mode 100644 index 0000000000000..ad54e76c6607d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/missing-helmet.md @@ -0,0 +1,67 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/missing-helmet + language: JavaScript + severity: Warning +title: Express application should use Helmet +--- +## Metadata +**ID:** `javascript-express/missing-helmet` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-helmet): + +> [Helmet](https://helmetjs.github.io/) can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately. + +This rule will check whether you've set `app.use(helmet())` within the file that you've called `express()` + +## Non-Compliant Code Examples +```javascript +const express = require("express") + +const app = express(); + +// no `app.use(helmet())` helmet detected in the file + +app.get("/foo", (req, res) => res.send("foo")); + +app.listen(8000); +``` + +## Compliant Code Examples +```javascript +const express = require("express") +const helmet = require("helmet") + +const app = express(); + +app.use(json()); // helmet detected +app.use(helmet()); // helmet detected + +app.get("/foo", (req, res) => res.send("foo")); + +app.listen(8000); +``` + +```javascript +import express from "express" +import helmet from "helmet" + +const app = express(); + +app.use(helmet()); // helmet detected + +app.get("/foo", (req, res) => res.send("foo")); + +app.listen(8000); +``` diff --git a/content/en/static_analysis/rules/javascript-express/path-traversal.md b/content/en/static_analysis/rules/javascript-express/path-traversal.md new file mode 100644 index 0000000000000..df525854d8474 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/path-traversal.md @@ -0,0 +1,57 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/path-traversal + language: JavaScript + severity: Warning +title: Avoid allowing access to unintended directories or files +--- +## Metadata +**ID:** `javascript-express/path-traversal` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +By not sanitizing user input prior to using it in path resolution methods you open your application's access to unintended directories and files. + +> If you're using `replace` on a user input, this rule will assume you've done so correctly and will not report a violation + +#### Learn More +- [OWASP path traversal](https://owasp.org/www-community/attacks/Path_Traversal) + +## Non-Compliant Code Examples +```javascript +const path = require("path"); + +app.get("/", (req, res) => { + path.join("/user/", req.params.path) + + var pathname = path.join("/public/", req.body.foo) + path.resolve(pathname) + + path.resolve(__dirname, req.body.foo) + path.resolve(__dirname, `${req.body.foo}`) +}) +``` + +## Compliant Code Examples +```javascript +const path = require("path"); + +app.get("/", (req, res) => { + path.join("/user/", req.params.path.replace(/^(\.\.(\/|\\|$))+/, '')) + + var pathname = path.join("/public/", req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) + path.resolve(pathname) + + path.resolve(__dirname, req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) + path.resolve(__dirname, `${req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')}`) +}) +``` diff --git a/content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md b/content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md new file mode 100644 index 0000000000000..c84c7296c3d0f --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md @@ -0,0 +1,66 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/reduce-server-fingerprinting + language: JavaScript + severity: Warning +title: Server fingerprinting misconfiguration +--- +## Metadata +**ID:** `javascript-express/reduce-server-fingerprinting` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Improve your overall server security by taking the step to reduce the likelihood of server fingerprinting the software being used on the server. + +By default, Express.js sends the `X-Powered-By` response header banner which can be disabled with `app.disable('X-Powered-By')`. + +If you're using `helmet`, you can use either of these methods too: +- `app.use(hidePoweredBy())` +- `app.use(helmet.hidePoweredBy())` + +#### Learn More +- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html) + +## Non-Compliant Code Examples +```javascript +const app = express() + +// express() is called but none of the following were detected afterwards +// app.disable('x-powered-by') +// app.use(hidePoweredBy()) +// app.use(helmet.hidePoweredBy()) +``` + +## Compliant Code Examples +```javascript +const app = express() + +app.use(helmet.hidePoweredBy()); + +// rest of your config +``` + +```javascript +const app = express() + +app.use(hidePoweredBy()) + +// rest of your config +``` + +```javascript +const app = express() + +app.disable('x-powered-by') + +// rest of your config +``` diff --git a/content/en/static_analysis/rules/javascript-express/xss-vulnerability.md b/content/en/static_analysis/rules/javascript-express/xss-vulnerability.md new file mode 100644 index 0000000000000..93f5223b447e8 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-express/xss-vulnerability.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-express/xss-vulnerability + language: JavaScript + severity: Warning +title: Avoid sending unsanitized user input in response +--- +## Metadata +**ID:** `javascript-express/xss-vulnerability` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Returning unsanitized user input in a `send` or `write` method can increase your application's risk of cross-site scripting attacks. + +#### Learn More +- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) + +## Non-Compliant Code Examples +```javascript +app.get("/", (req, res) => { + res.send(req.body.foo); + res.send({ title: "foo", message: req.body.foo }); + res.write(req.body.foo); + res.write({ title: "foo", message: req.body.foo }); +}) +``` + +## Compliant Code Examples +```javascript +app.get("/", (req, res) => { + res.send("foo"); + res.send({ title: "foo", message: 'foo' }); + res.write("foo"); + res.write({ title: "foo", message: 'foo' }); +}) +``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/comments.md b/content/en/static_analysis/rules/javascript-inclusive/comments.md new file mode 100644 index 0000000000000..50f065567a676 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-inclusive/comments.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-inclusive/comments + language: JavaScript + severity: Notice +title: Check comments for wording issues +--- +## Metadata +**ID:** `javascript-inclusive/comments` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Check the variable names and suggest better names. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```javascript +/** + * whitelist names to prevent unauthorized usage + */ + +// she SHE should check her code + +// he should check his +``` + +## Compliant Code Examples +```javascript +// allowlist names to prevent unauthorized usage + +/* the comments do not have a history of issues */ +``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/declarations.md b/content/en/static_analysis/rules/javascript-inclusive/declarations.md new file mode 100644 index 0000000000000..e4dee86c4de12 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-inclusive/declarations.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-inclusive/declarations + language: JavaScript + severity: Notice +title: Check declaration names for wording issues +--- +## Metadata +**ID:** `javascript-inclusive/declarations` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that some words are not used in the codebase and suggest a replacement when appropriate. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```javascript +function foo_blacklist() {} +a(function *blackList() {}); +function *whItEList() {} +function blacklist_names() {} +function whiteList() {} +class WhiteList {} +const slave = 0; +let master = ""; +var slave = b; +``` + +## Compliant Code Examples +```javascript +function foo_denyList() {} +a(function *allowedList() {}); +class primary {} +const secondary = 0; +``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md b/content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md new file mode 100644 index 0000000000000..8aa4632254173 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-inclusive/formal-parameters + language: JavaScript + severity: Notice +title: Check parameter names for wording issues +--- +## Metadata +**ID:** `javascript-inclusive/formal-parameters` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that some words are not used in the codebase and suggest a replacement when appropriate. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```javascript +function a(master, slave) {} +function a(blacklist, whitelist) {} +class A { foo(master, slave) {} } + +``` + +## Compliant Code Examples +```javascript +function denyList(primary, secondary) {} +``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/identifiers.md b/content/en/static_analysis/rules/javascript-inclusive/identifiers.md new file mode 100644 index 0000000000000..a2b7f7b3ceb2b --- /dev/null +++ b/content/en/static_analysis/rules/javascript-inclusive/identifiers.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: javascript-inclusive/identifiers + language: JavaScript + severity: Notice +title: Check identifier names for wording issues +--- +## Metadata +**ID:** `javascript-inclusive/identifiers` + +**Language:** JavaScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that some words are not used in the codebase and suggest a replacement when appropriate. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```javascript +{ slave: false } +const a = { 'master': false, }; +const a = { ['master']: false, }; +const a = { c, ...blacklist } = b; +const { whitelist } = b; +const a = { whitelist }; +const { whitelist: slave } = b; +[slave, ...master] = blacklist; +``` + +## Compliant Code Examples +```javascript +{ secondary: false } +const a = { 'primary': false, }; +const a = { c, ...denylist } = b; +const { AllowedList } = b; +[primary, ...secondary] = b; +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/argon2.md b/content/en/static_analysis/rules/javascript-node-security/argon2.md new file mode 100644 index 0000000000000..4a25b25f2f5b7 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/argon2.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/argon2 + language: JavaScript + severity: Error +title: Use strong security mechanisms with argon2 +--- +## Metadata +**ID:** `javascript-node-security/argon2` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Security + +## Description +Use secure and fast security mechanisms with using `argon2`. + +#### Learn More + + - [argon2 types](https://github.com/ranisalt/node-argon2/wiki/Options#type) + +## Non-Compliant Code Examples +```javascript +await argon2.hash('password', {type: argon2.argon2d}) +await argon2.hash('password', {type: argon2.argon2i}) +``` + +## Compliant Code Examples +```javascript +await argon2.hash('password', {type: argon2.argon2id}) +await argon2.hash('password', {}) +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md b/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md new file mode 100644 index 0000000000000..50aa4459f5f83 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/avoid-crypto-rc4 + language: JavaScript + severity: Warning +title: Avoid RC4 +--- +## Metadata +**ID:** `javascript-node-security/avoid-crypto-rc4` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of RC4 security protocol exposes your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library, RC4](https://cryptojs.gitbook.io/docs/#ciphers) + +## Non-Compliant Code Examples +```javascript +var encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase"); +var decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase"); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md b/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md new file mode 100644 index 0000000000000..86e7a5d06c0f5 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/avoid-crypto-sha1 + language: JavaScript + severity: Warning +title: Avoid SHA1 security protocol +--- +## Metadata +**ID:** `javascript-node-security/avoid-crypto-sha1` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of insecure encryption or hashing protocols expose your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hmac) + +## Non-Compliant Code Examples +```javascript +var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase"); +var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase", anotherargument); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/avoid-des.md b/content/en/static_analysis/rules/javascript-node-security/avoid-des.md new file mode 100644 index 0000000000000..3d81669904739 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/avoid-des.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/avoid-des + language: JavaScript + severity: Warning +title: Avoid DES and 3DES +--- +## Metadata +**ID:** `javascript-node-security/avoid-des` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of insecure encryption or hashing protocols expose your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library, DES and TripleDES](https://cryptojs.gitbook.io/docs/#ciphers) + +## Non-Compliant Code Examples +```javascript +var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase"); +var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase"); +var encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase"); +var decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase"); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md b/content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md new file mode 100644 index 0000000000000..e4bf7406abe16 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/chmod-permissions + language: JavaScript + severity: Warning +title: Do not give 777 permissions to a file +--- +## Metadata +**ID:** `javascript-node-security/chmod-permissions` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always make sure you restrict permissions of your application files. Application files should not allow write and execution for other users as it may leak data and information. Always restrict the number of users and applications that can access your application data. + +## Non-Compliant Code Examples +```javascript +const fs = require('fs'); +const fsPromises = fs.promises; + +fs.chmodSync("/tmp/myfile", 0o777); +fsPromises.chmod("/tmp/fsPromises", 0o777); + +``` + +## Compliant Code Examples +```javascript +const fs = require('fs'); +const fsPromises = fs.promises; + +fs.chmodSync(myPath, 0o770); +fsPromises.chmod("/tmp/fsPromises", 0o770); + +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/command-injection.md b/content/en/static_analysis/rules/javascript-node-security/command-injection.md new file mode 100644 index 0000000000000..8885513efbea7 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/command-injection.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/command-injection + language: JavaScript + severity: Warning +title: Avoid command injection +--- +## Metadata +**ID:** `javascript-node-security/command-injection` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +When executing a command, never use unchecked variables. Make sure that each variable in the command has been checked. + +## Non-Compliant Code Examples +```javascript +childprocess.exec(`mv ${src} ${dst}`, (error, stdout, stderr) => {}); +childprocess.exec('mv ' + src + " " + dst, (error, stdout, stderr) => {}); +``` + +## Compliant Code Examples +```javascript +childprocess.exec('mv /tmp/src /tmp/dst', (error, stdout, stderr) => {}); + +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md b/content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md new file mode 100644 index 0000000000000..1390784e384a8 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/crypto-avoid-weak-hash + language: JavaScript + severity: Warning +title: Avoid weak hash algorithm from CryptoJS +--- +## Metadata +**ID:** `javascript-node-security/crypto-avoid-weak-hash` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of insecure hash functions like MD5 or SHA1 can expose your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hashing) + +## Non-Compliant Code Examples +```javascript +var hash = CryptoJS.MD5("Message", "Secret Passphrase"); +var hash = CryptoJS.SHA1("Message", "Secret Passphrase"); +var hash = CryptoJS.HmacMD5("Message", "Secret Passphrase"); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md b/content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md new file mode 100644 index 0000000000000..de4d79a17bcaf --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md @@ -0,0 +1,115 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/detect-buffer-noassert + language: JavaScript + severity: Error +title: Avoid calls to 'buffer' with 'noAssert' flag set +--- +## Metadata +**ID:** `javascript-node-security/detect-buffer-noassert` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Security + +## Description +Avoid calls to [`buffer`](https://nodejs.org/api/buffer.html) with `noAssert`. If you skip the `offset` validation it can go beyond the end of the `Buffer`. + +## Non-Compliant Code Examples +```javascript +a.readUInt8(0, true) +a.readUInt16LE(0, true) +a.readUInt16BE(0, true) +a.readUInt32LE(0, true) +a.readUInt32BE(0, true) +a.readInt8(0, true) +a.readInt16LE(0, true) +a.readInt16BE(0, true) +a.readInt32LE(0, true) +a.readInt32BE(0, true) +a.readFloatLE(0, true) +a.readFloatBE(0, true) +a.readDoubleLE(0, true) +a.readDoubleBE(0, true) +a.writeUInt8(0, 0, true) +a.writeUInt16LE(0, 0, true) +a.writeUInt16BE(0, 0, true) +a.writeUInt32LE(0, 0, true) +a.writeUInt32BE(0, 0, true) +a.writeInt8(0, 0, true) +a.writeInt16LE(0, 0, true) +a.writeInt16BE(0, 0, true) +a.writeInt32LE(0, 0, true) +a.writeInt32BE(0, 0, true) +a.writeFloatLE(0, 0, true) +a.writeFloatBE(0, 0, true) +a.writeDoubleLE(0, 0, true) +a.writeDoubleBE(0, 0, true) + +``` + +## Compliant Code Examples +```javascript +a.readUInt8(0) +a.readUInt16LE(0) +a.readUInt16BE(0) +a.readUInt32LE(0) +a.readUInt32BE(0) +a.readInt8(0) +a.readInt16LE(0) +a.readInt16BE(0) +a.readInt32LE(0) +a.readInt32BE(0) +a.readFloatLE(0) +a.readFloatBE(0) +a.readDoubleLE(0) +a.readDoubleBE(0) +a.writeUInt8(0) +a.writeUInt16LE(0) +a.writeUInt16BE(0) +a.writeUInt32LE(0) +a.writeUInt32BE(0) +a.writeInt8(0) +a.writeInt16LE(0) +a.writeInt16BE(0) +a.writeInt32LE(0) +a.writeInt32BE(0) +a.writeFloatLE(0) +a.writeFloatBE(0) +a.writeDoubleLE(0) +a.writeDoubleBE(0) +a.readUInt8(0, false) +a.readUInt16LE(0, false) +a.readUInt16BE(0, false) +a.readUInt32LE(0, false) +a.readUInt32BE(0, false) +a.readInt8(0, false) +a.readInt16LE(0, false) +a.readInt16BE(0, false) +a.readInt32LE(0, false) +a.readInt32BE(0, false) +a.readFloatLE(0, false) +a.readFloatBE(0, false) +a.readDoubleLE(0, false) +a.readDoubleBE(0, false) +a.writeUInt8(0, false) +a.writeUInt16LE(0, false) +a.writeUInt16BE(0, false) +a.writeUInt32LE(0, false) +a.writeUInt32BE(0, false) +a.writeInt8(0, false) +a.writeInt16LE(0, false) +a.writeInt16BE(0, false) +a.writeInt32LE(0, false) +a.writeInt32BE(0, false) +a.writeFloatLE(0, false) +a.writeFloatBE(0, false) +a.writeDoubleLE(0, false) +a.writeDoubleBE(0, false) +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-child-process.md b/content/en/static_analysis/rules/javascript-node-security/detect-child-process.md new file mode 100644 index 0000000000000..9510ed7134926 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detect-child-process.md @@ -0,0 +1,119 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: javascript-node-security/detect-child-process + language: JavaScript + severity: Warning +title: Avoid instances of 'child_process' and non-literal 'exec()' +--- +## Metadata +**ID:** `javascript-node-security/detect-child-process` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +In Node.js, the "child_process" module provides capabilities to execute shell commands directly. While this might seem beneficial, it comes with significant security risks. If the input to this module isn't properly sanitized, it can pave the way for command injection attacks. In such attacks, malicious actors could introduce harmful commands, which, when executed, could compromise system integrity or lead to data breaches. + +Additionally, using non-literal arguments with "exec()" presents another challenge. When arguments to "exec()" are dynamic or derived from untrusted sources, there's a risk that attackers could manipulate this input. This makes the system vulnerable to unauthorized actions, potentially causing significant damage. Therefore, for a more secure Node.js application, it's advised to tread cautiously with these features, employing rigorous input validation and considering safer alternatives. + +## Non-Compliant Code Examples +```javascript +require('child_process') +require('node:child_process') +var child = require('child_process'); child.exec(com) +var nodeChild = require('node:child_process'); nodeChild.exec(com) +import childImport from 'child_process'; childImport.exec(com) +import nodeChildImport from 'node:child_process'; nodeChildImport.exec(com) + +// not supported +// var child = sinon.stub(require('child_process')); child.exec.returns({}); +// var child = sinon.stub(require('node:child_process')); child.exec.returns({}); + +function fn () { + var result = child.exec(str); +} + +function fn () { + var result = childImport.exec(str); +} + +function fn () { + var result = nodeChildImport.exec(str); +} + +require('child_process').exec(str) + +function fn () { + require('child_process').exec(str) +} + +const {exec} = require('child_process'); +exec(str) + +const {exec: nodeExec} = require('node:child_process'); +nodeExec(str) + +import {exec as foo} from 'child_process'; +foo(com); +``` + +## Compliant Code Examples +```javascript +child_process.exec('ls') + +var {} = require('child_process'); +var result = /hello/.exec(str); + +var {} = require('node:child_process'); +var result = /hello/.exec(str); + +import {} from 'child_process'; +var result = /hello/.exec(str); + +import {} from 'node:child_process'; +var result = /hello/.exec(str); + +var { spawn } = require('child_process'); spawn(str); +var { spawn } = require('node:child_process'); spawn(str); +import { spawn } from 'child_process'; spawn(str); +import { spawn } from 'node:child_process'; spawn(str); + +// import redeclare not covered +// var foo = require('child_process'); +// function fn () { +// var foo = /hello/; +// var result = foo.exec(str); +// } + +var child = require('child_process'); child.spawn(str) +var child = require('node:child_process'); child.spawn(str) +import child from 'child_process'; child.spawn(str) +import child from 'node:child_process'; child.spawn(str) + +var foo = require('child_process'); +function fn () { + var result = foo.spawn(str); +} + +require('child_process').spawn(str) + +function fn () { + require('child_process').spawn(str) +} + +// constant assigment static analysis not covered +// var child_process = require('child_process'); +// var FOO = 'ls'; +// child_process.exec(FOO); + +// import child_process from 'child_process'; +// const FOO = 'ls'; +// child_process.exec(FOO); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md b/content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md new file mode 100644 index 0000000000000..ccecd67079ed1 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/detect-eval-with-expression + language: JavaScript + severity: Warning +title: Avoid `eval` with expressions +--- +## Metadata +**ID:** `javascript-node-security/detect-eval-with-expression` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +The `eval` function could execute malicious code if used with non-literal values. The argument provided to the `eval` method could be used to execute malicious code. If an attacker manages to control the `eval` argument they can execute arbitrary code. + +In JavaScript, the `eval()` function evaluates or executes an argument if it's a string of JavaScript code. If this argument is influenced by user input or other external sources, it can lead to security vulnerabilities. Specifically, if an attacker can control or manipulate the value of the `variable` in `eval(variable)`, they can execute arbitrary code. + +You should avoid using `eval` at all costs, but if you face an advanced use case, use literal values that are under your control or sanitize the input. However, even then it is still recommended to avoid the use of `eval` as it has led to security breaches before. + +## Non-Compliant Code Examples +```javascript +eval(a); +global.eval(a); +globalThis.eval(a); + +const answer = eval(expression) +``` + +## Compliant Code Examples +```javascript +eval('alert()') +global.eval('a'); +globalThis.eval('a'); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md b/content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md new file mode 100644 index 0000000000000..af9373e65ea5e --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/detect-new-buffer + language: JavaScript + severity: Warning +title: Avoid Buffer(argument) with non-literal values +--- +## Metadata +**ID:** `javascript-node-security/detect-new-buffer` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Dealing with binary data can be achieved with the Node.js Buffer class. However, if you use non-literal params, this could lead to malicious control over the value, resulting in an attack. + +For example, a large number could allocate a significant amount of memory leading to a denial of service attack. It is recommended to use literal values that you can control to prevent these attacks. + +## Non-Compliant Code Examples +```javascript +var a = new Buffer(c) +``` + +## Compliant Code Examples +```javascript +var a = new Buffer('test') +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md new file mode 100644 index 0000000000000..d78b49079477c --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md @@ -0,0 +1,149 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/detect-non-literal-fs-filename + language: JavaScript + severity: Warning +title: Avoid variables in 'fs' calls filename argument +--- +## Metadata +**ID:** `javascript-node-security/detect-non-literal-fs-filename` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +An attacker could manipulate the file system call argument, leading to a path traversal attack. In this case, the attacker can get access to files and directories within your server file system. + +## Non-Compliant Code Examples +```javascript +/// requires +var something = require('fs'); +var a = something.open(c); + +var one = require('fs').readFile; +one(filename); + +var one = require('node:fs').readFile; +one(filename); + +var one = require('fs/promises').readFile; +one(filename); + +var something = require('fs/promises'); +something.readFile(filename); + +var something = require('node:fs/promises'); +something.readFile(filename); + +var something = require('fs-extra'); +something.readFile(filename); + +var { readFile: something } = require('fs'); +something(filename) + +//// imports +import { readFile as something } from 'fs'; +something(filename); + +import { readFile as something } from 'node:fs'; +something(filename); + +import { readFile as something } from 'fs-extra'; +something(filename); + +import { readFile as something } from 'fs/promises' +something(filename) + +import { readFile as something } from 'node:fs/promises' +something(filename) + +import { readFile } from 'node:fs/promises' +something(readFile) + +import * as something from 'fs'; +something.readFile(filename); +import * as something from 'node:fs'; +something.readFile(filename); + +/// promises +var something = require('fs').promises; +something.readFile(filename) + +var something = require('node:fs').promises; +something.readFile(filename) + +var something = require('fs'); +something.promises.readFile(filename) + +var something = require('node:fs'); +something.promises.readFile(filename) + +var fs = require('fs'); +fs.readFile(`template with ${filename}`); + +// inline +function foo () { + var fs = require('fs'); + fs.readFile(filename); +} + +function foo () { + var { readFile: something } = require('fs'); + something(filename); +} + +var fs = require('fs'); +function foo () { + var { readFile: something } = fs.promises; + something(filename); +} + +import fs from 'fs'; +import path from 'path'; +const key = fs.readFileSync(path.resolve(__dirname, foo)); +``` + +## Compliant Code Examples +```javascript +var fs = require('fs'); +var a = fs.open('test') + +var something = require('some'); +var a = something.readFile(c); + +var something = require('fs').readFile, readFile = require('foo').readFile; +readFile(c); + + +// TODO: allow path with constant arguments +import { promises as fsp } from 'fs'; +import fs from 'fs'; +import path from 'path'; +// const index = await fsp.readFile(path.resolve(__dirname, './index.html'), 'utf-8'); +// const key = fs.readFileSync(path.join(__dirname, './ssl.key')); +await fsp.writeFile(path.resolve(__dirname, './sitemap.xml'), sitemap); + +import fs from 'fs'; +import path from 'path'; +const dirname = path.dirname(__filename) +// const key = fs.readFileSync(path.resolve(dirname, './index.html')); + +import fs from 'fs'; +// const key = fs.readFileSync(`${process.cwd()}/path/to/foo.json`); + +import fs from 'fs'; +import path from 'path'; +import url from 'url'; +// const dirname = path.dirname(url.fileURLToPath(import.meta.url)); +// const html = fs.readFileSync(path.resolve(dirname, './index.html'), 'utf-8'); + +import fs from 'fs'; +// const pkg = fs.readFileSync(require.resolve('eslint/package.json'), 'utf-8'); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md new file mode 100644 index 0000000000000..2b6f8435ee66a --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/detect-non-literal-regexp + language: JavaScript + severity: Warning +title: Detects non-literal values in regular expressions +--- +## Metadata +**ID:** `javascript-node-security/detect-non-literal-regexp` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Creating a regular expression with user input can lead to a Regular Expression Denial of Service (ReDoS) attack. In this type of attack, a user can submit a very complex regular expression that takes too long to execute. + +If you have an advanced use case that requires regex evaluation with user input, always make sure to sanitize the data and provide a safe timeout environment. + +## Non-Compliant Code Examples +```javascript +var a = new RegExp(c, 'i'); + +``` + +## Compliant Code Examples +```javascript +var a = new RegExp('ab+c', 'i'); + +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md new file mode 100644 index 0000000000000..66e422c9420ac --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/detect-non-literal-require + language: JavaScript + severity: Warning +title: Avoid require with non-literal values +--- +## Metadata +**ID:** `javascript-node-security/detect-non-literal-require` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Importing packages from dynamic paths can be a security vulnerability. An attacker might provide an undesired path that leads to running arbitrary code or reading sensitive information from your file system. + +In Node.js, the `require()` function is a built-in function that allows modules to be loaded. You can use it to include various types of files (like .js, .json, .node, etc) in your project. + +If the argument to `require()` is a variable instead of a static string, and if that variable's value can be influenced by user input, then an attacker might be able to exploit this to run arbitrary code or read sensitive files from your server's disk. This is a serious security issue often referred to as arbitrary code execution. + +Dynamic imports are a common source of arbitrary file read and code execution vulnerabilities. Avoid using variables with `require` or `import` statements. If you have an advanced use case that requires the use of dynamic imports, make sure to sanitize the input and have an allowed list of paths you can import code from. Always set the proper access control to your file system. + +## Non-Compliant Code Examples +```javascript +var a = require(c); +var a = require(`${c}`); + +``` + +## Compliant Code Examples +```javascript +var a = require('b'); +var a = require(`b`); + +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md b/content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md new file mode 100644 index 0000000000000..153d9d1807402 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/detected-jwt-token + language: JavaScript + severity: Error +title: Detects hardcoded JWT tokens within the codebase. +--- +## Metadata +**ID:** `javascript-node-security/detected-jwt-token` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Security + +## Description +JSON Web Tokens (JWT) are commonly used for authentication and information exchange in web applications. While they are a powerful tool, they must be handled with care. + +## Non-Compliant Code Examples +```javascript +"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" +"eyJ0eXAiOiJKV1QiLA0KImFsZyI6IkhTMjU2In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" +"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9lIiwKInN0YXR1cyI6ImVtcGxveWVlIgp9" +'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IsWww6HFkcOtIMOWxZHDqcOoIiwiaWF0IjoxNTE2MjM5MDIyfQ.k5HibI_uLn_RTuPcaCNkaVaQH2y5q6GvJg8GPpGMRwQ' +`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ` +``` + +## Compliant Code Examples +```javascript +"eyfoo" +`eybaz` +'eybla' +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md b/content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md new file mode 100644 index 0000000000000..2e8c403d2542b --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/hardcoded-hmac-key + language: JavaScript + severity: Warning +title: Avoid hardcoded HMAC keys +--- +## Metadata +**ID:** `javascript-node-security/hardcoded-hmac-key` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Hardcoding cryptographic keys, secrets, or other sensitive information within the code is a common but dangerous practice. This rule aims to detect and prevent this kind of code pattern. + +## Non-Compliant Code Examples +```javascript +import crypto from "crypto"; + +crypto.createHmac('sha256', 'pa4qacea4VK9t9nGv7yZtwmj').update(data).digest('hex'); + +const rsa_key = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' +const hmac = crypto.createHmac('sha256', rsa_key) + +const key = 'private'; +const secret = key; +const fail = crypto.createHmac('sha256', secret); +``` + +## Compliant Code Examples +```javascript +import crypto from "crypto"; +import config from "./config"; + +const safely_stored_key = config.get('AWS_KEY') +const safe_hmac = crypto.createHmac('sha256', safely_stored_key) + +crypto.createHmac('sha256', process.env.KEY); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/insecure-hash.md b/content/en/static_analysis/rules/javascript-node-security/insecure-hash.md new file mode 100644 index 0000000000000..6e895648262ec --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/insecure-hash.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/insecure-hash + language: JavaScript + severity: Warning +title: Do not use weak hash functions +--- +## Metadata +**ID:** `javascript-node-security/insecure-hash` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not use weak hash algorithms such as MD5 or SHA1. + +#### Learn More + + - [CWE-328: Use of Weak Hash](https://cwe.mitre.org/data/definitions/328.html) + +## Non-Compliant Code Examples +```javascript +crypto.createHash("md5") + +createHash("md5") + +crypto.createHash("sha1") +``` + +## Compliant Code Examples +```javascript +crypto.createHash("sha256") + +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md b/content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md new file mode 100644 index 0000000000000..c9c76fbb8674e --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md @@ -0,0 +1,54 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/insecure-jwt-secret-usage + language: JavaScript + severity: Error +title: Insecure Usage of a Static Secret in JWT Signing +--- +## Metadata +**ID:** `javascript-node-security/insecure-jwt-secret-usage` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Security + +## Description +Using a static secret for signing JSON Web Tokens (JWT) poses several security risks: + +1. **Static Secrets**: Static secrets embedded in the code can be easily discovered by attackers. This is particularly dangerous if the code becomes publicly available or is leaked. +2. **Weak Secrets**: A simple, static secret might be weak and easily guessable, rendering the security controls it supports ineffective. +3. **Lack of Key Rotation**: A static secret doesn't allow for key rotation, a recommended practice to mitigate the risk if a secret is compromised. + +## Non-Compliant Code Examples +```javascript +import jwt from 'jsonwebtoken'; + +const privateKey = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' +export const authorize = (user = {}) => jwt.sign(user, privateKey, { expiresIn: '6h', algorithm: 'RS256' }); + +jwt.sign({ user: 'foo' }, 'secret'); + +const key = 'shhh'; +const secret = key; +jwt.sign({ user: 'foo' }, secret); +``` + +## Compliant Code Examples +```javascript +import jwt from "jsonwebtoken"; +import config from './config'; + +const payload = {foo: 'bar'}; +const secret3 = process.env.SECRET +const token5 = jwt.sign(payload, secret3) + +jwt.sign(payload, process.env.KEY); +jwt.sign(payload, config.secret); + +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md b/content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md new file mode 100644 index 0000000000000..3e018fad0469d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/jwt-hardcoded-secret + language: JavaScript + severity: Error +title: Do not use hardcoded secret with a JWT +--- +## Metadata +**ID:** `javascript-node-security/jwt-hardcoded-secret` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Security + +## Description +Never hardcode secrets. Instead, use secrets from environment variables or a secret vault. + + +## Non-Compliant Code Examples +```javascript +var jwt = require("jsonwebtoken"); + +var token = jwt.sign({ foo: "bar" }, "secret"); + +var token = jwt.sign({ foo: "bar" }, 'secret'); + +var token = jwt.sign({ foo: "bar" }, `secret`); +``` + +## Compliant Code Examples +```javascript +var jwt = require("jsonwebtoken"); + + var token = jwt.sign({ foo: "bar" }, process.env.JWT_SECRET); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md b/content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md new file mode 100644 index 0000000000000..2e5a0cdb78263 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/jwt-sensitive-data + language: JavaScript + severity: Warning +title: Do not put sensitive data in objects +--- +## Metadata +**ID:** `javascript-node-security/jwt-sensitive-data` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Never include sensitive information in a JWT. Instead, only use non-personal information to identify the end-user. + +## Non-Compliant Code Examples +```javascript +jwt.sign( + {user: { email: 'foo@bar.com'}} +) + +jwt.sign( + {user: { lastname: 'babar'}} +) + +``` + +## Compliant Code Examples +```javascript +jwt.sign( + {user: { id: 42}} +) +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md b/content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md new file mode 100644 index 0000000000000..ff8e803f7c756 --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/jwt-weak-encryption + language: JavaScript + severity: Warning +title: Use default encryption from the JWT library +--- +## Metadata +**ID:** `javascript-node-security/jwt-weak-encryption` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not use `none` as a validation algorithm for a JWT token. The none algorithm assumes that the token has been verified, which would allow attacker to create a token that would be automatically validated. + +Never use the `none` algorithm, always use a valid algorithm as directed by [the documentation](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback). + +## Non-Compliant Code Examples +```javascript +jwt.verify(token, secret, { algorithms: ['RS256', 'none'] }, func); +jwt.verify(token, secret, { algorithms: ['none', 'RS256'] }, func); +``` + +## Compliant Code Examples +```javascript +jwt.verify(token, secret, { algorithms: ['RS256', 'HS256'] }, func); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md b/content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md new file mode 100644 index 0000000000000..558ad338741bd --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/log-sensitive-data + language: JavaScript + severity: Warning +title: Avoid logging sensitive data +--- +## Metadata +**ID:** `javascript-node-security/log-sensitive-data` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not log sensitive data such as user id, email or other personal data (first name, last name, etc). + +## Non-Compliant Code Examples +```javascript +console.log("email from user" + user.email); +console.log(`email from user ${user.email}`); +logger.info(`email from user ${user.email}`); +logger.info(`email from user ${user.name}: ${user.email}`); +logger.info(`email from user ${username}: ${user.email}`); +logger.warn(email); +logger.error(`email from user ${email}`); + +foobar.error(`email from user ${email}`); + +logger.foobar(`email from user ${email}`); + +``` + +## Compliant Code Examples +```javascript +console.log("email from user" + user.id); +console.log(`email from user ${user.uuid}`); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md b/content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md new file mode 100644 index 0000000000000..21c80d519460d --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md @@ -0,0 +1,56 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/oauth2-hardcoded-secret + language: JavaScript + severity: Warning +title: Do not use hardcoded secret for OAuth2 providers +--- +## Metadata +**ID:** `javascript-node-security/oauth2-hardcoded-secret` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not put hardcoded credentials in code. Instead, put secrets in environment variables or a vault. + +## Non-Compliant Code Examples +```javascript +passport.use(new OAuth2Strategy({ + authorizationURL: 'https://www.example.com/oauth2/authorize', + tokenURL: 'https://www.example.com/oauth2/token', + clientID: `client_id`, + clientSecret: 'secret_id', + callbackURL: "http://localhost:3000/auth/example/callback" + }, + function(accessToken, refreshToken, profile, cb) { + User.findOrCreate({ exampleId: profile.id }, function (err, user) { + return cb(err, user); + }); + } +)); +``` + +## Compliant Code Examples +```javascript +passport.use(new OAuth2Strategy({ + authorizationURL: 'https://www.example.com/oauth2/authorize', + tokenURL: 'https://www.example.com/oauth2/token', + clientID: process.env.EXAMPLE_CLIENT_ID, + clientSecret: process.env.EXAMPLE_CLIENT_SECRET, + callbackURL: "http://localhost:3000/auth/example/callback" + }, + function(accessToken, refreshToken, profile, cb) { + User.findOrCreate({ exampleId: profile.id }, function (err, user) { + return cb(err, user); + }); + } +)); +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/sql-injection.md b/content/en/static_analysis/rules/javascript-node-security/sql-injection.md new file mode 100644 index 0000000000000..85545262a085f --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/sql-injection.md @@ -0,0 +1,276 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/sql-injection + language: JavaScript + severity: Error +title: Avoid SQL injection +--- +## Metadata +**ID:** `javascript-node-security/sql-injection` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Security + +## Description +Check for variable declarations in a SQL statement where there is potential for SQL injections. + +#### Learn More + + - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) + +## Non-Compliant Code Examples +```javascript +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + // only allow apple or orange related searches + if (!criteria.startsWith("apple") || !criteria.startsWith("orange")) { + res.status(400).send() + return + } + models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```javascript +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + criteria.replace(/"|'|;|and|or/i, "") + models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```javascript +const injectionChars = /"|'|;|and|or|;|#/i; + +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + if (criteria.match(injectionChars)) { + res.status(400).send() + return + } + models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```javascript +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name") + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```javascript +var express = require('express') + +var app = express() +const Sequelize = require('sequelize'); +const sequelize = new Sequelize('database', 'username', 'password', { + dialect: 'sqlite', + storage: 'data/juiceshop.sqlite' +}); + +app.post('/login', function (req, res) { + sequelize.query('SELECT * FROM Products WHERE name LIKE ' + req.body.username); + }) + + +app.post('/update', function (req, res) { + sequelize.query('UPDATE products SET bla=bli WHERE name LIKE ' + req.body.username); + }) + + + +app.post('/remove', function (req, res) { + sequelize.query('DELETE FROM product WHERE name LIKE ' + req.body.username); + }) +``` + +```javascript +const express = require('express'); +const router = express.Router() + +const config = require('../../config') +const mysql = require('mysql'); +const connection = mysql.createConnection({ + host : config.MYSQL_HOST, + port : config.MYSQL_PORT, + user : config.MYSQL_USER, + password : config.MYSQL_PASSWORD, + database : config.MYSQL_DB_NAME, +}); + +connection.connect(); + +router.get('/example1/user/:id', (req,res) => { + let userId = req.params.id; + let query = { + sql : "SELECT * FROM users WHERE id=" + userId + } + connection.query(query,(err, result) => { + res.json(result); + }); +}) + +router.get('/example2/user/:id', (req,res) => { + let userId = req.params.id; + connection.query("SELECT * FROM users WHERE id=" + userId,(err, result) => { + res.json(result); + }); +}) + +router.get('/example3/user/:id', (req,res) => { + let userId = req.params.id; + connection.query({ + sql : "SELECT * FROM users WHERE id=" +userId + },(err, result) => { + res.json(result); + }); +}) + + +module.exports = router +``` + +## Compliant Code Examples +```javascript +import {BasketModel} from "../../../models/basket"; + +module.exports = function login () { + function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { + BasketModel.findOrCreate({ where: { UserId: user.data.id } }) + .then(([basket]: [BasketModel, boolean]) => { + const token = security.authorize(user) + user.bid = basket.id // keep track of original basket + security.authenticatedUsers.put(token, user) + res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) + }).catch((error: Error) => { + next(error) + }) + } + + return (req: Request, res: Response, next: NextFunction) => { + models.sequelize.query(`SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL`, + { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) + .then((authenticatedUser: { data: User }) => { + const user = utils.queryResultToJson(authenticatedUser) + if (user.data?.id && user.data.totpSecret !== '') { + res.status(401).json({ + status: 'totp_token_required', + data: { + tmpToken: security.authorize({ + userId: user.data.id, + type: 'password_valid_needs_second_factor_token' + }) + } + }) + } else if (user.data?.id) { + afterLogin(user, res, next) + } else { + res.status(401).send(res.__('Invalid email or password.')) + } + }).catch((error: Error) => { + next(error) + }) + } +``` + +```javascript +import {BasketModel} from "../../../models/basket"; + +module.exports = function login () { + function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { + BasketModel.findOrCreate({ where: { UserId: user.data.id } }) + .then(([basket]: [BasketModel, boolean]) => { + const token = security.authorize(user) + user.bid = basket.id // keep track of original basket + security.authenticatedUsers.put(token, user) + res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) + }).catch((error: Error) => { + next(error) + }) + } + + return (req: Request, res: Response, next: NextFunction) => { + models.sequelize.query('SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL', + { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) + .then((authenticatedUser: { data: User }) => { + const user = utils.queryResultToJson(authenticatedUser) + if (user.data?.id && user.data.totpSecret !== '') { + res.status(401).json({ + status: 'totp_token_required', + data: { + tmpToken: security.authorize({ + userId: user.data.id, + type: 'password_valid_needs_second_factor_token' + }) + } + }) + } else if (user.data?.id) { + afterLogin(user, res, next) + } else { + res.status(401).send(res.__('Invalid email or password.')) + } + }).catch((error: Error) => { + next(error) + }) + } +``` diff --git a/content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md b/content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md new file mode 100644 index 0000000000000..bb69f5b49c3fe --- /dev/null +++ b/content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: javascript-node-security/variable-sql-statement-injection + language: JavaScript + severity: Warning +title: Avoid SQL injections +--- +## Metadata +**ID:** `javascript-node-security/variable-sql-statement-injection` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Check for variable declarations in a SQL statement where there is potential for SQL injections. + +## Non-Compliant Code Examples +```javascript +var table = 'baz'; + +const foo = "SELECT foo FROM " + table; +const select = `SELECT foo FROM ${table}`; +var del = `DELETE FROM ${table} WHERE condition;`; +let update = ' UPDATE ' + + table + + "SET column1 = value1, column2 = value2" + + "WHERE condition;"; +``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-key.md b/content/en/static_analysis/rules/jsx-react/jsx-key.md new file mode 100644 index 0000000000000..440b7ca7f83bd --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/jsx-key.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: jsx-react/jsx-key + language: JavaScript + severity: Error +title: Prevent missing key props in iterators/collection literals +--- +## Metadata +**ID:** `jsx-react/jsx-key` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +In JSX you need to specify a key prop for each item of a list because if it's missing it could lead to unexpected renders or stale UI. This rule checks for possible JSX lists and warns if the key prop is missing. + +## Non-Compliant Code Examples +```jsx +[<>]; +[, foo, ]; +[, foo, ]; +data.map(x => ); +data.map(x => {x}); +data.map(x => {x}); +data.map(x => { return {x}}); +data.map(x => { return {x}}); +data.map(function(x) { return {x}}); +data.map(function(x) { return {x}}); +Array.from([1, 2, 3], (x) => {x}); +``` + +## Compliant Code Examples +```jsx +[, , ]; +data.map((x) => {x}); +Array.from([1, 2, 3], (x) => {x}); + +``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md b/content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md new file mode 100644 index 0000000000000..67dfdcee08419 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md @@ -0,0 +1,69 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: jsx-react/jsx-no-comment-textnodes + language: JavaScript + severity: Warning +title: Avoid comments from being inserted as text nodes +--- +## Metadata +**ID:** `jsx-react/jsx-no-comment-textnodes` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +As JSX mixes HTML and JavaScript together, it's easy to mistake text nodes and add comments to them. This rule prevents you from accidentally leaving comments as HTML text. + +## Non-Compliant Code Examples +```jsx +var Hello = createReactClass({ + render: function() { + return ( +
+ asd /* empty div */ +
+ ); + } +}); + +var Hello = createReactClass({ + render: function() { + return ( +
+ /* empty div */ +
+ ); + } +}); +``` + +## Compliant Code Examples +```jsx +var Hello = createReactClass({ + displayName: 'Hello', + render: function() { + return
{/* empty div */}
; + } +}); + +var Hello = createReactClass({ + displayName: 'Hello', + render: function() { + return
; + } +}); + +var Hello = createReactClass({ + displayName: 'Hello', + render: function() { + return
; + } +}); +``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md b/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md new file mode 100644 index 0000000000000..795e56bac664f --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: jsx-react/jsx-no-duplicate-key + language: JavaScript + severity: Error +title: Ensures unique key prop +--- +## Metadata +**ID:** `jsx-react/jsx-no-duplicate-key` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +Duplicate JSX element keys can lead to unexpected behavior. Keys should always be unique. + +## Non-Compliant Code Examples +```jsx +[, foo, ]; +[, foo]; +[, ]; +data.map(x => ); +data.map(x => {x}); +data.map(x => {x}); +data.map(x => { return {x}}); +data.map(function(x) { return {x}}); +Array.from([1, 2, 3], (x) => {x}); +``` + +## Compliant Code Examples +```jsx +[, foo, ]; +data.map(x => { return {x}}); +``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md b/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md new file mode 100644 index 0000000000000..905e02b8cd335 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: jsx-react/jsx-no-duplicate-props + language: JavaScript + severity: Error +title: Avoid duplicate properties in JSX +--- +## Metadata +**ID:** `jsx-react/jsx-no-duplicate-props` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +Providing duplicate properties to JSX elements can produce unexpected results in your project. + +## Non-Compliant Code Examples +```jsx +; +foo; + +``` + +## Compliant Code Examples +```jsx +; +``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md b/content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md new file mode 100644 index 0000000000000..db33a2d3356a7 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md @@ -0,0 +1,49 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: jsx-react/jsx-no-target-blank + language: JavaScript + severity: Warning +title: Prevent target='_blank' security risks +--- +## Metadata +**ID:** `jsx-react/jsx-no-target-blank` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Security + +## Description +Using `target="_blank"` in an anchor (``) tag allows a link to be opened in a new browser tab or window. + +A malicious website opened through `target="_blank"` can change the `window.opener.location` to a phishing page, potentially misleading users. + +This rule enforces using `rel="noreferrer"` with on links that have the `target="_blank"` attribute. It might not be needed if you target modern browsers, but is still recommended to follow it as a best practice. + +#### Known Limitations + +This rule does not support custom link components without an `href`, `target` and `rel` properties. + +## Non-Compliant Code Examples +```jsx +var Hello = +var Hello = +var Nested = +var Nested = +``` + +## Compliant Code Examples +```jsx +var Hello =

+var Hello =

+var Hello = +var Hello = +var Hello = +var Hello = +var Hello = +``` diff --git a/content/en/static_analysis/rules/jsx-react/no-children-prop.md b/content/en/static_analysis/rules/jsx-react/no-children-prop.md new file mode 100644 index 0000000000000..8741ec3406ff8 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/no-children-prop.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: jsx-react/no-children-prop + language: JavaScript + severity: Warning +title: Avoid passing children as props +--- +## Metadata +**ID:** `jsx-react/no-children-prop` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Children should be used as actual children not a JSX prop. This rule enforces the use of children as an element between the JSX element opening and closing tag. + +## Non-Compliant Code Examples +```jsx +
; + +} />; +; + +React.createElement("div", { children: 'Children' }); +``` + +## Compliant Code Examples +```jsx +
Children
; +Children; + + Child 1 + Child 2 +; +React.createElement("div", {}, 'Children'); +React.createElement("div", 'Child 1', 'Child 2'); +``` diff --git a/content/en/static_analysis/rules/jsx-react/no-danger-with-children.md b/content/en/static_analysis/rules/jsx-react/no-danger-with-children.md new file mode 100644 index 0000000000000..5b836c964f172 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/no-danger-with-children.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: jsx-react/no-danger-with-children + language: JavaScript + severity: Warning +title: Avoid using children with dangerouslySetInnerHTML +--- +## Metadata +**ID:** `jsx-react/no-danger-with-children` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +If both `children` and `dangerouslySetInnerHTML` are set, it's unclear which one should take precedence. React will throw a warning if both are set. This rule enforces the use of either `children` or `dangerouslySetInnerHTML` but not both. + +## Non-Compliant Code Examples +```jsx +
{Children}
; +Children; +; +React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); +React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); +``` + +## Compliant Code Examples +```jsx +
; +; +
Children
; +Children; +React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }); +React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }); +React.createElement("div", {}, "Children"); +React.createElement("Hello", {}, "Children"); +``` diff --git a/content/en/static_analysis/rules/jsx-react/no-deprecated.md b/content/en/static_analysis/rules/jsx-react/no-deprecated.md new file mode 100644 index 0000000000000..ce0824fddf4f5 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/no-deprecated.md @@ -0,0 +1,73 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: jsx-react/no-deprecated + language: JavaScript + severity: Warning +title: Avoid deprecated methods +--- +## Metadata +**ID:** `jsx-react/no-deprecated` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +As React evolves, methods are deprecated over time. This rule warns you about deprecated methods. + +## Non-Compliant Code Examples +```jsx +React.render(, root); +React.unmountComponentAtNode(root); +React.findDOMNode(this.refs.foo); +React.renderToString(); +React.renderToStaticMarkup(); +React.createClass({ /* Class object */ }); + +//Any factories under React.DOM +React.DOM.div(); + +import React, { PropTypes } from 'react'; + +// old lifecycles (since React 16.9) +componentWillMount() { } +componentWillReceiveProps() { } +componentWillUpdate() { } + +// React 18 deprecations +import { render } from 'react-dom'; +ReactDOM.render(
, container); + +import { hydrate } from 'react-dom'; +ReactDOM.hydrate(
, container); + +import { unmountComponentAtNode } from 'react-dom'; +ReactDOM.unmountComponentAtNode(container); + +import { renderToNodeStream } from 'react-dom/server'; +ReactDOMServer.renderToNodeStream(element); +``` + +## Compliant Code Examples +```jsx +import { PropTypes } from 'prop-types'; + +UNSAFE_componentWillMount() { } +UNSAFE_componentWillReceiveProps() { } +UNSAFE_componentWillUpdate() { } + +ReactDOM.createPortal(child, container); + +import { createRoot } from 'react-dom/client'; +const root = createRoot(container); +root.unmount(); + +import { hydrateRoot } from 'react-dom/client'; +const root = hydrateRoot(container, ); +``` diff --git a/content/en/static_analysis/rules/jsx-react/no-render-return-value.md b/content/en/static_analysis/rules/jsx-react/no-render-return-value.md new file mode 100644 index 0000000000000..41f206bf860be --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/no-render-return-value.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: jsx-react/no-render-return-value + language: JavaScript + severity: Warning +title: Avoid usage of the return value of ReactDOM.render +--- +## Metadata +**ID:** `jsx-react/no-render-return-value` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Using the return value of the render method is a legacy feature. If you have a valid reason to reference the root React instance, you should assign a callback ref to the root component. + +## Non-Compliant Code Examples +```jsx +const inst = ReactDOM.render(, document.body); +``` + +## Compliant Code Examples +```jsx +ReactDOM.render(, document.body); + +ReactDOM.render(, document.body, doSomethingWithInst); +``` diff --git a/content/en/static_analysis/rules/jsx-react/no-string-refs.md b/content/en/static_analysis/rules/jsx-react/no-string-refs.md new file mode 100644 index 0000000000000..12c9f8de3bec0 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/no-string-refs.md @@ -0,0 +1,58 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: jsx-react/no-string-refs + language: JavaScript + severity: Warning +title: Avoid using string references +--- +## Metadata +**ID:** `jsx-react/no-string-refs` + +**Language:** JavaScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +String references are a legacy feature of React, use a reference callback instead. + +## Non-Compliant Code Examples +```jsx +var Hello = createReactClass({ + render: function() { + return
; + } +}); +var Hello = createReactClass({ + render: function() { + return
Hello, world.
; + } +}); +var Hello = createReactClass({ + componentDidMount: function() { + var component = this.refs.hello; + // ...do something with component + }, + render: function() { + return
Hello, world.
; + } +}); +``` + +## Compliant Code Examples +```jsx +var Hello = createReactClass({ + componentDidMount: function() { + var component = this.hello; + // ...do something with component + }, + render() { + return
{ this.hello = c; }}>Hello, world.
; + } +}); +``` diff --git a/content/en/static_analysis/rules/jsx-react/require-render-return.md b/content/en/static_analysis/rules/jsx-react/require-render-return.md new file mode 100644 index 0000000000000..5df03cc0d9570 --- /dev/null +++ b/content/en/static_analysis/rules/jsx-react/require-render-return.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: jsx-react/require-render-return + language: JavaScript + severity: Error +title: Enforce class for returning value in render function +--- +## Metadata +**ID:** `jsx-react/require-render-return` + +**Language:** JavaScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +It's easy to forget the return value of a class component render method. This rule warns when the render method does not return a value. + +## Non-Compliant Code Examples +```jsx +var Hello = createReactClass({ + render() { +
Hello
; + } +}); + +class Hello extends React.Component { + render() { +
Hello
; + } +} +``` + +## Compliant Code Examples +```jsx +var Hello = createReactClass({ + render() { + return
Hello
; + } +}); + +class Hello extends React.Component { + render() { + return
Hello
; + } +} +``` diff --git a/content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md b/content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md new file mode 100644 index 0000000000000..011587838e1f4 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/ambiguous-class-name + language: Python + severity: Notice +title: make sure class names are readable +--- +## Metadata +**ID:** `python-best-practices/ambiguous-class-name` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +In some fonts, some characters are indistinguishable from the numerals one and zero, such as, O looks like a zero. Use characters that are not ambiguous. + +## Non-Compliant Code Examples +```python +class I: # use i instead + pass +``` + +## Compliant Code Examples +```python +class MyClass: + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md b/content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md new file mode 100644 index 0000000000000..0d96a676b5713 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/ambiguous-function-name + language: Python + severity: Notice +title: make sure function names are readable +--- +## Metadata +**ID:** `python-best-practices/ambiguous-function-name` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +In some fonts, these characters are indistinguishable from the numerals one and zero. Use characters that are not ambiguous. + +## Non-Compliant Code Examples +```python +def I(): # use i instead + pass +``` + +## Compliant Code Examples +```python +def i(): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md b/content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md new file mode 100644 index 0000000000000..52a3d88f7877a --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/ambiguous-variable-name + language: Python + severity: Notice +title: make sure variable names are readable +--- +## Metadata +**ID:** `python-best-practices/ambiguous-variable-name` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +In some fonts, some characters are indistinguishable from the numerals one and zero, such as, O looks like a zero. Use characters that are not ambiguous. + +## Non-Compliant Code Examples +```python +I = 1 # use i instead +``` + +## Compliant Code Examples +```python +def i(): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/any-type-disallow.md b/content/en/static_analysis/rules/python-best-practices/any-type-disallow.md new file mode 100644 index 0000000000000..5f5368079a3ae --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/any-type-disallow.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/any-type-disallow + language: Python + severity: Warning +title: do not use Any type +--- +## Metadata +**ID:** `python-best-practices/any-type-disallow` + +**Language:** Python + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Use the `Any` type very carefully. Most of the time, the `Any` type is used because we do not know exactly what type is being used. If you want to specify that a value can be of any type, use `object` instead of `Any`. + + +#### Learn More + + - [Python documentation: the `Any` type](https://docs.python.org/3/library/typing.html#the-any-type) + +## Non-Compliant Code Examples +```python +my_var: Any = 1 +``` + +```python +def foo(x: Any): # do not use Any, use a specific type + pass +``` + +## Compliant Code Examples +```python +my_var: int = 1 + +def my_function(a: str) -> str: + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/argument-same-name.md b/content/en/static_analysis/rules/python-best-practices/argument-same-name.md new file mode 100644 index 0000000000000..2f7b1a3735381 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/argument-same-name.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/argument-same-name + language: Python + severity: Error +title: do not have arguments with the same name +--- +## Metadata +**ID:** `python-best-practices/argument-same-name` + +**Language:** Python + +**Severity:** Error + +**Category:** Error Prone + +## Description +Function parameters cannot have the same name. Each function parameter must have a distinct name. + +## Non-Compliant Code Examples +```python +def foo(bar, bar: int): # use another name for the second argument + pass +``` + +## Compliant Code Examples +```python +def foo(bar, baz): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md b/content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md new file mode 100644 index 0000000000000..c2e8caaa822e0 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/assertraises-specific-exception + language: Python + severity: Warning +title: assertRaises must check for a specific exception +--- +## Metadata +**ID:** `python-best-practices/assertraises-specific-exception` + +**Language:** Python + +**Severity:** Warning + +**Category:** Error Prone + +## Description +When checking an exception, check for a specific exception. Checking for `Exception` may bypass the verification of the correct behavior of the program. + +Using a generic exception is error-prone and give a false sense of correctness. Instead, use the correct exception to check against. + +## Non-Compliant Code Examples +```python +self.assertRaises(Exception, foo) # check a specific Exception, not a generic one +``` + +## Compliant Code Examples +```python +self.assertRaises(ValueError, foo) +``` diff --git a/content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md b/content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md new file mode 100644 index 0000000000000..e63f25fd05eb3 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/avoid-duplicate-keys + language: Python + severity: Warning +title: Avoid duplicate keys in dictionaries +--- +## Metadata +**ID:** `python-best-practices/avoid-duplicate-keys` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Keys in a dictionary must be unique. + +## Non-Compliant Code Examples +```python +dict = { + "key1": "key2", + "key2": "key3", + "key3": "key4", + "key1": "bla" +} + +``` + +## Compliant Code Examples +```python +dict = { + "key1": "key2", + "key2": "key3", + "key3": "key4", +} + +``` diff --git a/content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md b/content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md new file mode 100644 index 0000000000000..429fef63c2ac6 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md @@ -0,0 +1,54 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Performance + id: python-best-practices/avoid-string-concat + language: Python + severity: Warning +title: avoid string concatenation +--- +## Metadata +**ID:** `python-best-practices/avoid-string-concat` + +**Language:** Python + +**Severity:** Warning + +**Category:** Performance + +## Description +Concatenation of multiple strings is not efficient and make the code hard to read and understand. + +Instead of concatenating multiple strings, use an f-string or a format string. + +#### Learn More + + - [Python Documentation: `str.format()`](https://docs.python.org/3/library/stdtypes.html#str.format) + - [Python Documentation - f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) + +## Non-Compliant Code Examples +```python +"my" + awesome + "string" +plop = "super" + "awesome" + "text" +``` + +## Compliant Code Examples +```python +"my {0} string".format(awesome) +f"my {awesome} string" +plop = "superawesometext" + +function( + tags = ( + user_tags + + s.get("tags", []) + + [ + f"schedule_id:{s['_id']}", + f"schedule_name:{s['schedule_name']}", + f"git_ref:{schedule_git_ref}", + ] +) +) +``` diff --git a/content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md b/content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md new file mode 100644 index 0000000000000..bb034ef5da930 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/class-methods-use-self + language: Python + severity: Error +title: Class methods should not use self +--- +## Metadata +**ID:** `python-best-practices/class-methods-use-self` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +In a class method (that is not a class method nor a static method), the first argument must be `self` by convention. + +#### Learn More + + - [Method Objects on the Python documentation](https://docs.python.org/3.8/tutorial/classes.html#method-objects) + - [PEP8 style guide](https://peps.python.org/pep-0008/#function-and-method-arguments) + +## Non-Compliant Code Examples +```python +class Foo: + def bar(bar): # use def bar(self) instead + pass +``` + +## Compliant Code Examples +```python +class Foo: + @staticmethod + def static_method(bar): + pass + + @classmethod + def class_method(bar): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md b/content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md new file mode 100644 index 0000000000000..f9d71581127d3 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/collection-while-iterating + language: Python + severity: Error +title: do not modify a dictionary while iterating on it +--- +## Metadata +**ID:** `python-best-practices/collection-while-iterating` + +**Language:** Python + +**Severity:** Error + +**Category:** Error Prone + +## Description +Never update a dictionary while iterating on it. If you wish to update the dictionary, create a new dictionary from the existing values. + +## Non-Compliant Code Examples +```python +i = 0 +for element in my_list: + my_list["stuff"] = i # modifying a dictionary while iterating + i += 1 +``` + +## Compliant Code Examples +```python +i = 0 +new_list = {} +for element in my_list: + new_list["stuff"] = i # putting value to a new dictionary + i += 1 +``` diff --git a/content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md b/content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md new file mode 100644 index 0000000000000..cf22b69206d5e --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/comment-fixme-todo-ownership + language: Python + severity: Notice +title: TODO and FIXME comments must have ownership +--- +## Metadata +**ID:** `python-best-practices/comment-fixme-todo-ownership` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When using `TODO` or `FIXME`, specify who write the annotation. It's a best practice to remind you who created the annotation and have potential context and information about this issue. + +## Non-Compliant Code Examples +```python +# TODO fix this function +def my_function(): + pass + +# FIXME fix this function +def my_function(): + pass +``` + +## Compliant Code Examples +```python +# TODO(bob) fix this function +def my_function(): + pass + +# FIXME(julien) fix this function +def my_other_function(): + pass + +# FIXME[julien] fix this function +def my_other_function(): + pass + +# TODO[bob] fix this function +def my_function(): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md b/content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md new file mode 100644 index 0000000000000..f021e24fa4099 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/comparison-constant-left + language: Python + severity: Notice +title: in comparisons, variables must be left +--- +## Metadata +**ID:** `python-best-practices/comparison-constant-left` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +In a comparison that compare a variable with a value, put the variable on the left side of the comparison expression. + +## Non-Compliant Code Examples +```python +if 1 <= i: # use i >= 1 + pass +``` + +```python +if 1.0 <= i: # use i >= 1.0 + pass +``` + +## Compliant Code Examples +```python +if i >= 1: + pass + +if 0 < nextSx <= len(subject): + px = nextPx + sx = nextSx + +if 1 in ctx: + print("foo") + +``` diff --git a/content/en/static_analysis/rules/python-best-practices/condition-similar-block.md b/content/en/static_analysis/rules/python-best-practices/condition-similar-block.md new file mode 100644 index 0000000000000..34be359370f61 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/condition-similar-block.md @@ -0,0 +1,48 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/condition-similar-block + language: Python + severity: Warning +title: if conditions must have different code blocks +--- +## Metadata +**ID:** `python-best-practices/condition-similar-block` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Code in the branches of an `if` condition must be unique. If you have duplicated branches, merge the conditions. + +## Non-Compliant Code Examples +```python +if foo: + printf("bar") +elif baz: + printf("bar2") +elif bap: + # same code than the if condition + printf("bar") +else: + # same code than the if condition + printf("bar") +``` + +## Compliant Code Examples +```python +if foo: + printf("bar") +elif baz: + printf("bar2") +elif bap: + printf("bar3") +else: + printf("bar4") +``` diff --git a/content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md b/content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md new file mode 100644 index 0000000000000..056a1f263f635 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md @@ -0,0 +1,48 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/ctx-manager-enter-exit-defined + language: Python + severity: Error +title: ensure that both __exit__ and __enter__ are defined +--- +## Metadata +**ID:** `python-best-practices/ctx-manager-enter-exit-defined` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +Methods `__enter__` and `__exit__` must be declared together. If one method is missing, we should make sure both are defined. + +#### Learn More + + - [contextlib documentation](https://docs.python.org/3/library/contextlib.html) + +## Non-Compliant Code Examples +```python +class Ctx: + def __exit__(self, *exc): # the method __enter__ should be defined. + pass +``` + +```python +class Ctx: + def __enter__(self): # the method __exit__ should also be defined. + pass +``` + +## Compliant Code Examples +```python +class Ctx: + def __enter__(self): + pass + def __exit__(self, *exc): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md b/content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md new file mode 100644 index 0000000000000..1a5cf0cf6e217 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md @@ -0,0 +1,66 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/dataclass-special-methods + language: Python + severity: Notice +title: do not use special method on data class +--- +## Metadata +**ID:** `python-best-practices/dataclass-special-methods` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Data classes (annotated with @dataclass) do not use special method such as `__init__`, `__gt__`, and more. + +## Non-Compliant Code Examples +```python +@dataclass +class _Leaf(Generic[T]): + parent: _Leaf + value: T + + def __init__(self, value: Optional[T] = None): + self.value = value + self.parent = self + + def update(self, value: T): + self.value = value + return self + + def __lt__(self, other: _Leaf): + return repr(self) < repr(other) + + def __gt__(self, other: _Leaf): + return repr(self) > repr(other) + + # __eq__ should not be used + def __eq__(self, other: _Leaf): + return repr(self) == repr(other) + + def __repr__(self): + return self.value +``` + +## Compliant Code Examples +```python +@dataclass +class _Leaf(Generic[T]): + parent: _Leaf + value: T + + def update(self, value: T): + self.value = value + return self + + def __repr__(self): + return self.value +``` diff --git a/content/en/static_analysis/rules/python-best-practices/equal-basic-types.md b/content/en/static_analysis/rules/python-best-practices/equal-basic-types.md new file mode 100644 index 0000000000000..bae5144a88694 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/equal-basic-types.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/equal-basic-types + language: Python + severity: Warning +title: check equal is used on consistent basic types +--- +## Metadata +**ID:** `python-best-practices/equal-basic-types` + +**Language:** Python + +**Severity:** Warning + +**Category:** Error Prone + +## Description +When comparing basic types (string, integer, float), we should always values of the same types. + +## Non-Compliant Code Examples +```python +1 == "1" # Comparing an integer and a string +1.0 == "foo" # Comparing a float and a string +``` + +## Compliant Code Examples +```python +1 == 1 +"abc" == "def" +a == 1 +a == b +``` diff --git a/content/en/static_analysis/rules/python-best-practices/exception-inherit.md b/content/en/static_analysis/rules/python-best-practices/exception-inherit.md new file mode 100644 index 0000000000000..8c0b71fde3c9a --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/exception-inherit.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/exception-inherit + language: Python + severity: Warning +title: ensure exception inherit a base exception +--- +## Metadata +**ID:** `python-best-practices/exception-inherit` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +New `Exception` must inherit the base `Exception`. Always use another exception as parent or use at least the `Exception` base class. + +#### Learn More + +- [Python Documentation: User-defined Exceptions](https://docs.python.org/3/tutorial/errors.html#user-defined-exceptions) + +## Non-Compliant Code Examples +```python +class CustomException: + """An Invalid exception class.""" +``` + +## Compliant Code Examples +```python +class CustomException(Exception): + """An Invalid exception class.""" +``` diff --git a/content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md b/content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md new file mode 100644 index 0000000000000..203393c3e7c20 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md @@ -0,0 +1,72 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/finally-no-break-continue-return + language: Python + severity: Warning +title: do not use break or continue in finally block +--- +## Metadata +**ID:** `python-best-practices/finally-no-break-continue-return` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +When using `return`, `break` or `continue` in a `finally` block, it will stop the spread of any exceptions that were thrown in the `try`, `else`, or `except` blocks and will disregard any return statements. + +#### Learn More + + - [Official Python documentation](https://docs.python.org/3/reference/compound_stmts.html#except) + +## Non-Compliant Code Examples +```python +try: + client_obj.get_url(url) +except (URLError, ValueError): + client_obj.remove_url(url) +except SocketTimeout: + client_obj.handle_url_timeout(url) +finally: + break # avoid break in the finally block +``` + +```python +try: + client_obj.get_url(url) +except (URLError, ValueError): + client_obj.remove_url(url) +except SocketTimeout: + client_obj.handle_url_timeout(url) +finally: + return 0 # avoid return in the finally block +``` + +```python +try: + client_obj.get_url(url) +except (URLError, ValueError): + client_obj.remove_url(url) +except SocketTimeout: + client_obj.handle_url_timeout(url) +finally: + continue # avoid continue in the finally block +``` + +## Compliant Code Examples +```python +try: + client_obj.get_url(url) +except (URLError, ValueError): + client_obj.remove_url(url) +except SocketTimeout: + client_obj.handle_url_timeout(url) +finally: + print("cleanup the mess") +``` diff --git a/content/en/static_analysis/rules/python-best-practices/function-already-exists.md b/content/en/static_analysis/rules/python-best-practices/function-already-exists.md new file mode 100644 index 0000000000000..a1cd3a88a3ff9 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/function-already-exists.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/function-already-exists + language: Python + severity: Error +title: a function must be defined only once +--- +## Metadata +**ID:** `python-best-practices/function-already-exists` + +**Language:** Python + +**Severity:** Error + +**Category:** Error Prone + +## Description +A function should only be defined once. Make sure you use unique name for each function in a module. + +## Non-Compliant Code Examples +```python + +def my_function(): + pass + +def foo(): + pass + +def my_function(): # function already defined + pass + +``` + +## Compliant Code Examples +```python + +def my_function(): + pass + +def foo(): + pass + +def my_other_function(): + pass + +``` diff --git a/content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md b/content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md new file mode 100644 index 0000000000000..f9a5247ec86e0 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/function-variable-argument-name + language: Python + severity: Warning +title: Do not assign to function arguments +--- +## Metadata +**ID:** `python-best-practices/function-variable-argument-name` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +A function parameter should only be read and not be modified. If your intent is to modify the value of the parameter, return the value in the function and handle the new value in the caller of the function. + +## Non-Compliant Code Examples +```python +def func(arg1, arg2): + arg1 = foo # assign to a variable that is an argument +``` + +```python +def func(arg1, arg2): + (arg1, arg3, arg2) = foo # assign to a variable that is an argument +``` + +## Compliant Code Examples +```python +def func(arg1, arg2): + arg3 = foo +``` diff --git a/content/en/static_analysis/rules/python-best-practices/generic-exception-last.md b/content/en/static_analysis/rules/python-best-practices/generic-exception-last.md new file mode 100644 index 0000000000000..d7cae4a1e2ba2 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/generic-exception-last.md @@ -0,0 +1,57 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/generic-exception-last + language: Python + severity: Notice +title: If using generic exception, it should be last +--- +## Metadata +**ID:** `python-best-practices/generic-exception-last` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When multiple exceptions are caught, the generic `Exception` must be caught last. Catching `Exception` is very generic and if placed before specific exceptions, it will caught all exceptions and specific exception handlers will not be caught. + +For this reason, generic `Exception` must be the last to be handled to let specific exception handlers to be triggered/executed. + +#### Learn More + +- [Python tutorials on errors](https://docs.python.org/3/tutorial/errors.html) + +## Non-Compliant Code Examples +```python +try: + pass +except Exception: + pass +except FileNotFound as e: + pass +``` + +## Compliant Code Examples +```python +try: + pass +except MyError: + pass +except Exception as e: + pass +``` + +```python +try: + pass +except MyError: + pass +except FileNotFound as e: + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/get-set-arguments.md b/content/en/static_analysis/rules/python-best-practices/get-set-arguments.md new file mode 100644 index 0000000000000..091a45dd72adc --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/get-set-arguments.md @@ -0,0 +1,69 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/get-set-arguments + language: Python + severity: Warning +title: getter/setter must have 1 or 2 arguments respectively +--- +## Metadata +**ID:** `python-best-practices/get-set-arguments` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Ensure that getter and setter have the right number of parameters: + - getters must have exactly one parameter (the instance we are reading from) + - setters must have exactly two parameters (the instance we are updating and the associated value) + +#### Learn More + + - [Python documentation - property](https://docs.python.org/3/library/functions.html#property) + +## Non-Compliant Code Examples +```python +class Foo: + @property + def get_my_attribute(self, foo): # getter should have only one argument + return self.my_attribute + + @attr.setter + def set_attr(self, v, bar): # setter should have only two arguments + self._attr = v + + @attr.deleter + def del_attr(self, foo): # deleter should have only one argument + del self._attr +``` + +## Compliant Code Examples +```python +class Foo: + def get_my_attribute(self): + return self.my_attribute + + def get_my_attribute(self, foo): # Not a property or attr, valid + return self.my_attribute + + @property + def get_my_attribute(self): + return self.my_attribute + + def set_my_attribute(self, v): + self.my_attribute = v + + @attr.setter + def set_attr(self, v): + self._attr = v + + @attr.deleter + def del_attr(self,): + return self._attr +``` diff --git a/content/en/static_analysis/rules/python-best-practices/if-return-no-else.md b/content/en/static_analysis/rules/python-best-practices/if-return-no-else.md new file mode 100644 index 0000000000000..035265b18a04c --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/if-return-no-else.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/if-return-no-else + language: Python + severity: Notice +title: when an if condition returns an value, else is not necessary +--- +## Metadata +**ID:** `python-best-practices/if-return-no-else` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +If the code in the `if` branch returns a value, do not have the `else` branch present. + +## Non-Compliant Code Examples +```python +if bla: + foo() + return 1 +else: # unnecessary, remove the else branch + return 2 +``` + +## Compliant Code Examples +```python +if bla: + foo() + return 1 +return 2 +``` + +```python +if bla: + foo() +else: + return 2 +``` diff --git a/content/en/static_analysis/rules/python-best-practices/import-modules-twice.md b/content/en/static_analysis/rules/python-best-practices/import-modules-twice.md new file mode 100644 index 0000000000000..a8ca70c531380 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/import-modules-twice.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/import-modules-twice + language: Python + severity: Warning +title: module imported twice +--- +## Metadata +**ID:** `python-best-practices/import-modules-twice` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Always define a module once. Do not import the module multiple times and/or import the module using different methods. It makes the code harder to understand. Import a module once and for all with only one import mechanism. + +## Non-Compliant Code Examples +```python +import logging +import logging # do not import the same module again. + +``` + +## Compliant Code Examples +```python +import typing +from typing import cast +``` + +```python +import logging +``` + +```python +import logging +from logging import foo # not an issue since we are using a from import + +``` diff --git a/content/en/static_analysis/rules/python-best-practices/import-single-module.md b/content/en/static_analysis/rules/python-best-practices/import-single-module.md new file mode 100644 index 0000000000000..9954df84a41b9 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/import-single-module.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/import-single-module + language: Python + severity: Notice +title: only one module to import per import statement +--- +## Metadata +**ID:** `python-best-practices/import-single-module` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Import using the `import` keyword should be done on separate lines. + +## Non-Compliant Code Examples +```python +import os, sys # when using an import statement, import one module at a time +``` + +## Compliant Code Examples +```python +from collections.abc import Mapping, Sequence +import os +import sys +from typing import Any, NewType +``` diff --git a/content/en/static_analysis/rules/python-best-practices/init-call-parent.md b/content/en/static_analysis/rules/python-best-practices/init-call-parent.md new file mode 100644 index 0000000000000..f90641be401c7 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/init-call-parent.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/init-call-parent + language: Python + severity: Warning +title: use super() to call the parent constructor +--- +## Metadata +**ID:** `python-best-practices/init-call-parent` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Calling the parent constructor should be done by calling `super()`, not by calling the parent object directly. + +## Non-Compliant Code Examples +```python +class Class(Parent): + def __init__(self): + SomeClass.__init__(self) # should use super() +``` + +## Compliant Code Examples +```python +# More than one parent, we need to know exactly what +# parent constructor to use +class DummyCIVisibilityWriter(DummyWriterMixin, CIVisibilityWriter): + def __init__(self, *args, **kwargs): + CIVisibilityWriter.__init__(self, *args, **kwargs) + DummyWriterMixin.__init__(self, *args, **kwargs) + self._encoded = None +``` + +```python +class Class(Parent): + def foo(self): + SomeClass.__init__(self) # outside of __init__, valid +``` + +```python +class Class(Parent): + def __init__(self): + super().__init__(self) +``` diff --git a/content/en/static_analysis/rules/python-best-practices/init-method-required.md b/content/en/static_analysis/rules/python-best-practices/init-method-required.md new file mode 100644 index 0000000000000..145bd56892f49 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/init-method-required.md @@ -0,0 +1,106 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/init-method-required + language: Python + severity: Notice +title: ensure classes have an __init__ method +--- +## Metadata +**ID:** `python-best-practices/init-method-required` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Ensure that a class has an `__init__` method. This check is bypassed when the class is a data class (annotated with @dataclass). + +## Non-Compliant Code Examples +```python +class Foo: # need to define __init__ + def foo(bar): + pass + def bar(baz): + pass +``` + +## Compliant Code Examples +```python +# dataclass do not require an init class +@dataclass +class Requests: + cpu: float # expressed in cpu cores + memory: int # expressed in bytes + + @staticmethod + def from_pod(pod: V1Pod): + cpu = 0.0 + memory = 0 + + for container in pod.spec.containers: + cpu += parse_cpu_string(container.resources.requests["cpu"]) + memory += parse_memory_string(container.resources.requests["memory"]) + + return Requests(cpu, memory) + + def add(self, other): + self.cpu += other.cpu + self.memory += other.memory + +``` + +```python +class Foo(Bar): + + def foo(): + pass +``` + +```python +class UserLoginTest(TestCase): + def setUp(self): + self.username = 'testuser' + self.password = 'testpassword' + self.user = User.objects.create_user(username=self.username, password=self.password) + + def test_correct_credentials(self): + user = authenticate(username=self.username, password=self.password) + self.assertIsNotNone(user) + self.assertEqual(user, self.user) + + def test_incorrect_credentials(self): + user = authenticate(username=self.username, password='wrongpassword') + self.assertIsNone(user) +``` + +```python +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + ] +``` + +```python +@dataclass +class Foo: # no __init__ required for dataclass + value = 51 +``` + +```python +class Foo: + def __init__(self): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/init-no-return-value.md b/content/en/static_analysis/rules/python-best-practices/init-no-return-value.md new file mode 100644 index 0000000000000..d5712ed737291 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/init-no-return-value.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/init-no-return-value + language: Python + severity: None +title: No return in an __init__ function +--- +## Metadata +**ID:** `python-best-practices/init-no-return-value` + +**Language:** Python + +**Severity:** None + +**Category:** Error Prone + +## Description +The `__init__` method (and the `__new__` method) should never return a non-`None` value. + +#### Learn More + + - [`__init__` function on the Python datamodel documentation](https://docs.python.org/3/reference/datamodel.html#object.__init__) + +## Non-Compliant Code Examples +```python +class Foo: + def __init__(self): + # __init__ should not return a value + return 3 + + def my_method(): + return 10 +``` + +## Compliant Code Examples +```python +class Foo: + def __init__(self): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md b/content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md new file mode 100644 index 0000000000000..698c53f5b891a --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/invalid-strip-call + language: Python + severity: Notice +title: strip() argument should not have duplicate characters +--- +## Metadata +**ID:** `python-best-practices/invalid-strip-call` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When using `.strip()`, you only need to pass the letters you want to split on. There is no need to specify the same letter twice. + +## Non-Compliant Code Examples +```python +"Hello World".strip("Hello") # letter l is present twice in the string +``` + +## Compliant Code Examples +```python +"Hello World".strip("Helo") # letter l is present twice in the string +``` diff --git a/content/en/static_analysis/rules/python-best-practices/logging-no-format.md b/content/en/static_analysis/rules/python-best-practices/logging-no-format.md new file mode 100644 index 0000000000000..87446c8e1f34d --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/logging-no-format.md @@ -0,0 +1,37 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/logging-no-format + language: Python + severity: Notice +title: do not use format string with logging functions +--- +## Metadata +**ID:** `python-best-practices/logging-no-format` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Avoid using format string with the `format` method when logging information. + +## Non-Compliant Code Examples +```python +import logging +import shlex + +logging.info("error {0}".format(plop)) # use instead logging.info("error %s", plop) +``` + +## Compliant Code Examples +```python +import logging + +logging.info("wfwef") +``` diff --git a/content/en/static_analysis/rules/python-best-practices/method-hidden.md b/content/en/static_analysis/rules/python-best-practices/method-hidden.md new file mode 100644 index 0000000000000..fcaa77c406db1 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/method-hidden.md @@ -0,0 +1,48 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/method-hidden + language: Python + severity: Warning +title: a method has the same name than an attribute +--- +## Metadata +**ID:** `python-best-practices/method-hidden` + +**Language:** Python + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Make sure that class attribute and class methods have a unique name without any collision. + +## Non-Compliant Code Examples +```python +class MyClass: + def __init__(self, something): + self.foo = something + + def bla(foo): + pass + + def foo(self): # hidden by self.foo + pass +``` + +## Compliant Code Examples +```python +class MyClass: + def __init__(self, something): + self.foo = something + + def bla(foo): + pass + + def bar(self): # hidden by self.foo + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/nested-blocks.md b/content/en/static_analysis/rules/python-best-practices/nested-blocks.md new file mode 100644 index 0000000000000..f6fe127599c12 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/nested-blocks.md @@ -0,0 +1,78 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-best-practices/nested-blocks + language: Python + severity: Error +title: Do not have too many nested blocks +--- +## Metadata +**ID:** `python-best-practices/nested-blocks` + +**Language:** Python + +**Severity:** Error + +**Category:** Code Style + +## Description +Avoid to nest too many loops together. Having too many loops make your code harder to understand. +Prefer to organize your code in functions and unit of code you can clearly understand. + +#### Learn More + + - [Computer Programming wikibooks - Minimize nesting](https://en.wikibooks.org/wiki/Computer_Programming/Coding_Style/Minimize_nesting) + + +## Non-Compliant Code Examples +```python +def func(): + for v in bla: + if bar: + if baz: + if wiz: # too many nested elements + pass +``` + +```python +def func(): + if foo: + pass + else: + if bar: + if baz: + if wiz: # too many nested elements + pass +``` + +```python +def func(): + if foo: + if bar: + if baz: + if wiz: # too many nested elements + pass +``` + +```python +def func(): + if foo: + pass + elif bar: + if bar: + if baz: + if wiz: # too many nested elements + pass + else: + pass +``` + +## Compliant Code Examples +```python +while Foo: + while Bar: + print("foobar") +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md b/content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md new file mode 100644 index 0000000000000..c334dcc0264d0 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/no-assert-on-tuples + language: Python + severity: Error +title: no assert on tuples +--- +## Metadata +**ID:** `python-best-practices/no-assert-on-tuples` + +**Language:** Python + +**Severity:** Error + +**Category:** Error Prone + +## Description +Do not assert on tuples. Asserting on tuples will always evaluate to `True` if the tuple is not empty. Instead, assert on each value rather than asserting on a tuple. + +## Non-Compliant Code Examples +```python +assert (1, 2) # do not assert on tuples +``` + +## Compliant Code Examples +```python +assert x + +assert exitcode == 42, (stdout, stderr) +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-assert.md b/content/en/static_analysis/rules/python-best-practices/no-assert.md new file mode 100644 index 0000000000000..6ec19cbc902f3 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-assert.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-assert + language: Python + severity: Error +title: do not use assert in production code +--- +## Metadata +**ID:** `python-best-practices/no-assert` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +Avoid having `assert` statements in code as they are not being used when . This rule does not apply to test files, such as, files ending with `_test.py`. + +## Non-Compliant Code Examples +```python +def foo(bar): + assert bar # no assert in production code +``` + +## Compliant Code Examples +```python +ctx1.set_baggage_item("test", 3) +ctx2 = SpanContext() +# Assert in a test file does not raise an error +assert "test" not in ctx2._baggage +``` + +```python +def foo(bar): + assert bar # assert ok in test code (see filename) +``` + +```python +def foo(bar): + assert bar # assert ok in test code +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-bare-except.md b/content/en/static_analysis/rules/python-best-practices/no-bare-except.md new file mode 100644 index 0000000000000..61536c42df172 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-bare-except.md @@ -0,0 +1,70 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-bare-except + language: Python + severity: Warning +title: do not use bare except +--- +## Metadata +**ID:** `python-best-practices/no-bare-except` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Avoid bare `except`. Try to always use specialized exception names in `except` blocks. + +## Non-Compliant Code Examples +```python +try: + print("foo") +except: # use a specialized exception name + print("bar") +``` + +## Compliant Code Examples +```python +try: + parsed = json.loads(response.body) +except json.JSONDecodeError: + log.warning("Test skips request responded with invalid JSON '%s'", response.body) + return +``` + +```python +try: + pass +except (TypeError, ValueError): + log.debug( + ( + "received invalid x-datadog-* headers, " + "trace-id: %r, parent-id: %r, priority: %r, origin: %r, tags:%r" + ), + trace_id, + parent_span_id, + sampling_priority, + origin, + tags_value, + ) +``` + +```python +try: + foo() +except MyError as e: + bar() +``` + +```python +try: + print("foo") +except MyException: + print("bar") +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-bare-raise.md b/content/en/static_analysis/rules/python-best-practices/no-bare-raise.md new file mode 100644 index 0000000000000..e411e131185d4 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-bare-raise.md @@ -0,0 +1,49 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-bare-raise + language: Python + severity: Warning +title: Do not use a raise statement without a specific exception +--- +## Metadata +**ID:** `python-best-practices/no-bare-raise` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Never use a bare raise and always use a specific exception. Using a specific exception helps you distinguish errors in your program and have appropriate error handling code. + +## Non-Compliant Code Examples +```python +def myfunc(): + raise # should use specific exception + +if foo: + raise +else: + func1() + raise + +for v in list: + do_something() + raise +``` + +## Compliant Code Examples +```python +def myfunc(): + raise MyException + +try: + foo() +except MyException: + raise # re-raise exception +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-base-exception.md b/content/en/static_analysis/rules/python-best-practices/no-base-exception.md new file mode 100644 index 0000000000000..18abec10ada1c --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-base-exception.md @@ -0,0 +1,55 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-base-exception + language: Python + severity: Notice +title: do not raise base exception +--- +## Metadata +**ID:** `python-best-practices/no-base-exception` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not raise `Exception` and `BaseException`. These are too generic. Having generic exceptions makes it difficult to differentiate errors in a program. Use a specific exception, for example, `ValueError`, or create your own instead of using generic ones. + +#### Learn More + + - [Stop using `raise Exception`](https://jerrynsh.com/stop-using-exceptions-like-this-in-python/#2-stop-using-raise-exception) + +## Non-Compliant Code Examples +```python +if foo: + raise Exception("bla") +elif bar: + raise Exception +else: + raise Exception +``` + +```python +def use_base_exception(): + raise Exception + raise Exception("awesome") +``` + +```python +for v in list: + raise BaseException +``` + +## Compliant Code Examples +```python +if foo: + print("bar") +else: + raise ValueError +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-datetime-today.md b/content/en/static_analysis/rules/python-best-practices/no-datetime-today.md new file mode 100644 index 0000000000000..d37b621c4d7f2 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-datetime-today.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-datetime-today + language: Python + severity: Notice +title: do not use datetime.today() +--- +## Metadata +**ID:** `python-best-practices/no-datetime-today` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Avoid using `datetime.today()` and use instead `datetime.now()`. The two calls are equivalent (as mentioned in the [official documentation](https://docs.python.org/3/library/datetime.html#datetime.date.today)) and the use of `now()` is more explicit than `today()`. + +Using `today()` makes you think it only returns the year/month/day but it returns a full timestamp. For this reason, prefer using `now()`. + +## Non-Compliant Code Examples +```python +from datetime import datetime +print("foo") +bla = datetime.today() # use datetime.now() instead +``` + +## Compliant Code Examples +```python +from datetime import datetime +print("foo") +bla = datetime.now() +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-double-not.md b/content/en/static_analysis/rules/python-best-practices/no-double-not.md new file mode 100644 index 0000000000000..2e9b3b05492d6 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-double-not.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/no-double-not + language: Python + severity: Warning +title: do not use double negation +--- +## Metadata +**ID:** `python-best-practices/no-double-not` + +**Language:** Python + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Do not use two negation. It makes the code more complex to read and understand. Instead of using two negation, use the expression directly. + +## Non-Compliant Code Examples +```python +if not not foo: # just use if foo + pass +``` + +## Compliant Code Examples +```python +if not foo: + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md b/content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md new file mode 100644 index 0000000000000..69dbaf2f9ae56 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-double-unary-operator + language: Python + severity: Error +title: do not use operator -- and ++ +--- +## Metadata +**ID:** `python-best-practices/no-double-unary-operator` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +Operator `--` and `++` do not exists in Python. Increment or decrement the variable appropriately. + +## Non-Compliant Code Examples +```python +--n # use n = n - 1 +++n # use n = n + 1 + +``` + +## Compliant Code Examples +```python +n = n + 1 +n = n - 1 +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md b/content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md new file mode 100644 index 0000000000000..f8de46813cd59 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/no-duplicate-base-class + language: Python + severity: Warning +title: use a base class only once +--- +## Metadata +**ID:** `python-best-practices/no-duplicate-base-class` + +**Language:** Python + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Classes should not have the same superclass specified twice. Each superclass must be unique. + +## Non-Compliant Code Examples +```python +class MyClass: + pass + + +# The SuperClass parent is specified twice +class MyClassTwo(SuperClass, SuperClass): + pass +``` + +## Compliant Code Examples +```python +class MyClass: + pass + + +class MyClassTwo(SuperClass): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-equal-unary.md b/content/en/static_analysis/rules/python-best-practices/no-equal-unary.md new file mode 100644 index 0000000000000..78fe13cd09d79 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-equal-unary.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-equal-unary + language: Python + severity: Error +title: do not use operations =+ and =- +--- +## Metadata +**ID:** `python-best-practices/no-equal-unary` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +Operator `=+` and `=-` do not exist in Python. The code is valid but is unlikely doing what the developer wants to achieve. + +## Non-Compliant Code Examples +```python +# =+ does not exists in Python, use n = n + 3 +n =+ 3 + +# =- does not exists in Python, use n = n - 3 +n =- 3 +``` + +## Compliant Code Examples +```python +n = n + 3 + +n = n - 3 + +foo = -1 +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-exit.md b/content/en/static_analysis/rules/python-best-practices/no-exit.md new file mode 100644 index 0000000000000..a1d52afc61556 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-exit.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-exit + language: Python + severity: Error +title: do not use exit() +--- +## Metadata +**ID:** `python-best-practices/no-exit` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +Use `sys.exit()` instead of `exit()`. Exit is a [builtin](https://docs.python.org/3/library/constants.html#exit) and done mostly for the console. `sys.exit()` is done for program with a proper return argument ([see documentation](https://docs.python.org/3/library/sys.html#sys.exit)). + +#### Learn More + - [Python documentation for `sys.exit()`](https://docs.python.org/3/library/sys.html#sys.exit) + +## Non-Compliant Code Examples +```python +print("bla") +exit(0) # use sys.exit() instead +``` + +## Compliant Code Examples +```python +import sys +print("bla") +sys.exit(0) +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-generic-exception.md b/content/en/static_analysis/rules/python-best-practices/no-generic-exception.md new file mode 100644 index 0000000000000..50e2b1b795502 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-generic-exception.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-generic-exception + language: Python + severity: Warning +title: Do not use generic exceptions +--- +## Metadata +**ID:** `python-best-practices/no-generic-exception` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +The specific error must be raised, not a generic `Exception`. Use the exact exception(s) you want to handle and have a recovery handler for each exception that your program may raise. + +#### Learn More + + - [Avoid using `except Exception`](https://jerrynsh.com/stop-using-exceptions-like-this-in-python/#3-avoid-using-except-exception) + +## Non-Compliant Code Examples +```python +a = 2 +b = 0 +try: + c = a /b +except Exception as e: + pass +``` + +## Compliant Code Examples +```python +a = 2 +b = 0 +try: + c = a /b +except ValueError as e: + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-if-true.md b/content/en/static_analysis/rules/python-best-practices/no-if-true.md new file mode 100644 index 0000000000000..3667005f7dff7 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-if-true.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-best-practices/no-if-true + language: Python + severity: Notice +title: do not compare to True in a condition +--- +## Metadata +**ID:** `python-best-practices/no-if-true` + +**Language:** Python + +**Severity:** Notice + +**Category:** Code Style + +## Description +Do not use `variable == True`, just use `variable`. Comparing against `True` makes the code more complicated to read. + +## Non-Compliant Code Examples +```python +if foo == True: # just used if foo + print("bar") +``` + +## Compliant Code Examples +```python +if foo: + print("bar") +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md b/content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md new file mode 100644 index 0000000000000..555801f945df9 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-range-loop-with-len + language: Python + severity: Error +title: Do not use for i in range(len()) +--- +## Metadata +**ID:** `python-best-practices/no-range-loop-with-len` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +Do not iterate over an array using `for in range(len(array))`. Use instead `for i in array`. + +#### Learn More + + - [Python Loop Through an Array](https://www.w3schools.com/python/gloss_python_array_loop.asp) + +## Non-Compliant Code Examples +```python +for i in range(len(tab)): # iterate directly over the array + bla(tab[i]) +``` + +```python +for i in range(len(tab)): # iterate directly over the array + tab[i] = bla +``` + +## Compliant Code Examples +```python +for i in tab: + bla(i) +``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-silent-exception.md b/content/en/static_analysis/rules/python-best-practices/no-silent-exception.md new file mode 100644 index 0000000000000..caf244b30a26b --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/no-silent-exception.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/no-silent-exception + language: Python + severity: Error +title: Do not ignore Exception with a pass statement +--- +## Metadata +**ID:** `python-best-practices/no-silent-exception` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +Using the `pass` statement in an exception block ignores the exception. Exceptions should never be ignored. Instead, the user must add code to notify an exception occurred and attempt to handle it or recover from it. + +## Non-Compliant Code Examples +```python +a = 2 +b = 0 +try: + c = a /b +except Exception as e: + pass # should use a regular statement and not ignore the exception +``` + +## Compliant Code Examples +```python +a = 2 +b = 0 +try: + c = a /b +except ValueError as e: + print(e) + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/open-add-flag.md b/content/en/static_analysis/rules/python-best-practices/open-add-flag.md new file mode 100644 index 0000000000000..59352d039538e --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/open-add-flag.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/open-add-flag + language: Python + severity: Error +title: do not define an open flag for reading +--- +## Metadata +**ID:** `python-best-practices/open-add-flag` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +If a flag is opened for read-only, no need to put a flag to open the file. + + +#### Learn More + + - [Python documentation: `open()`](https://docs.python.org/3/library/functions.html#open) + +## Non-Compliant Code Examples +```python +def print_foo(): + with open("myfile.txt", "r") as myfile: # no need to specify the "r" flag + content = myfile.read() + + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + hasher.update(chunk) +``` + +## Compliant Code Examples +```python +def print_foo(): + with open("myfile.txt") as myfile: + content = myfile.read() +``` diff --git a/content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md b/content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md new file mode 100644 index 0000000000000..595c8d3b08b68 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md @@ -0,0 +1,37 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/os-environ-no-assign + language: Python + severity: Error +title: assigning to os.environ does not clear the environment +--- +## Metadata +**ID:** `python-best-practices/os-environ-no-assign` + +**Language:** Python + +**Severity:** Error + +**Category:** Error Prone + +## Description +Assigning to `os.environ` does not clear the environment. To clear the environment, use `os.environ.clear()` + +## Non-Compliant Code Examples +```python +import os + +os.environ = {} # use os.environ.clear +``` + +## Compliant Code Examples +```python +import os + +os.environ.clear() + +``` diff --git a/content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md b/content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md new file mode 100644 index 0000000000000..a1822159ef15c --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/raising-not-implemented + language: Python + severity: Warning +title: Do not raise NotImplemented - it does not exists +--- +## Metadata +**ID:** `python-best-practices/raising-not-implemented` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Code should not raise `NotImplemented` and instead use `NotImplementedError`. `NotImplemented` is a value (as per the [documentation](https://docs.python.org/3/library/constants.html#NotImplemented), not an exception. The proper exception is [NotImplementedError](https://docs.python.org/3/library/exceptions.html#NotImplementedError) + +#### Learn More + + - [NotImplementedError documentation](https://docs.python.org/3/library/exceptions.html#NotImplementedError) + +## Non-Compliant Code Examples +```python +a = 1 +b = 2 +raise NotImplemented # use NotImplementedError instead +c = 3 +``` + +## Compliant Code Examples +```python +a = 1 +b = 2 +raise NotImplementedError +c = 3 +``` diff --git a/content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md b/content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md new file mode 100644 index 0000000000000..413961cad5c80 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/return-bytes-not-string + language: Python + severity: Notice +title: __bytes__ method should returns bytes, not string +--- +## Metadata +**ID:** `python-best-practices/return-bytes-not-string` + +**Language:** Python + +**Severity:** Notice + +**Category:** Error Prone + +## Description +The `__bytes__` method should not return a string and instead, ensure to return bytes. + +## Non-Compliant Code Examples +```python +class MyClass: + def __bytes__(self): + pass + return "123" # should return b"123" +``` + +## Compliant Code Examples +```python +class MyClass: + def __bytes__(self): + pass + return b"123" +``` diff --git a/content/en/static_analysis/rules/python-best-practices/return-outside-function.md b/content/en/static_analysis/rules/python-best-practices/return-outside-function.md new file mode 100644 index 0000000000000..5f0b4c9fdc6ff --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/return-outside-function.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/return-outside-function + language: Python + severity: Notice +title: do not return outside a function +--- +## Metadata +**ID:** `python-best-practices/return-outside-function` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +All `return` statements must be within a function. Putting a `return` statement outside of a function may have unexpected behaviors (such as exiting the program early). + +## Non-Compliant Code Examples +```python +class Foo: + return 1 # return must be done within a function +``` + +```python +def foo(): + return "bar" + +return "bar" # return must be done within a function +``` + +## Compliant Code Examples +```python +def foobar() + return 2 +``` diff --git a/content/en/static_analysis/rules/python-best-practices/self-assignment.md b/content/en/static_analysis/rules/python-best-practices/self-assignment.md new file mode 100644 index 0000000000000..797b098da73c1 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/self-assignment.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/self-assignment + language: Python + severity: Notice +title: do not assign to itself +--- +## Metadata +**ID:** `python-best-practices/self-assignment` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not assign a value to itself. Instead, assign the value to a different variable to make the data flow clear to read and understand. + +## Non-Compliant Code Examples +```python +def foo(): + bar = bar # avoid self assignment +``` + +## Compliant Code Examples +```python +def foo(): + bar = baz +``` diff --git a/content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md b/content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md new file mode 100644 index 0000000000000..0f64865eac30c --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md @@ -0,0 +1,53 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: python-best-practices/slots-no-single-string + language: Python + severity: Error +title: __slots__ should not be a single string +--- +## Metadata +**ID:** `python-best-practices/slots-no-single-string` + +**Language:** Python + +**Severity:** Error + +**Category:** Error Prone + +## Description +The `__slots__` attribute must be a non-string iterable. + +#### Learn More + + - [Python Wiki: Using slots](https://wiki.python.org/moin/UsingSlots) + +## Non-Compliant Code Examples +```python +class MyClass: + __slots__ = "attr" # should be an iterable + + def __init__(self): + pass +``` + +## Compliant Code Examples +```python +from django.apps import AppConfig + + +class TweetsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'tweets' +``` + +```python +class MyClass: + __slots__ = ("attr", ) + + def __init__(self): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md b/content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md new file mode 100644 index 0000000000000..5a85a7925dd5b --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md @@ -0,0 +1,54 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/special-methods-arguments + language: Python + severity: Error +title: ensure special methods have the correct arguments +--- +## Metadata +**ID:** `python-best-practices/special-methods-arguments` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +For all special methods for an class (`__add__`, `__sub__`, and more) make sure the method has the correct number of arguments. + +## Non-Compliant Code Examples +```python +class GFG: + + def __init__(self, val): + self.val = val + + def __next__(self, val2, val3): # invalid, we should have only one argument. + return GFG(self.val + val2.val) +``` + +```python +class GFG: + + def __init__(self, val): + self.val = val + + def __add__(self, val2, val3): # we should hvea only two arguments. + return GFG(self.val + val2.val) +``` + +## Compliant Code Examples +```python +class GFG: + + def __init__(self, val): + self.val = val + + def __add__(self, val2): + return GFG(self.val + val2.val) +``` diff --git a/content/en/static_analysis/rules/python-best-practices/static-method-no-self.md b/content/en/static_analysis/rules/python-best-practices/static-method-no-self.md new file mode 100644 index 0000000000000..0c9a7708ad6b3 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/static-method-no-self.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/static-method-no-self + language: Python + severity: Error +title: do not use self as parameter for static methods +--- +## Metadata +**ID:** `python-best-practices/static-method-no-self` + +**Language:** Python + +**Severity:** Error + +**Category:** Best Practices + +## Description +A static method makes no use of an instance. Therefore, the `self` argument is not needed nor useful and should not be used. + +## Non-Compliant Code Examples +```python +class Foo: + @staticmethod + def foo(self, bar): # no need to use the self argument with a @staticmethod + pass +``` + +## Compliant Code Examples +```python +class Foo: + @staticmethod + def foo(bar): + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md b/content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md new file mode 100644 index 0000000000000..19db77d99f217 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/too-many-nested-if + language: Python + severity: Warning +title: do not use too many nested if conditions +--- +## Metadata +**ID:** `python-best-practices/too-many-nested-if` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Too many nested loops make the code hard to read and understand. Simplify your code by removing nesting levels and separate code in small units. + +## Non-Compliant Code Examples +```python +if foo: + if bar: + if baz: + if bao: + pass +``` + +## Compliant Code Examples +```python +if foo: + if bar: + if baz: + pass +``` diff --git a/content/en/static_analysis/rules/python-best-practices/too-many-while.md b/content/en/static_analysis/rules/python-best-practices/too-many-while.md new file mode 100644 index 0000000000000..5d7377293e0ec --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/too-many-while.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/too-many-while + language: Python + severity: Warning +title: do not use too many nested loops and conditions +--- +## Metadata +**ID:** `python-best-practices/too-many-while` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +A program should have a maximum level of nesting loops. If your program has too many nested loops (`if`/`for`/`while`), consider refactoring your program to avoid too many nesting levels. + +## Non-Compliant Code Examples +```python +while bla: + while foo: + while bar: + while baz: + pass + +``` + +## Compliant Code Examples +```python +while bla: + while foo: + while bar: + pass + +``` diff --git a/content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md b/content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md new file mode 100644 index 0000000000000..532db22e84de9 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/type-check-isinstance + language: Python + severity: Notice +title: use isinstance instead of type +--- +## Metadata +**ID:** `python-best-practices/type-check-isinstance` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Using `isinstance` is faster than `type` but also consider inheritance, which makes it more accurate. + +## Non-Compliant Code Examples +```python +# use isinstance instead of +if type(Foo()) == Foo: + print("is foo") +``` + +## Compliant Code Examples +```python +raise ValueError("target %s config %s has type of %s" % (target, config_content, type(config_content))) +``` + +```python +if isinstance(Bar(), Foo): + print("foo") +``` diff --git a/content/en/static_analysis/rules/python-best-practices/unreachable-code.md b/content/en/static_analysis/rules/python-best-practices/unreachable-code.md new file mode 100644 index 0000000000000..11daefb5dc8b9 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/unreachable-code.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/unreachable-code + language: Python + severity: Notice +title: avoid unreachable code +--- +## Metadata +**ID:** `python-best-practices/unreachable-code` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Avoid unreachable code. If the code cannot be reached because of a coding mistake, fix the business logic. If the code should not be used, remove it. + + +#### Learn More + + - [Carnegie Mellon University: Avoid having unreachable code](https://wiki.sei.cmu.edu/confluence/display/android/Avoid+having+unreachable+code) + +## Non-Compliant Code Examples +```python +def foo(): + return 3 + foo() # unreachable code + pass # unreachable code +``` + +## Compliant Code Examples +```python +def foo(): + foo() + pass + return 3 + +``` diff --git a/content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md b/content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md new file mode 100644 index 0000000000000..16b06a582a312 --- /dev/null +++ b/content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-best-practices/use-callable-not-hasattr + language: Python + severity: Notice +title: do not use hasattr to check if a value is callable +--- +## Metadata +**ID:** `python-best-practices/use-callable-not-hasattr` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not make any check using `hasattr` to check if a function is callable since the object may have redefine `__getattr__`. Instead, use `callable()`. + +#### Learn More + + - [Python Documentation: callable() built-in](https://docs.python.org/3/library/functions.html#callable) + +## Non-Compliant Code Examples +```python +hasattr(x, '__call__') # use callable +``` + +## Compliant Code Examples +```python +callable(x) +``` diff --git a/content/en/static_analysis/rules/python-code-style/assignment-names.md b/content/en/static_analysis/rules/python-code-style/assignment-names.md new file mode 100644 index 0000000000000..90e2436dfdc2c --- /dev/null +++ b/content/en/static_analysis/rules/python-code-style/assignment-names.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-code-style/assignment-names + language: Python + severity: Error +title: variable names must use snake_case +--- +## Metadata +**ID:** `python-code-style/assignment-names` + +**Language:** Python + +**Severity:** Error + +**Category:** Code Style + +## Description +Ensure that variable names use `snake_case` and not `camelCase`. + +#### Learn More + +- [PEP8 - Naming Style](https://peps.python.org/pep-0008/#descriptive-naming-styles) + +## Non-Compliant Code Examples +```python +fooBar = foobar() +``` + +```python +firstVariable, secondVariable = functioncall() +``` + +## Compliant Code Examples +```python +hello = 1 +``` + +```python +fooBAr = foobar() +``` diff --git a/content/en/static_analysis/rules/python-code-style/class-name.md b/content/en/static_analysis/rules/python-code-style/class-name.md new file mode 100644 index 0000000000000..9b7e795b40459 --- /dev/null +++ b/content/en/static_analysis/rules/python-code-style/class-name.md @@ -0,0 +1,93 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-code-style/class-name + language: Python + severity: Notice +title: class name should be CamelCase +--- +## Metadata +**ID:** `python-code-style/class-name` + +**Language:** Python + +**Severity:** Notice + +**Category:** Code Style + +## Description +Class names should be `CamelCase` and not `camelCase` or `snake_case`. + +#### Learn More + + - [PEP8 style guide](https://peps.python.org/pep-0008/#descriptive-naming-styles) + +## Non-Compliant Code Examples +```python +class _runtimeMetricsStatus(type): + pass +``` + +```python +class myClass(Parent): + def __init__(self): + pass + + +``` + +## Compliant Code Examples +```python +class REQUESTS_MODE(IntEnum): + AGENTLESS_EVENTS = 0 + EVP_PROXY_EVENTS = 1 +``` + +```python +class _RuntimeMetricsStatus(type): + pass +``` + +```python +class Migration(migrations.Migration): + + dependencies = [ + ('tweets', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='tweet', + name='parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='tweets.tweet'), + ), + migrations.DeleteModel( + name='Reply', + ), + ] +``` + +```python +class MyClass(Parent): + def __init__(self): + pass + +class TestRestapiV4Lock(FunctionalTestController): + pass + +class TestS3Storage(TestCase): + pass + + +class TestS35Storage(TestCase): + pass + + + +class TestS35Storage(TestCase): + pass + +``` diff --git a/content/en/static_analysis/rules/python-code-style/function-naming.md b/content/en/static_analysis/rules/python-code-style/function-naming.md new file mode 100644 index 0000000000000..76416f658c724 --- /dev/null +++ b/content/en/static_analysis/rules/python-code-style/function-naming.md @@ -0,0 +1,67 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-code-style/function-naming + language: Python + severity: Notice +title: function name and parameters should use snake_case +--- +## Metadata +**ID:** `python-code-style/function-naming` + +**Language:** Python + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that function use `snake_case`. + +This rule is not valid for tests files (prefixed by `test_` or suffixed by `_test.py`) because testing requires some camel case methods, such as, `tearDown`, `setUp`, and more. + +#### Learn More + + - [Python Documentation Testing: `setUp()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUp) + +## Non-Compliant Code Examples +```python +def my_function(myParameter, otherParameter): + pass +``` + +```python +def myFunction(arg1, arg2): + pass + +def myOtherFunction(): + pass +``` + +## Compliant Code Examples +```python +# name used in many testing frameworks. Do not warn on it +def tearDown(self): + """After each test case, reset and remove the dummy tracer""" + super(TracerTestCase, self).tearDown() +``` + +```python +class TestModel(unittest.TestCase): + def setUp(self): # used in a file model_test.py, skip the rule for setUp and tearDown + pass + + def tearDown(self): # used in a file model_test.py, skip the rule for setUp and tearDown + pass + + def test_violation_category(self): + self.assertEqual(ViolationCategory.BEST_PRACTICE.value, 1) + self.assertEqual(ViolationCategory.DESIGN.value, 2) + v1 = Violation("bla", 1, "description", 2, ViolationCategory.BEST_PRACTICE, 10, "notool") + self.assertEqual(v1.get_category_string(), "Best Practices") + v1 = Violation("bla", 1, "description", 2, 1, 10, "notool") + self.assertEqual(v1.get_category_string(), "Unknown") +``` diff --git a/content/en/static_analysis/rules/python-code-style/max-class-lines.md b/content/en/static_analysis/rules/python-code-style/max-class-lines.md new file mode 100644 index 0000000000000..873be711fa561 --- /dev/null +++ b/content/en/static_analysis/rules/python-code-style/max-class-lines.md @@ -0,0 +1,138 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-code-style/max-class-lines + language: Python + severity: Warning +title: classes must be less than 100 lines +--- +## Metadata +**ID:** `python-code-style/max-class-lines` + +**Language:** Python + +**Severity:** Warning + +**Category:** Code Style + +## Description +A class must stay short (less than 100 lines) to be easy to understand. If your class or function is more than 100 lines, you should refactor your code and ensure that your class is less than 100 lines. + +## Non-Compliant Code Examples +```python +class MyClass: + def __init__(self): + pass + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + def foo(self): + pass +``` + +## Compliant Code Examples +```python +class MyClass: + def __init__(self): + pass + + def foo(self): + pass +``` diff --git a/content/en/static_analysis/rules/python-code-style/max-function-lines.md b/content/en/static_analysis/rules/python-code-style/max-function-lines.md new file mode 100644 index 0000000000000..9afecd61d1cf6 --- /dev/null +++ b/content/en/static_analysis/rules/python-code-style/max-function-lines.md @@ -0,0 +1,259 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-code-style/max-function-lines + language: Python + severity: Error +title: Functions must be less than 200 lines +--- +## Metadata +**ID:** `python-code-style/max-function-lines` + +**Language:** Python + +**Severity:** Error + +**Category:** Code Style + +## Description +Ensure that a function is not too long. A function should be less than 100 lines. Otherwise, it's too long and hard to understand. + +## Non-Compliant Code Examples +```python +def myfunction(): + foo() + bar() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pass +``` + +## Compliant Code Examples +```python +def myfunction(args): + foo() + bar() + pass +``` diff --git a/content/en/static_analysis/rules/python-design/function-too-long.md b/content/en/static_analysis/rules/python-design/function-too-long.md new file mode 100644 index 0000000000000..ed0777e1c5006 --- /dev/null +++ b/content/en/static_analysis/rules/python-design/function-too-long.md @@ -0,0 +1,134 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-design/function-too-long + language: Python + severity: Warning +title: functions must have less than 100 lines +--- +## Metadata +**ID:** `python-design/function-too-long` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Function should be short to be easy to understand and maintain. Functions more of 100 lines trigger a warning and should be refactored into smaller units of code. + +## Non-Compliant Code Examples +```python +def myfunc(): # function is too long + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pass +``` + +## Compliant Code Examples +```python +def myfunc(): + pass +``` diff --git a/content/en/static_analysis/rules/python-django/http-response-from-request.md b/content/en/static_analysis/rules/python-django/http-response-from-request.md new file mode 100644 index 0000000000000..ee9ce1411d90c --- /dev/null +++ b/content/en/static_analysis/rules/python-django/http-response-from-request.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-django/http-response-from-request + language: Python + severity: Error +title: Lack of sanitization of user data +--- +## Metadata +**ID:** `python-django/http-response-from-request` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +The response sent with an `HttpResponse` contains unsanitized request data. The data should be sanitized before being returns in an `HttpResponse`. + +#### Learn More + + - [CWE-20: Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html) + +## Non-Compliant Code Examples +```python +def execute_command(request): + data = request.GET.get("data") + print("foobar") + foo = HttpResponse("data: '{0}'".format(data)) + foo = HttpResponse(data) + return HttpResponse("data: '{0}'".format(data)) +``` + +## Compliant Code Examples +```python +def execute_command(request): + data = request.GET.get("data") + print("foobar") + return HttpResponse("user '{user}' does not exist".format(sanitize_data(data))) + +``` diff --git a/content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md b/content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md new file mode 100644 index 0000000000000..f91b81853f8c8 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-django/http-response-with-json-dumps + language: Python + severity: Notice +title: use JsonResponse instead of HttpResponse to send JSON data +--- +## Metadata +**ID:** `python-django/http-response-with-json-dumps` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Use `JsonResponse` instead of `HttpResponse` when attempting to send JSON data. + +## Non-Compliant Code Examples +```python +import json + +from django.http import HttpResponse + +response_data = {} +response_data['result'] = 'error' +response_data['message'] = 'Some error message' +return HttpResponse(json.dumps(response_data)) # use a JsonResponse to send JSON data + +``` + +## Compliant Code Examples +```python +import json + +from django.http import HttpResponse + +response_data = {} +response_data['result'] = 'error' +response_data['message'] = 'Some error message' +return JsonResponse(response_data) +``` diff --git a/content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md b/content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md new file mode 100644 index 0000000000000..09a07b6e8b0b7 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-django/jsonresponse-no-content-type + language: Python + severity: Notice +title: do not specify content-type for JsonResponse +--- +## Metadata +**ID:** `python-django/jsonresponse-no-content-type` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +The `JsonResponse` is already setting the content type of the response. Do not redefine the content type being sent. + +## Non-Compliant Code Examples +```python +import json + +from django.http import HttpResponse + +response_data = {} +response_data['result'] = 'error' +response_data['message'] = 'Some error message' +return JsonResponse(response_data, content_type="application/json") # content-type is not necessary for JsonResponse +``` + +## Compliant Code Examples +```python +import json + +from django.http import HttpResponse + +response_data = {} +response_data['result'] = 'error' +response_data['message'] = 'Some error message' +return JsonResponse(response_data) # content-type is not necessary for JsonResponse +``` diff --git a/content/en/static_analysis/rules/python-django/model-charfield-max-length.md b/content/en/static_analysis/rules/python-django/model-charfield-max-length.md new file mode 100644 index 0000000000000..2286a3fab02e4 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/model-charfield-max-length.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-django/model-charfield-max-length + language: Python + severity: Warning +title: always specify max_length for a Charfield +--- +## Metadata +**ID:** `python-django/model-charfield-max-length` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +On a `Charfield`, define the attribute `max_length` to specify the maximum size of a field. + +## Non-Compliant Code Examples +```python +class Person(models.Model): + first_name = models.CharField() # define max_length + last_name = models.CharField() # define max_length +``` + +## Compliant Code Examples +```python +class Person(models.Model): + first_name = models.CharField(max_length=20) + last_name = models.CharField(max_length=40) +``` diff --git a/content/en/static_analysis/rules/python-django/model-help-text.md b/content/en/static_analysis/rules/python-django/model-help-text.md new file mode 100644 index 0000000000000..feb1e6aeadc72 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/model-help-text.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-django/model-help-text + language: Python + severity: Notice +title: use help_text to document model columns +--- +## Metadata +**ID:** `python-django/model-help-text` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Use `help_text` to document the fields used in your database. + +#### Learn More + + - [Django Documentation: `help_text`](https://docs.djangoproject.com/en/4.2/ref/models/fields/#help-text) + +## Non-Compliant Code Examples +```python +class MyModel(models.Model): + my_field = models.DateField() + last_name = models.CharField(max_length=40) # add help_text to explain what this field is doing +``` + +## Compliant Code Examples +```python +class MyModel(models.Model): + my_field = models.DateField(help_text = "Use format YYYY/MM/DD") +``` diff --git a/content/en/static_analysis/rules/python-django/no-null-boolean.md b/content/en/static_analysis/rules/python-django/no-null-boolean.md new file mode 100644 index 0000000000000..478864f235207 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/no-null-boolean.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-django/no-null-boolean + language: Python + severity: Notice +title: do not use NullBooleanField +--- +## Metadata +**ID:** `python-django/no-null-boolean` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +The `NullBooleanField` type is deprecated. Use the `BooleanField` instead. + +## Non-Compliant Code Examples +```python +class Person(models.Model): + is_adult = models.NullBooleanField() # use BooleanField + +``` + +## Compliant Code Examples +```python +class Person(models.Model): + is_adult = models.BooleanField(null=True) +``` diff --git a/content/en/static_analysis/rules/python-django/no-unicode-on-models.md b/content/en/static_analysis/rules/python-django/no-unicode-on-models.md new file mode 100644 index 0000000000000..544c715a5a75c --- /dev/null +++ b/content/en/static_analysis/rules/python-django/no-unicode-on-models.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-django/no-unicode-on-models + language: Python + severity: Warning +title: do not use __unicode__ +--- +## Metadata +**ID:** `python-django/no-unicode-on-models` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Do not use `__unicode__` on Django models. The field `__unicode__` is used for Python 2. Use `__str__` instead, `__str__` is used with Python 3. + +## Non-Compliant Code Examples +```python +class Person(models.Model): + + def __unicode__(self): # do not define __unicode__, define __str__ + pass +``` + +## Compliant Code Examples +```python +class Person(models.Model): + + def __str__(self): + "person" +``` diff --git a/content/en/static_analysis/rules/python-django/open-filename-from-request.md b/content/en/static_analysis/rules/python-django/open-filename-from-request.md new file mode 100644 index 0000000000000..16cbaa5681ef5 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/open-filename-from-request.md @@ -0,0 +1,77 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-django/open-filename-from-request + language: Python + severity: Error +title: Filename coming from the request +--- +## Metadata +**ID:** `python-django/open-filename-from-request` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Improper validation of input data, leading to potential data leaks. The path should be checked and validated before opening a file in order to prevent opening random files and leaking data. + +#### Learn More + + - [CWE-22: Improper Limitation of a Pathname to a Restricted Directory](https://cwe.mitre.org/data/definitions/22.html) + +## Non-Compliant Code Examples +```python +def download_file1(request): + url = request.GET.get("filename") + print(f"url of the file: {url}") + file = open(url, "rb") + + with open(url) as f: + pass + pass + + +def download_file2(request): + url = request.POST.get("filename") + print(f"url of the file: {url}") + file = open(url, "rb") + + with open(url) as f: + pass + pass + +def download_file3(request): + url = request.BLA.get("filename") + print(f"url of the file: {url}") + file = open(url, "rb") + + with open(url) as f: + pass + pass +``` + +## Compliant Code Examples +```python +import os + +def download_file(request): + url = request.GET.get("filename") + + if ".." in url: + return + + sanitized_path = os.path.realpath(url, strict=True) + + print(f"url of the file: {url}") + file = open(sanitized_path, "rb") + + with open(sanitized_path) as f: + pass + pass +``` diff --git a/content/en/static_analysis/rules/python-django/os-system-from-request.md b/content/en/static_analysis/rules/python-django/os-system-from-request.md new file mode 100644 index 0000000000000..9d86318dd4c1e --- /dev/null +++ b/content/en/static_analysis/rules/python-django/os-system-from-request.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-django/os-system-from-request + language: Python + severity: Error +title: Command coming from incoming request +--- +## Metadata +**ID:** `python-django/os-system-from-request` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Execute a process using unsanitized and unvalidated user-inputs. The user data should be sanitized and validated before being used to launch a new process. + +#### Learn More + + - [CWE-20: Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html) + +## Non-Compliant Code Examples +```python +import os + +def execute_command(request): + cmd = request.GET.get("cmd") + print("foobar") + os.system(cmd) + + bli = os.system(cmd) + +``` + +## Compliant Code Examples +```python +import os +import shlex + +def execute_command(request): + cmd = request.GET.get("cmd") + print("foobar") + os.system(shlex.escape(cmd)) + +``` diff --git a/content/en/static_analysis/rules/python-django/subprocess-from-request.md b/content/en/static_analysis/rules/python-django/subprocess-from-request.md new file mode 100644 index 0000000000000..f588019689648 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/subprocess-from-request.md @@ -0,0 +1,59 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-django/subprocess-from-request + language: Python + severity: Error +title: Command coming from incoming request +--- +## Metadata +**ID:** `python-django/subprocess-from-request` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Execute a process using unsanitized and unvalidated user-inputs. The user data should be sanitized and validated before being used to launch a new process. + +#### Learn More + + - [CWE-20: Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html) + +## Non-Compliant Code Examples +```python +import subprocess + +def execute_command(request): + cmd = request.GET.get("cmd") + print("foobar") + subprocess.run(cmd) + subprocess.call(cmd) + subprocess.capture_output(cmd) + subprocess.call(["bash", cmd]) + + bli = subprocess.run(cmd) + bla = subprocess.call(cmd) + ble = subprocess.capture_output(cmd) + blo = subprocess.call(["bash", cmd]) + blip = subprocess.call("bash {0}".format(cmd)) + blop = subprocess.call("bash " + cmd) + + +``` + +## Compliant Code Examples +```python +import subprocess + +def execute_command(request): + cmd = request.GET.get("cmd") + print("foobar") + subprocess.run(shlex.escape(cmd)) + +``` diff --git a/content/en/static_analysis/rules/python-django/use-convenience-imports.md b/content/en/static_analysis/rules/python-django/use-convenience-imports.md new file mode 100644 index 0000000000000..7f5d0c4e926b0 --- /dev/null +++ b/content/en/static_analysis/rules/python-django/use-convenience-imports.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-django/use-convenience-imports + language: Python + severity: Notice +title: use convenience imports whenever possible +--- +## Metadata +**ID:** `python-django/use-convenience-imports` + +**Language:** Python + +**Severity:** Notice + +**Category:** Code Style + +## Description +Use convenient imports from Django whenever possible. + +## Non-Compliant Code Examples +```python +from django.views.generic.base import View # use django.views +``` + +## Compliant Code Examples +```python +from django.views import View +``` diff --git a/content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md b/content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md new file mode 100644 index 0000000000000..8e0938cb9af9f --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md @@ -0,0 +1,67 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/disable-sqlalchemy-text + language: Python + severity: Warning +title: Do not use text() as it leads to SQL injection +--- +## Metadata +**ID:** `python-flask/disable-sqlalchemy-text` + +**Language:** Python + +**Severity:** Warning + +**Category:** Security + +## Description +The `text` function from SQLAlchemy lets you build custom SQL statements. It is recommended to use the ORM functions to build queries and avoid building custom queries, which are vulnerable to SQL injections. + +#### Learn More + + - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) + +## Non-Compliant Code Examples +```python +from sqlalchemy.sql import text + + +con = engine.connect() + +data = ( { "id": 1, "title": "The Hobbit", "primary_author": "Tolkien" }, + { "id": 2, "title": "The Silmarillion", "primary_author": "Tolkien" }, +) + +statement = text("""INSERT INTO book(id, title, primary_author) VALUES(:id, :title, :primary_author)""") + +for line in data: + con.execute(statement, **line) +``` + +## Compliant Code Examples +```python +con = engine.connect() + +data = ( { "id": 1, "title": "The Hobbit", "primary_author": "Tolkien" }, + { "id": 2, "title": "The Silmarillion", "primary_author": "Tolkien" }, +) + +statement = text("""INSERT INTO book(id, title, primary_author) VALUES(:id, :title, :primary_author)""") + +for line in data: + con.execute(statement, **line) +``` + +```python +from sqlalchemy import text + +BOOKS = meta.tables['books'] +query = sqlalchemy.select(BOOKS).where(BOOKS.c.genre == 'fiction') +result = engine.execute(query).fetchall() + + +``` diff --git a/content/en/static_analysis/rules/python-flask/html-format-from-user-input.md b/content/en/static_analysis/rules/python-flask/html-format-from-user-input.md new file mode 100644 index 0000000000000..83bbeea8397dc --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/html-format-from-user-input.md @@ -0,0 +1,91 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/html-format-from-user-input + language: Python + severity: Error +title: Use of unsanitized data to make API calls +--- +## Metadata +**ID:** `python-flask/html-format-from-user-input` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Use of unsanitized from incoming request for SQL queries is unsafe and leads to SQL injections. Data from requests must be sanitized before being used to issues SQL queries, open file or deserialize data. Make sure the data is sanitized before use. + +#### Learn More + + - [CWE-79: Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) + +## Non-Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + + +@app.route("/route/to/resource/") +def resource1(resource_id): + return f"Click me!" + +@app.route("/route/to/resource/") +def resource2(resource_id): + return "Click me!".format(resource_id) + + +@app.route("/route/to/resource/") +def resource3(): + resource_id = flask.request.args.get("resource_id") + return "Click me!" % resource_id + + +@app.route("/route/to/resource/") +def resource4(resource_id): + ret = f"Click me!" + return ret + +@app.route("/route/to/resource/") +def resource2(): + resource_id = flask.request.args.get("resource_id") + ret = "Click me!".format(resource_id) + return ret + + +@app.route("/route/to/resource/") +def resource3(resource_id): + ret = "Click me!" % resource_id + return ret + +``` + +## Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + + +@app.route("/route/to/resource/") +def resource2(resource_id): + return "Click me!".format(sanitize(resource_id)) + + +@app.route("/route/to/resource/") +def resource2(): + resource_id = get.data() + ret = requests.get(foo); + ret = "Click me!".format(resource_id) + return ret + + +``` diff --git a/content/en/static_analysis/rules/python-flask/listen-all-interfaces.md b/content/en/static_analysis/rules/python-flask/listen-all-interfaces.md new file mode 100644 index 0000000000000..e6caf84799504 --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/listen-all-interfaces.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/listen-all-interfaces + language: Python + severity: Notice +title: Your application should not listen on all interfaces +--- +## Metadata +**ID:** `python-flask/listen-all-interfaces` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +Avoid giving access to your resources to all connected interfaces. Instead, bind the resources on a specific interface. Running the server on 0.0.0.0 exposes the server publicly. + +#### Learn More + + - [CWE-668 - Exposure of Resource to Wrong Sphere](https://cwe.mitre.org/data/definitions/668.html) + - [OWASP A01-2021 - Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) + +## Non-Compliant Code Examples +```python +#ruleid:avoid_app_run_with_bad_host +app.run(host="0.0.0.0") + +#ruleid:avoid_app_run_with_bad_host +app.run("0.0.0.0") + +``` + +## Compliant Code Examples +```python +#ruleid:avoid_app_run_with_bad_host +app.run(host="192.168.10.4") + +#ruleid:avoid_app_run_with_bad_host +app.run("192.168.10.4") + +``` diff --git a/content/en/static_analysis/rules/python-flask/no-render-template-string.md b/content/en/static_analysis/rules/python-flask/no-render-template-string.md new file mode 100644 index 0000000000000..0a9ceb4400d44 --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/no-render-template-string.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/no-render-template-string + language: Python + severity: Error +title: Do not use template created with strings +--- +## Metadata +**ID:** `python-flask/no-render-template-string` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Using templates created with string leads to server-side injection. Use template based on files. + +#### Learn More + + - [CWE-96: Improper Neutralization of Directives in Statically Saved](https://cwe.mitre.org/data/definitions/96.html) + +## Non-Compliant Code Examples +```python +import os +from functools import wraps +from flask import request, redirect, url_for, render_template_string + + +API_KEY = os.environ.get('VULN_FLASK_APP_API_KEY') + +# Decorator to check if user is logged in +def require_api_key(f): + @wraps(f) + def wrap(*args, **kwargs): + api_key = request.cookies.get('api_key') + if API_KEY is None or api_key == API_KEY: + return f(*args, **kwargs) + else: + return render_template_string('no api key found'), 401 + return wrap +``` diff --git a/content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md b/content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md new file mode 100644 index 0000000000000..a29eeb18bdfb8 --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md @@ -0,0 +1,73 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/open-file-unsanitized-data + language: Python + severity: Error +title: Use of unsanitized data to open file +--- +## Metadata +**ID:** `python-flask/open-file-unsanitized-data` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Use of unsanitized from incoming request, leading to potential data leak and lack of control of the service. Do not use unsanitized data to control file operations. The code should check any incoming data and make sure it's safe to use it. + +#### Learn More + + - [CWE-22: CWE-22: Improper Limitation of a Pathname to a Restricted Directory](https://cwe.mitre.org/data/definitions/22.html) + +## Non-Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + + +@app.route("/route/to/resource/") +def resource1(resource_id): + with open(resource_id) as f: + pass + with open(f"/path/to/{resource_id}") as f: + pass + with open("/path/to/{0}".format(resource_id)) as f: + pass + with open("/path/to/{0}".other(resource_id)) as f: + pass + +@app.route("/route/to/resource/") +def resource2(resource_id): + file1 = open(resource_id) + file2 = open(f"/path/to/{resource_id}") + file3 = open("/path/to/{0}".format(resource_id)) + + +@app.route("/route/to/resource") +def resource2(): + resource_id = flask.request.args.get("resource_id") + file1 = open(resource_id) + file2 = open(f"/path/to/{resource_id}") + file3 = open("/path/to/{0}".format(resource_id)) +``` + +## Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + +@app.route("/route/to/resource/") +def resource2(resource_id): + sanitized_resource_id = sanitize(resource_id) + file1 = open(sanitized_resource_id) +``` diff --git a/content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md b/content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md new file mode 100644 index 0000000000000..3d66e94e692c5 --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md @@ -0,0 +1,66 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/os-system-unsanitized-data + language: Python + severity: Error +title: Use of unsanitized data to create processes +--- +## Metadata +**ID:** `python-flask/os-system-unsanitized-data` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Use of unsanitized from incoming request to execute a command may lead to command injection. It is highly recommended that data is checked and sanitized before use. + +#### Learn More + + - [CWE-78: roper Neutralization of Special Elements used in an OS](https://cwe.mitre.org/data/definitions/78.html) + +## Non-Compliant Code Examples +```python +import flask +import os + +app = flask.Flask(__name__) + + + +@app.route("/route/to/resource/") +def resource2(resource_id): + file1 = subprocess.call(resource_id) + file2 = subprocess.capture_output(f"/path/to/{resource_id}") + +@app.route("/route/to/resource/") +def resource2(resource_id): + file4 = os.system("/path/to/{0}".format(resource_id)) + os.system(request.remote_addr) + bla = os.system(request.foo) + +@app.route("/route/to/resource") +def resource2(): + resource_id = flask.request.args.get("resource_id") + subprocess.call(resource_id) + subprocess.run(["command", resource_id]) +``` + +## Compliant Code Examples +```python +import flask +import os + +app = flask.Flask(__name__) + +@app.route("/route/to/resource/") +def resource2(resource_id): + file1 = subprocess.call(sanitize(resource_id)) + file2 = subprocess.capture_output(f"/path/to/{sanitize(resource_id)}") +``` diff --git a/content/en/static_analysis/rules/python-flask/secure-cookie.md b/content/en/static_analysis/rules/python-flask/secure-cookie.md new file mode 100644 index 0000000000000..5f0b30df266f0 --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/secure-cookie.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/secure-cookie + language: Python + severity: Notice +title: Make sure cookies are safe and secure +--- +## Metadata +**ID:** `python-flask/secure-cookie` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +Cookies must have the `secure` and `httponly` parameters set to True. + +#### Learn More + + - [CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute](https://cwe.mitre.org/data/definitions/614.html) + +## Non-Compliant Code Examples +```python +response.set_cookie('username', 'flask', secure=False, httponly=False, samesite="Lax") +response.set_cookie('username', 'flask', secure=True, httponly=False, samesite="Lax") +response.set_cookie('username', 'flask', secure=False, httponly=True, samesite=None) +response.set_cookie('username', 'flask', samesite=None, secure=False, httponly=True) +response.set_cookie('username', 'flask', secure=False, samesite=None) +response.set_cookie('username', 'flask', samesite=None, httponly=True) + +``` + +## Compliant Code Examples +```python +response.set_cookie('username', 'flask', secure=True, httponly=True, samesite='Lax') +``` diff --git a/content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md b/content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md new file mode 100644 index 0000000000000..8d8de47616b4d --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md @@ -0,0 +1,64 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/sqlalchemy-injection + language: Python + severity: Error +title: Use of unsanitized data to issue SQL queries +--- +## Metadata +**ID:** `python-flask/sqlalchemy-injection` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Use of unsanitized data from incoming requests in SQL queries may lead to SQL injections. Instead, the data should be filtered and sanitized before use, making sure all potential SQL injections are avoided. + +#### Learn More + + - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) + +## Non-Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + + + +@app.route("/route/to/resource/") +def resource2(resource_id): + file1 = query.order_by(resource_id) + file2 = query.having(f"{resource_id}") + +@app.route("/route/to/resource/") +def resource3(resource_id): + file3 = query.filter("{0}".format(resource_id)) + + +@app.route("/route/to/resource") +def resource2(): + resource_id = flask.request.args.get("resource_id") + file1 = query.group_by(resource_id) +``` + +## Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + +@app.route("/route/to/resource") +def resource2(): + resource_id = flask.request.args.get("resource_id") + file1 = query.group_by(sanitize(resource_id)) +``` diff --git a/content/en/static_analysis/rules/python-flask/ssrf-requests.md b/content/en/static_analysis/rules/python-flask/ssrf-requests.md new file mode 100644 index 0000000000000..69fd3f752d5f5 --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/ssrf-requests.md @@ -0,0 +1,96 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/ssrf-requests + language: Python + severity: Error +title: Use of unsanitized data to make API calls +--- +## Metadata +**ID:** `python-flask/ssrf-requests` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Use of unsanitized data from incoming request for handling SQL request may lead to SQL injection. Incoming request data must always be sanitized before used. + +#### Learn More + + - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) + +## Non-Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + +@app.route("/route/to/resource/") +def resource(resource_id): + foo = requests.get(f"https://api.service.ext/get/by/id/{resource_id}") + return None + + +@app.route("/route/to/resource/") +def resource2(resource_id): + bar = requests.get("https://api.service.ext/get/by/id/" + resource_id}) + return None + +@app.route("/route/to/resource/") +def resource3(resource_id): + baz = requests.get("https://api.service.ext/get/by/id/{0}".format(resource_id})) + return None + + +@app.get("/route/to/another/resource/") +def resource4(resource_id): + foo = requests.get(f"https://api.service.ext/get/by/id/{resource_id}") + return None + +@app.get("/route/to/another/resource/") +def resource5(resource_id): + bar = requests.get("https://api.service.ext/get/by/id/" + resource_id}) + return None + +@app.get("/route/to/another/resource/") +def resource6(resource_id): + baz = requests.get("https://api.service.ext/get/by/id/{0}".format(resource_id})) + return None + +@app.route("/route/to/resource/the/return/", methods=["GET"]) +def get_param(): + rid = flask.request.args.get("resource_id") + # unsanitized data + requests.post(f"https://api.service.ext/get/by/id/{rid}", timeout=10) + requests.patch(rid, timeout=10) + requests.get("https://api.service.ext/get/by/id/{0}".format(rid)) + requests.get("https://api.service.ext/get/by/id/" + rid) + requests.patch(rid, timeout=10) + return None + +@app.route("/this/is/fine/") +def fine(sure): + print("foobar") + return requests.get("https://api.service.ext/nothing") +``` + +## Compliant Code Examples +```python +import flask +import requests + +app = flask.Flask(__name__) + +@app.route("/route/to/resource/") +def resource(resource_id): + sanitized_resource_id = sanitize(resource_id) + foo = requests.get(f"https://api.service.ext/get/by/id/{sanitized_resource_id}") + return foo +``` diff --git a/content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md b/content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md new file mode 100644 index 0000000000000..3d48206294fdc --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md @@ -0,0 +1,62 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-flask/urlopen-unsanitized-data + language: Python + severity: Error +title: Use of unsanitized data to open API +--- +## Metadata +**ID:** `python-flask/urlopen-unsanitized-data` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Use of unsanitized from incoming request, leading to potential data leak and lack of control of the service. The code should check any incoming data and make sure it's safe to use it. + +#### Learn More + + - [CWE-918: Server-Side Request Forgery (SSRF)](https://cwe.mitre.org/data/definitions/918.html) + +## Non-Compliant Code Examples +```python +import flask +from urllib.request import urlopen + +app = flask.Flask(__name__) + + + +@app.route("/route/to/resource/") +def resource2(resource_id): + file1 = urlopen(resource_id) + file2 = urlopen(f"/path/to/{resource_id}") + + +@app.route("/route/to/resource") +def resource2(): + resource_id = flask.request.args.get("resource_id") + file1 = urlopen(resource_id) + file2 = urlopen(f"/path/to/{resource_id}") + file3 = urlopen("/path/to/{0}".format(resource_id)) +``` + +## Compliant Code Examples +```python +import flask +from urllib.request import urlopen + +app = flask.Flask(__name__) + +@app.route("/route/to/resource/") +def resource2(resource_id): + sanitized_resource_id = sanitize(resource_id) + file1 = urlopen(sanitized_resource_id) +``` diff --git a/content/en/static_analysis/rules/python-flask/use-jsonify.md b/content/en/static_analysis/rules/python-flask/use-jsonify.md new file mode 100644 index 0000000000000..b75795d8fa853 --- /dev/null +++ b/content/en/static_analysis/rules/python-flask/use-jsonify.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-flask/use-jsonify + language: Python + severity: Notice +title: use jsonify instead of json.dumps for JSON output +--- +## Metadata +**ID:** `python-flask/use-jsonify` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +With the flask framework, `jsonify` helps you write API endpoints that return JSON data. + +#### Learn More + + - [Python Flask: `jsonify()`](https://flask.palletsprojects.com/en/2.3.x/api/#flask.json.jsonify) + + + +## Non-Compliant Code Examples +```python +@app.route("/article") +def get_article(): + article = get_article_by_id(request.args.get("id")) + return json.dumps(article) # use flask.jsonify instead of json.dumps +``` + +## Compliant Code Examples +```python +from flask import jsonify + +@app.route("/article") +def get_article(): + article = get_article_by_id(request.args.get("id")) + return jsonify(article) +``` diff --git a/content/en/static_analysis/rules/python-inclusive/comments.md b/content/en/static_analysis/rules/python-inclusive/comments.md new file mode 100644 index 0000000000000..de460dac2a0c1 --- /dev/null +++ b/content/en/static_analysis/rules/python-inclusive/comments.md @@ -0,0 +1,57 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-inclusive/comments + language: Python + severity: Notice +title: check comments for wording issues +--- +## Metadata +**ID:** `python-inclusive/comments` + +**Language:** Python + +**Severity:** Notice + +**Category:** Code Style + +## Description +Check the variable names and suggest better names. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```python +# whitelist names to prevent unauthorized usage +def filter_names(names): + pass + +# she SHE should check her code +def new_function_from_helen(): + pass + + +class Foo: + # he should check his + def new_function_from_joe(): + pass +``` + +## Compliant Code Examples +```python +# allowlist names to prevent unauthorized usage +def filter_names(names): + pass + +# the comments do not have an history of issues +def foo(bar): + baz() +``` diff --git a/content/en/static_analysis/rules/python-inclusive/function-definition.md b/content/en/static_analysis/rules/python-inclusive/function-definition.md new file mode 100644 index 0000000000000..234b33c04f011 --- /dev/null +++ b/content/en/static_analysis/rules/python-inclusive/function-definition.md @@ -0,0 +1,62 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-inclusive/function-definition + language: Python + severity: Notice +title: check function names for wording issues +--- +## Metadata +**ID:** `python-inclusive/function-definition` + +**Language:** Python + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that some words are not used in the codebase and suggest replacement when appropriate. + +Examples of replacement suggestions: + - `blacklist` with `denylist` + - `whitelist` with `allowlist` + - `master` with `primary` + - `slave` with `secondary` + +## Non-Compliant Code Examples +```python +# blacklist located at the end of the string +def foo_blacklist(): + pass +``` + +```python +# Do not use the name blacklist, even if casing is mixed +def BlaCKliSt_NaMeS(): + pass + +def wHiTeLisT_NaMeS(): + pass +``` + +```python +# blacklist at the beginning of the function name +def blacklist_names(): + pass +``` + +```python +# wrong identifier in the function name and parameters +def blacklist_names(master, slave): + pass +``` + +## Compliant Code Examples +```python +def foo_denylist(): + pass +``` diff --git a/content/en/static_analysis/rules/python-inclusive/variable-name.md b/content/en/static_analysis/rules/python-inclusive/variable-name.md new file mode 100644 index 0000000000000..5613f82619bb1 --- /dev/null +++ b/content/en/static_analysis/rules/python-inclusive/variable-name.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: python-inclusive/variable-name + language: Python + severity: Notice +title: check variable names for wording issues +--- +## Metadata +**ID:** `python-inclusive/variable-name` + +**Language:** Python + +**Severity:** Notice + +**Category:** Code Style + +## Description +Check the variable names and suggest better names. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```python +# banned name, will suggest allowlist +whitelist = "foo" +names_whitelist = "bla"; + +names_blacklist = "bla"; + +addr_master_ip = "5.4.3.8"; +addr_slave_ip = "1.2.3.4"; +``` + +## Compliant Code Examples +```python +# not a problem with the name +snow_white = "happy" +``` diff --git a/content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md b/content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md new file mode 100644 index 0000000000000..78e409c914ac7 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md @@ -0,0 +1,60 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/arith-operator-not-functions + language: Python + severity: Notice +title: Use arithmetic operator instead of a function +--- +## Metadata +**ID:** `python-pandas/arith-operator-not-functions` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +User should use arithmetic operators (`+`, `-`, etc) instead of function (`.add`) to make the code more clear. + +## Non-Compliant Code Examples +```python +def myfunction(): + foo = pd.DataFrame({'angles': [0, 3, 4], + 'degrees': [360, 180, 360]}, + index=['circle', 'triangle', 'rectangle']) + if something: + baz = foo.add(1) + elif other_thing: + baz = foo.add(42) + else: + baz = foo.add(51) + + bar = whatever() + baz = bar.add(4) +``` + +```python +def myfunction(): + foo = pd.DataFrame({'angles': [0, 3, 4], + 'degrees': [360, 180, 360]}, + index=['circle', 'triangle', 'rectangle']) + baz = foo.add(1) + + bar = whatever() + baz = bar.add(4) +``` + +## Compliant Code Examples +```python +foo = pd.DataFrame({'angles': [0, 3, 4], + 'degrees': [360, 180, 360]}, + index=['circle', 'triangle', 'rectangle']) +baz = foo + 1 + + +``` diff --git a/content/en/static_analysis/rules/python-pandas/avoid-inplace.md b/content/en/static_analysis/rules/python-pandas/avoid-inplace.md new file mode 100644 index 0000000000000..4bbb2767900d3 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/avoid-inplace.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/avoid-inplace + language: Python + severity: Warning +title: Avoid using inplace=True +--- +## Metadata +**ID:** `python-pandas/avoid-inplace` + +**Language:** Python + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Avoid using `inplace=True` as it does not have clear performance impact and is potentially dangerous and does not behave as it should. + +#### Learn More + + - [Why You Should Probably Never Use pandas inplace=True](https://towardsdatascience.com/why-you-should-probably-never-use-pandas-inplace-true-9f9f211849e4?gi=ae387a166946) + +## Non-Compliant Code Examples +```python +df.drop(['a'], axis=1, inplace=True) +``` + +## Compliant Code Examples +```python +df.drop(['a'], axis=1, inplace=False) +``` diff --git a/content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md b/content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md new file mode 100644 index 0000000000000..4f43fbce8055e --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/comp-operator-not-function + language: Python + severity: None +title: Use operators to compare values, not functions +--- +## Metadata +**ID:** `python-pandas/comp-operator-not-function` + +**Language:** Python + +**Severity:** None + +**Category:** Best Practices + +## Description +User should use comparison operators (`<`, `>`, etc) instead of function (`.ld`) to make the code more clear. + +## Non-Compliant Code Examples +```python +foo.le(bar) +``` + +## Compliant Code Examples +```python +foo < bar +``` diff --git a/content/en/static_analysis/rules/python-pandas/import-as-pd.md b/content/en/static_analysis/rules/python-pandas/import-as-pd.md new file mode 100644 index 0000000000000..329ad28394951 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/import-as-pd.md @@ -0,0 +1,53 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/import-as-pd + language: Python + severity: Notice +title: Import pandas according to coding guidelines +--- +## Metadata +**ID:** `python-pandas/import-as-pd` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +The `pandas` library is generally imported using the following code snippet. + +```python +import pandas as pd +``` + +It is good practice to ensure that all pandas import are done this way. This rule ensures that all code uses this pattern. + +## Non-Compliant Code Examples +```python +import pandas # should use import pandas as pd + + +import pandas as foo + + +import foo as bar +``` + +```python +from pandas import something # should use import pandas as pd + +``` + +```python +import pandas as something # should use import pandas as pd +``` + +## Compliant Code Examples +```python +import pandas as pd # should use import pandas as pd +``` diff --git a/content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md b/content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md new file mode 100644 index 0000000000000..5cbb1416b3a67 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/isna-instead-of-isnull + language: Python + severity: Notice +title: Use isna instead of isnull +--- +## Metadata +**ID:** `python-pandas/isna-instead-of-isnull` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +The functions `isna` and `isnull` are similar. However, this is a best practice to use `isna` since other methods use the same naming patterns. + +#### Learn More + + - [Pandas isna() and isnull(), what is the difference?](https://stackoverflow.com/questions/52086574/pandas-isna-and-isnull-what-is-the-difference) + +## Non-Compliant Code Examples +```python +nulls = pd.isnull(val) # prefer using isna +``` + +## Compliant Code Examples +```python +nas = pd.isna(val) +``` diff --git a/content/en/static_analysis/rules/python-pandas/loc-not-ix.md b/content/en/static_analysis/rules/python-pandas/loc-not-ix.md new file mode 100644 index 0000000000000..a8e0a6489fa19 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/loc-not-ix.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/loc-not-ix + language: Python + severity: None +title: prefer iloc or loc rather than ix +--- +## Metadata +**ID:** `python-pandas/loc-not-ix` + +**Language:** Python + +**Severity:** None + +**Category:** Best Practices + +## Description +The functions `notna` and `notnull` are similar. However, this is a best practice to use `notna` since other methods use the same naming patterns. + +## Non-Compliant Code Examples +```python +index = df.iat[:, 1:3] +``` + +```python +index = df.at[:, ['B', 'A']] +``` + +```python +s = df.ix[[0, 2], 'A'] +``` + +## Compliant Code Examples +```python +new_df = df.iloc[] +``` diff --git a/content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md b/content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md new file mode 100644 index 0000000000000..6f5960e7fe3e1 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/notna-instead-of-notnull + language: Python + severity: None +title: prefer notna to notnull +--- +## Metadata +**ID:** `python-pandas/notna-instead-of-notnull` + +**Language:** Python + +**Severity:** None + +**Category:** Best Practices + +## Description +The functions `notna` and `notnull` are similar. However, this is a best practice to use `notna` since other methods use the same naming patterns. + +## Non-Compliant Code Examples +```python +notnulls = pd.notnull(val) +``` + +## Compliant Code Examples +```python +notnas = pd.notna(val) +``` diff --git a/content/en/static_analysis/rules/python-pandas/pivot-table.md b/content/en/static_analysis/rules/python-pandas/pivot-table.md new file mode 100644 index 0000000000000..e65a95261ce10 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/pivot-table.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/pivot-table + language: Python + severity: Notice +title: Use pivot_table instead of pivot or unstack +--- +## Metadata +**ID:** `python-pandas/pivot-table` + +**Language:** Python + +**Severity:** Notice + +**Category:** Best Practices + +## Description +The functions `isna` and `isnull` are similar. However, this is a best practice to use `isna` since other methods use the same naming patterns. + +#### Learn More + + - [Pandas isna() and isnull(), what is the difference?](https://stackoverflow.com/questions/52086574/pandas-isna-and-isnull-what-is-the-difference) + +## Non-Compliant Code Examples +```python +table = df.unstack(level=0) +``` + +```python +table = pd.pivot( + df, + index='foo', + columns='bar', + values='baz' + ) +``` + +## Compliant Code Examples +```python +table = df.pivot_table( + df, + values='D', + index=['A', 'B'], + columns=['C'], + aggfunc=np.sum, + fill_value=0 +``` diff --git a/content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md b/content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md new file mode 100644 index 0000000000000..dd1cc1fc41339 --- /dev/null +++ b/content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-pandas/use-read-csv-not-read-table + language: Python + severity: None +title: prefer read_csv to read_table +--- +## Metadata +**ID:** `python-pandas/use-read-csv-not-read-table` + +**Language:** Python + +**Severity:** None + +**Category:** Best Practices + +## Description +The functions `notna` and `notnull` are similar. However, this is a best practice to use `notna` since other methods use the same naming patterns. + +## Non-Compliant Code Examples +```python +employees = pd.read_table(input_file) +``` + +## Compliant Code Examples +```python +employees = pd.read_csv(input_file) +``` diff --git a/content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md b/content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md new file mode 100644 index 0000000000000..0e65974da4e9e --- /dev/null +++ b/content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/asyncio-subprocess-create-shell + language: Python + severity: Error +title: Unsafe execution of shell commands +--- +## Metadata +**ID:** `python-security/asyncio-subprocess-create-shell` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Detect unsafe shell execution in the asyncio framework. When we invoke the shell, we should make sure that the data is safe and secure. Use `shlex` to sanitize user inputs. + +#### Learn More + + - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) + - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) + +## Non-Compliant Code Examples +```python +import asyncio + +def handler(event, context): + # Should sanitize arguments + async_loop.run_until_complete(async_loop.create_subprocess_shell("mycommand")) + +``` + +## Compliant Code Examples +```python +import asyncio +import shlex + +def handler(event, context): + # Should sanitize arguments + async_loop.run_until_complete(async_loop.create_subprocess_shell(shlex.escape("mycommand"))) +``` diff --git a/content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md b/content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md new file mode 100644 index 0000000000000..82825c0402220 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/asyncio-subprocess-exec + language: Python + severity: Error +title: Unsafe execution of shell commands +--- +## Metadata +**ID:** `python-security/asyncio-subprocess-exec` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Detect unsafe shell execution in the asyncio framework. When we invoke the shell, we should make sure that the data is safe and secure. Use `shlex` to sanitize user inputs. + +#### Learn More + + - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) + - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) + +## Non-Compliant Code Examples +```python +import asyncio + +def handler(event, context): + # Should sanitize arguments + async_loop.run_until_complete(async_loop.subprocess_exec(waiting_protocol, ["/bin/sh", "mycommand"])) +``` + +## Compliant Code Examples +```python +import asyncio +import shlex + +def handler(event, context): + # Should sanitize arguments + async_loop.run_until_complete(async_loop.subprocess_exec(waiting_protocol, shlex.split(shlex.quote("/bin/sh mycommand")))) +``` diff --git a/content/en/static_analysis/rules/python-security/avoid-random.md b/content/en/static_analysis/rules/python-security/avoid-random.md new file mode 100644 index 0000000000000..52b67fbc5100f --- /dev/null +++ b/content/en/static_analysis/rules/python-security/avoid-random.md @@ -0,0 +1,64 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/avoid-random + language: Python + severity: Error +title: use secrets package over random package +--- +## Metadata +**ID:** `python-security/avoid-random` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Make sure to use values that are *actually* random. The `random` module in Python should generally not be used and replaced with the `secrets` module, as noted in the [official Python documentation](https://docs.python.org/3/library/random.html). + +#### Learn More + + - [CWE-330](https://cwe.mitre.org/data/definitions/330.html) + - [Python random module documentation](https://docs.python.org/3/library/random.html) + - [Python secrets module documentation](https://docs.python.org/3/library/secrets.html#module-secrets) + +## Non-Compliant Code Examples +```python +from random import randrange + +randrange(10) # # randrange is not actually random +``` + +```python +from random import random + +v = random() # random is not actually random +``` + +```python +import random + +n = random.randrange(10) # randrange is not actually random +``` + +```python +import random + +n = random.random(1) # randrange is not actually random +``` + +```python +import random + +n = random.random() # randrange is not actually random +``` + +## Compliant Code Examples +```python +n = random.random() +``` diff --git a/content/en/static_analysis/rules/python-security/aws-boto-credentials.md b/content/en/static_analysis/rules/python-security/aws-boto-credentials.md new file mode 100644 index 0000000000000..5fb60e28cbd9c --- /dev/null +++ b/content/en/static_analysis/rules/python-security/aws-boto-credentials.md @@ -0,0 +1,89 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/aws-boto-credentials + language: Python + severity: Notice +title: use env vars over hardcoded values +--- +## Metadata +**ID:** `python-security/aws-boto-credentials` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +This rule makes sure that the `boto3` library use the environments variables to authenticate instead of using hardcoded credentials. This rule checks for the `boto3.client` and `boto3.Session` calls. It addresses the [CWE-798 rule](https://cwe.mitre.org/data/definitions/798.html) - uses of hardcoded credentials in code. + +#### Learn More + + - [AWS credentials](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials) + - [CWE-798: Use of Hard-coded Credentials](https://cwe.mitre.org/data/definitions/798.html) + +## Non-Compliant Code Examples +```python +from boto3 import client + +cli = client( + 's3', + aws_access_key_id="AGPAFOOBAR", + aws_secret_access_key="bar", + aws_session_token=SESSION_TOKEN +) +``` + +```python +import boto3 + +client = boto3.client( + 's3', + aws_access_key_id="AGPAFOOBAR", + aws_secret_access_key="bar", + aws_session_token=SESSION_TOKEN +) +``` + +```python +import boto3 + +client = boto3.Session( + 's3', + aws_access_key_id=ACCESS_KEY, + aws_secret_access_key=SECRET_KEY, + aws_session_token="foobar" # hard coded credential +) +``` + +## Compliant Code Examples +```python +import boto3 + +client = boto3.Session( + 's3', + aws_session_token=SESSION_TOKEN +) +``` + +```python +import boto3 + +client = boto3.client( + 's3', + aws_session_token=SESSION_TOKEN +) +``` + +```python +client = boto3.client( + 's3', + aws_access_key_id=ACCESS_KEY, + aws_secret_access_key=SECRET_KEY, + aws_session_token=SESSION_TOKEN +) +``` diff --git a/content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md b/content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md new file mode 100644 index 0000000000000..c449210c2505e --- /dev/null +++ b/content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md @@ -0,0 +1,54 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/deserialize-untrusted-data + language: Python + severity: Notice +title: avoid unsafe function to (de)serialize data +--- +## Metadata +**ID:** `python-security/deserialize-untrusted-data` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +Do not deserialize untrusted data. Make sure you use alternatives to check that the data can be deserialized safely. There is no workaround around this: unless you **really** trust the data source, it's better to use another way to exchange data, such as an API or other protocols such as [protobuf](https://developers.google.com/protocol-buffers) or [thrift](https://thrift.apache.org/). + +**Read More** + + - [Unsafe Deserialization in Python (CWE-502)](https://www.codiga.io/blog/python-unsafe-deserialization/) + + - [CWE-502: Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html) + +## Non-Compliant Code Examples +```python +import marshal +person = {"name":"xyz", "age":22, "marks":[45,56,78]} +data = marshal.dumps(person) +obj = marshal.loads(data) +``` + +```python +import pickle + +data = pickle.loads(data) +``` + +## Compliant Code Examples +```python +import pickle + +data = pickle.loads(data) + +``` + +```python +data = pickle.loads(data) +``` diff --git a/content/en/static_analysis/rules/python-security/file-write-others.md b/content/en/static_analysis/rules/python-security/file-write-others.md new file mode 100644 index 0000000000000..3feb11440a57e --- /dev/null +++ b/content/en/static_analysis/rules/python-security/file-write-others.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/file-write-others + language: Python + severity: Warning +title: do not let all users write permissions +--- +## Metadata +**ID:** `python-security/file-write-others` + +**Language:** Python + +**Severity:** Warning + +**Category:** Security + +## Description +Make sure that programs do not let write permissions for all users. When using `os.chmod`, the user should never use `S_IWOTH` that gives the permission to all users to write the file on the filesystem. + +Instead, this permission should be removed, and proper control access should be configured. + +See the following related CWE: + - [CWE-275](https://cwe.mitre.org/data/definitions/275.html) category - Permission Issues + - [CWE-280](https://cwe.mitre.org/data/definitions/280.html) - Improper Handling of Insufficient Permissions or Privileges + +## Non-Compliant Code Examples +```python +import stat + +path = "/path/to/file" +os.chmod(path, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH) +``` + +## Compliant Code Examples +```python +import stat + +path = "/path/to/file" +os.chmod(path, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH) # skipping because it's in a test file +``` + +```python +import stat + +path = "/path/to/file" +os.chmod(path, stat.S_IROTH | stat.S_IXOTH) # no write by others +``` diff --git a/content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md b/content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md new file mode 100644 index 0000000000000..b0b2347eec75a --- /dev/null +++ b/content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md @@ -0,0 +1,64 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: python-security/hardcoded-tmp-file + language: Python + severity: None +title: Do not hardcode temp file or directory +--- +## Metadata +**ID:** `python-security/hardcoded-tmp-file` + +**Language:** Python + +**Severity:** None + +**Category:** Best Practices + +## Description +Do not hardcode the name or directory of temporary files. Use the `tempfile` Python instead of hardcoding values. + + +#### Learn More + + - [CWE-377 - Insecure Temporary File](https://cwe.mitre.org/data/definitions/377.html) + - [Create, use and remove. temporary files securely](https://security.openstack.org/guidelines/dg_using-temporary-files-securely.html) + - [`tempfile` module](https://docs.python.org/3/library/tempfile.html) + +## Non-Compliant Code Examples +```python +with open("/tmp/acme.pub", "rb") as key_file: + public_key = serialization.load_pem_public_key( + key_file.read(), + backend=default_backend() + ) + +def foobar(): + api_key_file = Path('/tmp/supersecret.txt') + +keyfile = '/tmp/vulpy.apikey.{}.{}'.format(username, key) +keyfile = f"/tmp/vulpy.apikey.{username}.{key}" +def authenticate(request): + if 'X-APIKEY' not in request.headers: + return None + + key = request.headers['X-APIKEY'] + + for f in Path('/tmp/').glob('vulpy.apikey.*.' + key): + return f.name.split('.')[2] + + return None +``` + +## Compliant Code Examples +```python +secure_temp = tempfile.mkstemp(prefix="pre_",suffix="_suf") +print(secure_temp) + +temp = tempfile.NamedTemporaryFile() +print(temp) +print(temp.name) +``` diff --git a/content/en/static_analysis/rules/python-security/html-string-from-parameters.md b/content/en/static_analysis/rules/python-security/html-string-from-parameters.md new file mode 100644 index 0000000000000..26b74ebb4801b --- /dev/null +++ b/content/en/static_analysis/rules/python-security/html-string-from-parameters.md @@ -0,0 +1,76 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/html-string-from-parameters + language: Python + severity: Error +title: Avoid HTML built in strings +--- +## Metadata +**ID:** `python-security/html-string-from-parameters` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Detect unsafe HTML content. User-input may be injected into HTML content without being sanitized. + +User input should always be checked before being used in HTML data. + +#### Learn More + +- [CWE-79: Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) + +## Non-Compliant Code Examples +```python +def my_function(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): + html1 = f"
{arg1}
" + html1 = "
{0}
".format(arg1) + html2 = f"
{arg2['bli']}
" + html2 = "
{0}
".format(arg2['bli']) + html3 = "
" + arg1 + "
" + render(f"
{arg1}
") + return html + + +def my_function2(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): + html1 = f"
{arg51}
" + html1 = "
{0}
".format(arg42) + html2 = f"
{arg26['bli']}
" + html2 = "
{0}
".format(arg51['bli']) + html3 = "
" + arg41 + "
" + render(f"
{arg51}
") + return html + + +def my_function3(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): + html1 = f"
{arg1}
" + html1 = "
{0}
".format(arg1) + html2 = f"
{arg2['bli']}
" + html2 = "
{0}
".format(arg2['bli']) + html3 = "
" + arg1 + "
" + render(f"
{arg1}
") + return html +``` + +## Compliant Code Examples +```python +def my_function(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): + html1 = f"
{sanitize_value(arg1)}
" + html1 = "
{0}
".format(sanitize_value(arg1)) + html2 = f"
{sanitize_value(arg2['bli'])}
" + html2 = "
{0}
".format(sanitize_value(arg2['bli'])) + html3 = "
" + sanitize_value(arg1) + "
" + render(f"
{sanitize_value(arg1)}
") + return html + + + + +``` diff --git a/content/en/static_analysis/rules/python-security/insecure-hash-functions.md b/content/en/static_analysis/rules/python-security/insecure-hash-functions.md new file mode 100644 index 0000000000000..2c5dce020d899 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/insecure-hash-functions.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/insecure-hash-functions + language: Python + severity: Warning +title: Do not use insecure functions +--- +## Metadata +**ID:** `python-security/insecure-hash-functions` + +**Language:** Python + +**Severity:** Warning + +**Category:** Security + +## Description +Do not use a broken or risky cryptographic algorithm. This exposes you to unwanted attacks. + +It checks the following modules + - [hashlib](https://docs.python.org/3/library/hashlib.html) + - [cryptography](https://cryptography.io/) + +#### Learn More + + - [CWE-327](https://cwe.mitre.org/data/definitions/327.html) - Use of a Broken or Risky Cryptographic Algorithm + - [CWE-328](https://cwe.mitre.org/data/definitions/328.html) - Use of Weak Hash + +## Non-Compliant Code Examples +```python +from cryptography.hazmat.primitives import hashes +digest = hashes.Hash(hashes.MD5()) +``` + +```python +from cryptography.hazmat.primitives import hashes +digest = hashes.Hash(hashes.MD5()) +``` + +```python +import hashlib + +hashlib.new('md5') +hashlib.new('md4') + + +hashlib.md5("bla"); +``` diff --git a/content/en/static_analysis/rules/python-security/insecure-jwt.md b/content/en/static_analysis/rules/python-security/insecure-jwt.md new file mode 100644 index 0000000000000..0acb67adc9fd5 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/insecure-jwt.md @@ -0,0 +1,53 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/insecure-jwt + language: Python + severity: Notice +title: Ensure JWT signatures are verified +--- +## Metadata +**ID:** `python-security/insecure-jwt` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +Use `"verify_signature": False` when decoding a JWT bypasses security and may authenticate users that should not be authenticated. + +**See Also** + + - [CWE-287 - Improper Authentication](https://cwe.mitre.org/data/definitions/287.html) + +## Non-Compliant Code Examples +```python +import jwt + +jwt.decode(encoded, options={"verify_signature": False}) +``` + +## Compliant Code Examples +```python +import jwt + +jwt.decode(encoded, bla={"verify_signature": False}) + +jwt.decode(encoded, options={"foobar": False}) + +``` + +```python +import jwt + +jwt.decode(encoded, options={"verify_signature": True}) +``` + +```python +jwt.decode(encoded, options={"verify_signature": True}) +``` diff --git a/content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md b/content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md new file mode 100644 index 0000000000000..5b656bf26967a --- /dev/null +++ b/content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md @@ -0,0 +1,74 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/insecure-ssl-protocols + language: Python + severity: Notice +title: Do not use insecure encryption protocols +--- +## Metadata +**ID:** `python-security/insecure-ssl-protocols` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +The following security protocols should never be used in Python: `SSLv3`, `SSLv2`, `TLSv1`. For more details, read the [SSL module page](https://docs.python.org/3/library/ssl.html) of the official documentation. + +The issue addresses the [CWE-757](https://cwe.mitre.org/data/definitions/757.html) - selection of less-secure algorithm during negotiation. + + + +## Non-Compliant Code Examples +```python +import ssl + +def newconnect(self): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + remote = ssl.wrap_socket(s, + ca_certs= CA, + cert_reqs=ssl.CERT_REQUIRED, + ssl_version = ssl.PROTOCOL_SSLv3) + remote.connect(self.server.seradd) + if not self.server.seradd[0] == remote.getpeercert()['subjectAltName'][0][1]: + logging.error('Server crt error !! Server Name don\'t mach !!') + logging.error(remote.getpeercert()['subjectAltName'][0][1]) + return + if not self.send_PW(remote): + logging.warn('PW error !') + return + except socket.error, e: + logging.warn(e) + return +``` + +## Compliant Code Examples +```python +import ssl + +def newconnect(self): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + remote = ssl.wrap_socket(s, + ca_certs= CA, + cert_reqs=ssl.CERT_REQUIRED, + ssl_version = ssl.PROTOCOL_TLS) + remote.connect(self.server.seradd) + if not self.server.seradd[0] == remote.getpeercert()['subjectAltName'][0][1]: + logging.error('Server crt error !! Server Name don\'t mach !!') + logging.error(remote.getpeercert()['subjectAltName'][0][1]) + return + if not self.send_PW(remote): + logging.warn('PW error !') + return + except socket.error, e: + logging.warn(e) + return +``` diff --git a/content/en/static_analysis/rules/python-security/jinja-autoescape.md b/content/en/static_analysis/rules/python-security/jinja-autoescape.md new file mode 100644 index 0000000000000..eeba30b9e66ad --- /dev/null +++ b/content/en/static_analysis/rules/python-security/jinja-autoescape.md @@ -0,0 +1,70 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/jinja-autoescape + language: Python + severity: Notice +title: Auto escape should be set to true +--- +## Metadata +**ID:** `python-security/jinja-autoescape` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +By default, jinja2 is not autoescaping. This can lead to XSS attacks. The `autoescape` parameter should always be `True`. + + +#### Learn More + + - [OWASP XSS](https://owasp.org/www-community/attacks/xss/) + - [CWE-94 - Improper Control of Generation of Code](https://cwe.mitre.org/data/definitions/94.html) + +## Non-Compliant Code Examples +```python +import jinja2 +env = jinja2.Environment( + loader=PackageLoader("yourapp"), + autoescape=False # should be True +) +``` + +```python +from jinja2 import Environment, PackageLoader, select_autoescape +env = Environment( + loader=PackageLoader("yourapp"), + autoescape=False # should be True +) +``` + +## Compliant Code Examples +```python +import jinja2 +env = Environment( + loader=PackageLoader("yourapp"), + autoescape=True +) +``` + +```python +from jinja2 import Environment, PackageLoader, select_autoescape +env = Environment( + loader=PackageLoader("yourapp"), + autoescape=select_autoescape() +) +``` + +```python +from jinja2 import Environment, PackageLoader, select_autoescape +env = Environment( + loader=PackageLoader("yourapp"), + autoescape=True +) +``` diff --git a/content/en/static_analysis/rules/python-security/mktemp.md b/content/en/static_analysis/rules/python-security/mktemp.md new file mode 100644 index 0000000000000..e4190cdfa3a40 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/mktemp.md @@ -0,0 +1,49 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/mktemp + language: Python + severity: Notice +title: Make sure temporary files are secure +--- +## Metadata +**ID:** `python-security/mktemp` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +Using insecure temporary files makes your program vulnerable to attacks. The official [Python documentation](https://docs.python.org/3/library/tempfile.html) reports this module being vulnerable to attacks. Instead of `mktemp`, use the secure version `mkstemp()`. + + +#### Learn More + + - [CWE-377 - Insecure Temporary File](https://cwe.mitre.org/data/definitions/377.html) + - [Python documentation for mktemp()](https://docs.python.org/3/library/tempfile.html) + +## Non-Compliant Code Examples +```python +from tempfile import mktemp +mktemp(dir=self._tmp_dir) +``` + +```python +import tempfile +tempfile.mktemp(dir=self._tmp_dir) +``` + +## Compliant Code Examples +```python +tempfile.mktemp(dir=self._tmp_dir) +``` + +```python +import tempfile +tempfile.mkstemp(dir=self._tmp_dir) +``` diff --git a/content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md b/content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md new file mode 100644 index 0000000000000..99802e754e476 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/no-empty-array-as-parameter + language: Python + severity: Warning +title: Do not use empty array as default parameter +--- +## Metadata +**ID:** `python-security/no-empty-array-as-parameter` + +**Language:** Python + +**Severity:** Warning + +**Category:** Security + +## Description +We should never pass an empty array parameter to a function. Instead, use `None` and check the value if defined. This can cause unwanted behavior as the value of the argument is only evaluated once. + +**Read more** + + - [Avoid using empty list as default argument](https://nikos7am.com/posts/mutable-default-arguments/) + +## Non-Compliant Code Examples +```python +def newFunction(arg1, arg2: int, arg3 = [], arg4: MyType = []): # do not use empty array/list as default parameter + print("bla") +``` + +## Compliant Code Examples +```python +def newFunction(arg1, arg2: int, arg3 = None): # do not use empty array/list as default parameter + print("bla") +``` diff --git a/content/en/static_analysis/rules/python-security/no-eval.md b/content/en/static_analysis/rules/python-security/no-eval.md new file mode 100644 index 0000000000000..b8426e74b128c --- /dev/null +++ b/content/en/static_analysis/rules/python-security/no-eval.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/no-eval + language: Python + severity: Notice +title: use of eval can be insecure +--- +## Metadata +**ID:** `python-security/no-eval` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +`eval()` is insecure, and uncontrolled data could then create a vulnerability, as reported by the [official Python documentation](https://docs.python.org/3/library/functions.html#eval). Generated code should be controlled as mentioned by [CWE-94](https://cwe.mitre.org/data/definitions/94.html). + +#### Learn More + + - [CWE-94](https://cwe.mitre.org/data/definitions/94.html) - Improper Control of Generation of Code + - [Safe and Secure Python: do not use eval()](https://www.codiga.io/blog/python-eval/) + +## Non-Compliant Code Examples +```python +print("bla") +eval('[1, 2, 3]') # eval() can be unsafe +``` + +## Compliant Code Examples +```python +import foo +foo.eval('[1, 2, 3]') +``` + +```python +from ast import literal_eval +print("bla") +literal_eval('[1, 2, 3]') +``` diff --git a/content/en/static_analysis/rules/python-security/os-spawn.md b/content/en/static_analysis/rules/python-security/os-spawn.md new file mode 100644 index 0000000000000..03a7c7777d515 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/os-spawn.md @@ -0,0 +1,57 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/os-spawn + language: Python + severity: Error +title: Call of a spawn process without sanitization +--- +## Metadata +**ID:** `python-security/os-spawn` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Detect unsafe shell execution with the `os` module. We should ensure the command is safe before execution. Use `shlex` to sanitize user inputs. + +#### Learn More + + - [Python `os.spawn*()` documentation](https://docs.python.org/3/library/os.html#os.spawnl) + - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) + - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) + +## Non-Compliant Code Examples +```python +import os + +directory = "/tmp" + +# Use of unsanitized data to create a process +os.spawnl(os.P_WAIT, "/bin/ls") +os.spawnle(os.P_WAIT, "/bin/ls") +os.spawnlp(os.P_WAIT, "/bin/ls") +os.spawnlpe(os.P_WAIT, "/bin/ls") +os.spawnv(os.P_WAIT, "/bin/ls") +os.spawnve(os.P_WAIT, "/bin/ls") +os.spawnvp(os.P_WAIT, "/bin/ls") +os.spawnvpe(os.P_WAIT, "/bin/ls") + + +os.spawnvpe(os.P_WAIT, "/bin/ls " + directory) +``` + +## Compliant Code Examples +```python +import os +import shlex + +# Use of shlex() to sanitize data +os.spawnl(os.P_WAIT, shlex.escape("/bin/ls")) +``` diff --git a/content/en/static_analysis/rules/python-security/os-system.md b/content/en/static_analysis/rules/python-security/os-system.md new file mode 100644 index 0000000000000..c64831bd4f0e0 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/os-system.md @@ -0,0 +1,88 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/os-system + language: Python + severity: Error +title: Command execution without sanitization +--- +## Metadata +**ID:** `python-security/os-system` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Detect unsafe shell execution with the `os` module. We should ensure the command is safe before execution. Use `shlex` to sanitize user inputs. + +#### Learn More + + - [Python `os.system()` documentation](https://docs.python.org/3/library/os.html#os.system) + - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) + - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) + +## Non-Compliant Code Examples +```python +os.system(f'mv {saved_file_path} {public_upload_file_path}') +``` + +```python +command = f'convert "{temp_upload_file_path}" -resize 50% "{resized_image_path}"' +os.system(command) + + +command2 = f'convert "{temp_upload_file_path}" -resize 50% "{resized_image_path}"' +os.system(command4) +``` + +```python +import os + +directory = "/tmp" + +# Use of unsanitized data to execute a process +os.system("/bin/ls") +os.system("/bin/ls " + directory) + + +os.system(f'mv {saved_file_path} {public_upload_file_path}') + + +def file_upload_api(request, app): + file = request.files['file'] + + if not _validate_file(file.filename): + return { + 'message': 'Invalid file extension', + 'allowed_ext': ALLOWED_EXTENSIONS, + 'filename': file.filename + }, 422 + + saved_file_result = _save_temp_file(file, app) + saved_file_path = saved_file_result['saved_path'] + + file_name = Path(saved_file_path).name + + public_upload_file_path = os.path.join(app.config['PUBLIC_UPLOAD_FOLDER'], file_name) + + os.system(f'mv {saved_file_path} {public_upload_file_path}') + + return render_template('file_upload.html', file_url=f'{get_uploads_folder_url()}/{file_name}') +``` + +## Compliant Code Examples +```python +import os +import shlex + +# Use of shlex() to sanitize data +os.system(shlex.escape("/bin/ls")) + + +``` diff --git a/content/en/static_analysis/rules/python-security/request-verify.md b/content/en/static_analysis/rules/python-security/request-verify.md new file mode 100644 index 0000000000000..acb1dddf7833d --- /dev/null +++ b/content/en/static_analysis/rules/python-security/request-verify.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/request-verify + language: Python + severity: Error +title: verify should be True +--- +## Metadata +**ID:** `python-security/request-verify` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +The `verify` parameter controls whether the SSL certificate should be verified during your server requests. It's strongly recommended to set this parameter to `True` which is the default value. This rule will warn you when it's detected `False` has been set. + +## Non-Compliant Code Examples +```python +from requests import get +r = get(w, verify=False) # verify should be True +r = get(w, verify=False, timeout=10) # verify should be True +``` + +## Compliant Code Examples +```python +from requests import get +r = get(w) +r = get(w, timeout=10, verify=True) +``` + +```python +from requests import get +r = get(w) +r = get(w, timeout=10) +``` diff --git a/content/en/static_analysis/rules/python-security/requests-http.md b/content/en/static_analysis/rules/python-security/requests-http.md new file mode 100644 index 0000000000000..5211822365364 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/requests-http.md @@ -0,0 +1,72 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/requests-http + language: Python + severity: Warning +title: Do not make http calls without encryption +--- +## Metadata +**ID:** `python-security/requests-http` + +**Language:** Python + +**Severity:** Warning + +**Category:** Security + +## Description +Making a request with http enables attackers to listen to the traffic and obtain sensitive information. Use `https://` instead. + +#### Learn More + + - [CWE-319: Cleartext Transmission of Sensitive Information](https://cwe.mitre.org/data/definitions/319.html) + +## Non-Compliant Code Examples +```python +def test1(): + url1 = "http://api.tld" + requests.get(url1) + + +def test2(): + url2 = "http://api.tld/user/{0}".format(user_id) + requests.get(url2) + +def test3(): + url3 = f"http://api.tld/user/{user_id}" + requests.get(url3) + requests.get(url4) +``` + +```python +def test1(): + requests.get("http://api.tld") + requests.get("http://api.tld/user/{0}".format(user_id)) + requests.get(f"http://api.tld/user/{user_id}") +``` + +## Compliant Code Examples +```python +def download_stuff(identifier, data): + directory = "/tmp" + attachments = data.get("attachments", []) + + attachment_url = attachments[0].get("attachment_url", "") + + try: + response = requests.get(attachment_url, timeout=300) + response.raise_for_status() + except requests.exceptions.RequestException: + return (False, "") +``` + +```python +def test1(): + requests.get("https://api.tld") + requests.get("https://api.tld/user/{0}".format(user_id)) + requests.get(f"https://api.tld/user/{user_id}") +``` diff --git a/content/en/static_analysis/rules/python-security/requests-timeout.md b/content/en/static_analysis/rules/python-security/requests-timeout.md new file mode 100644 index 0000000000000..9f83c4abb7bb2 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/requests-timeout.md @@ -0,0 +1,64 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/requests-timeout + language: Python + severity: Error +title: no timeout was given on call to external resource +--- +## Metadata +**ID:** `python-security/requests-timeout` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Access to remote resources should always use a timeout and appropriately handle the timeout and recovery. When using `requests.get`, `requests.put`, `requests.patch`, etc. - we should always use a `timeout` as an argument. + +#### Learn More + + - [CWE-1088 - Synchronous Access of Remote Resource without Timeout](https://cwe.mitre.org/data/definitions/1088.html) + - [Python Best Practices: always use a timeout with the requests library](https://www.codiga.io/blog/python-requests-timeout/) + +## Non-Compliant Code Examples +```python +from requests import get, put +r = get(w, verify=False) # missing a timeout +r = get(w, verify=False, timeout=10) + +def bla(): + r = get(w, verify=False) +``` + +```python +import requests +r = requests.put(w, verify=False) # missing a timeout +``` + +```python +import requests +r = requests.get(w, verify=False) # missing a timeout +r = requests.get(w, verify=False, timeout=10) + + + +def foo(): + r = requests.get(w, verify=False) # missing a timeout +``` + +## Compliant Code Examples +```python +r = requests.put(w, verify=False) +``` + +```python +import requests +r = requests.get(w, verify=False, timeout=5) +r = requests.get(w, verify=False, timeout=10) +``` diff --git a/content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md b/content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md new file mode 100644 index 0000000000000..24ccda29f0d50 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md @@ -0,0 +1,55 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/ruamel-unsafe-yaml + language: Python + severity: Error +title: Do not use insecure YAML deserialization +--- +## Metadata +**ID:** `python-security/ruamel-unsafe-yaml` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Unsafe YAML deserialization. Make sure to use safe deserialization methods to avoid execution or arbitrary code. + +#### Learn More + + - [ruamel.yaml documentation](https://yaml.readthedocs.io/en/latest/basicuse.html?highlight=typ) + - [CWE 502 - Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html) + +## Non-Compliant Code Examples +```python +from ruamel.yaml import YAML + +foo = YAML(typ='unsafe') + +def myfunction(arg): + bar = YAML(typ='base') +``` + +## Compliant Code Examples +```python +foo = YAML(typ='unsafe') + +def myfunction(arg): + bar = YAML(typ='base') +``` + +```python +from ruamel.yaml import YAML + +default = YAML() + +rt = YAML(typ='rt') + +safe = YAML(typ='safe') +``` diff --git a/content/en/static_analysis/rules/python-security/sql-server-security-credentials.md b/content/en/static_analysis/rules/python-security/sql-server-security-credentials.md new file mode 100644 index 0000000000000..d8944d08ec526 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/sql-server-security-credentials.md @@ -0,0 +1,86 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/sql-server-security-credentials + language: Python + severity: Error +title: do not pass hardcoded credentials +--- +## Metadata +**ID:** `python-security/sql-server-security-credentials` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Hardcoding database credentials directly in your source code is a security risk as anyone with access to your source code and see your credentials. It's strongly recommended to use a different approach that limits the exposure of your credentials. + +## Non-Compliant Code Examples +```python +import psycopg2 + +conn = psycopg2.connect(database="db_name", + host="db_host", + user="db_user", + password="db_pass", # hardcoded password + port="db_port") +``` + +```python +import mysql.connector + +connection = mysql.connector.connect( + host=host, + user=user, + passwd=f"password", # hardcoded password + database=database, + charset='utf8mb4', + use_pure=True, + connection_timeout=5) +``` + +```python +import mysql.connector + +connection = mysql.connector.connect( + host=host, + user=user, + passwd="password", # hardcoded password + database=database, + charset='utf8mb4', + use_pure=True, + connection_timeout=5) +``` + +## Compliant Code Examples +```python +import mysql.connector + +connection = mysql.connector.connect( + host=host, + user=user, + passwd=password, + database=database, + charset='utf8mb4', + use_pure=True, + connection_timeout=5) +``` + +```python +import mysql.connector + +connection = mysql.connector.another_function( + host=host, + user=user, + passwd=f"password", + database=database, + charset='utf8mb4', + use_pure=True, + connection_timeout=5) +``` diff --git a/content/en/static_analysis/rules/python-security/ssl-unverified-context.md b/content/en/static_analysis/rules/python-security/ssl-unverified-context.md new file mode 100644 index 0000000000000..81416a90ca0db --- /dev/null +++ b/content/en/static_analysis/rules/python-security/ssl-unverified-context.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/ssl-unverified-context + language: Python + severity: Notice +title: should not bypass certificate verification +--- +## Metadata +**ID:** `python-security/ssl-unverified-context` + +**Language:** Python + +**Severity:** Notice + +**Category:** Security + +## Description +The call to `_create_unverified_context` from the ssl module bypass certificates verification. It should not be used and instead, certificates must be verified. + +## Non-Compliant Code Examples +```python +import xmlrpclib +import ssl + +test = xmlrpclib.ServerProxy('https://admin:bz15h9v9n@localhost:9999/API', + verbose=False, use_datetime=True, + context=ssl._create_unverified_context()) +test.list_satellites() +``` + +## Compliant Code Examples +```python +import xmlrpclib +import ssl + +test = xmlrpclib.ServerProxy('https://admin:bz15h9v9n@localhost:9999/API', + verbose=False, use_datetime=True) +test.list_satellites() +``` + +```python +import xmlrpclib + +test = xmlrpclib.ServerProxy('https://admin:bz15h9v9n@localhost:9999/API', + verbose=False, use_datetime=True, + context=ssl._create_unverified_context()) +test.list_satellites() +``` diff --git a/content/en/static_analysis/rules/python-security/subprocess-shell-true.md b/content/en/static_analysis/rules/python-security/subprocess-shell-true.md new file mode 100644 index 0000000000000..ccc85e8c7e727 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/subprocess-shell-true.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/subprocess-shell-true + language: Python + severity: Warning +title: shell argument leads to unnecessary privileges +--- +## Metadata +**ID:** `python-security/subprocess-shell-true` + +**Language:** Python + +**Severity:** Warning + +**Category:** Security + +## Description +Never invoke `subprocess.Popen` with `shell = True` leads to unnecessary privileges and access to the underlying execution runtime. Execution with `shell = True` should clearly be verified and checked for code in production. + +#### Learn More + + - [CWE-250](https://cwe.mitre.org/data/definitions/250.html) - Execution with Unnecessary Privileges + - [CWE-657](https://cwe.mitre.org/data/definitions/657.html) - Violation of Secure Design Principles + +## Non-Compliant Code Examples +```python +from subprocess import Popen +Popen('/bin/ls %s' % ('something',), shell=True) +``` + +```python +import subprocess +subprocess.Popen('/bin/ls %s' % ('something',), shell=True) +``` + +## Compliant Code Examples +```python +subprocess.Popen('/bin/ls %s' % ('something',), shell=True) +``` diff --git a/content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md b/content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md new file mode 100644 index 0000000000000..7b32f74745810 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md @@ -0,0 +1,145 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/variable-sql-statement-injection + language: Python + severity: Error +title: Avoid SQL injections +--- +## Metadata +**ID:** `python-security/variable-sql-statement-injection` + +**Language:** Python + +**Severity:** Error + +**Category:** Security + +## Description +Check for declarations of variables for a SQL statement where we have potential SQL injections. + +## Non-Compliant Code Examples +```python +def db_init_users(): + + users = [ + ('admin', 'SuperSecret'), + ('elliot', '123123123'), + ('tim', '12345678') + ] + + conn = sqlite3.connect('db_users.sqlite') + c = conn.cursor() + c.execute("CREATE TABLE users (username text, password text, failures int, mfa_enabled int, mfa_secret text)") + + for u,p in users: + c.execute("INSERT INTO users (username, password, failures, mfa_enabled, mfa_secret) VALUES ('%s', '%s', '%d', '%d', '%s')" %(u, p, 0, 0, '')) + + conn.commit() + conn.close() +``` + +```python +def get_product_by_id(db_connection, product_id): + cursor = db_connection.cursor() + res = cursor.execute(f"SELECT id, title from products WHERE id={product_id}") + data = res.fetchone() + if data is not None: + return Product(data[0], data[1]) + else: + return None + +def xss_reflected_page(request, app): + search = request.args.get('search') + + products = app.db_helper.execute_read( + f"SELECT * FROM products WHERE name LIKE :search", + { 'search': f'%{search}%' } + ) + + products = list( + map( + lambda p: { + 'id': p[0], + 'name': p[1], + 'price': p[2] + }, + products + ) + ) + + return render_template( + 'xss-reflected.html', + products=products + ) +``` + +```python +stmt = "UPDATE analysis_results SET running_time_sec='{0}' WHERE id={1}".format(nsec, id) + +stmt = "UPDATE analysis_results SET running_time_sec='%s' WHERE id=%s" % (nsec, id) + +stmt = "UPDATE analysis_results SET"\ + "running_time_sec='%s' WHERE id=%s" % nsec + + + +``` + +```python +v = "UPDATE bar SET plop={0}".format(plip) +``` + +```python +v = "UPDATE bar SET plop={0}".format(plip) + +cursor.execute("UPDATE bar SET plop={0}".format(plip)) + +cursor.execute("UPDATE `bar` SET plop={0}".format(plip)) +``` + +```python +v = f"DELETE FROM bar WHERE plop={bli}" + +cursor.execute(f"DELETE FROM bar WHERE plop={bli}") + +cursor.execute("DELETE FROM bar WHERE plop=%s", bli) +``` + +```python +v = f"SELECT foo FROM bar WHERE plop={bli}" +``` + +```python +v = "SELECT foo FROM bar WHERE plop={0}".format(bli) +``` + +## Compliant Code Examples +```python +def db_init_users(): + + users = [ + ('admin', 'SuperSecret'), + ('elliot', '123123123'), + ('tim', '12345678') + ] + + conn = sqlite3.connect('db_users.sqlite') + c = conn.cursor() + + for u,p in users: + c.execute("INSERT INTO users (username, password, failures, mfa_enabled, mfa_secret) VALUES ('%s', '%s', '%d', '%d', '%s')", (u, p, 0, 0, '')) + + conn.commit() + conn.close() +``` + +```python +v = "SELECT foo FROM bar WHERE plop=%s" +cursor.execute(v, (my_valie)) + +cursor.execute("UPDATE `bar` SET foo=%s", ("baz")) +``` diff --git a/content/en/static_analysis/rules/python-security/yaml-load.md b/content/en/static_analysis/rules/python-security/yaml-load.md new file mode 100644 index 0000000000000..36aaa0b8f4554 --- /dev/null +++ b/content/en/static_analysis/rules/python-security/yaml-load.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: python-security/yaml-load + language: Python + severity: Warning +title: avoid deserializing untrusted YAML +--- +## Metadata +**ID:** `python-security/yaml-load` + +**Language:** Python + +**Severity:** Warning + +**Category:** Security + +## Description +Avoid deserialization of untrusted YAML data via potential unsafe `yaml.load`. + +This rule checks that the `yaml` module is used and the `load` method is used. It recommends the usage of `safe_load` that prevents unsafe deserialization. + +**See Also** + + - [CWE-502 - Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html) + +## Non-Compliant Code Examples +```python +from yaml import load + +load("string") # should use safe_load +``` + +```python +import yaml + +yaml.load("string") # should use safe_load +``` + +## Compliant Code Examples +```python +import yaml + +yaml.load("string", loader=yaml.SafeLoader) # uses SafeLoader, so load is okay +``` + +```python +yaml.load("string") +``` diff --git a/content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md b/content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md new file mode 100644 index 0000000000000..16a624f5dfaa1 --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md @@ -0,0 +1,69 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: tsx-react/jsx-no-comment-textnodes + language: TypeScript + severity: Warning +title: Avoid comments from being inserted as text nodes +--- +## Metadata +**ID:** `tsx-react/jsx-no-comment-textnodes` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +As JSX mixes HTML and JavaScript together, comments in text nodes must be in brackets to be evaluated as JavaScript instead of HTML. This rule prevents you from accidentally leaving comments as HTML text. + +## Non-Compliant Code Examples +```typescript +var Hello = createReactClass({ + render: function() { + return ( +
+ asd /* empty div */ +
+ ); + } +}); + +var Hello = createReactClass({ + render: function() { + return ( +
+ /* empty div */ +
+ ); + } +}); +``` + +## Compliant Code Examples +```typescript +var Hello = createReactClass({ + displayName: 'Hello', + render: function() { + return
{/* empty div */}
; + } +}); + +var Hello = createReactClass({ + displayName: 'Hello', + render: function() { + return
; + } +}); + +var Hello = createReactClass({ + displayName: 'Hello', + render: function() { + return
; + } +}); +``` diff --git a/content/en/static_analysis/rules/tsx-react/no-children-prop.md b/content/en/static_analysis/rules/tsx-react/no-children-prop.md new file mode 100644 index 0000000000000..3fa06c732845f --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/no-children-prop.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: tsx-react/no-children-prop + language: TypeScript + severity: Warning +title: Avoid passing children as props +--- +## Metadata +**ID:** `tsx-react/no-children-prop` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +The children of a JSX element should appear as elements between the parent's opening and closing tags, not as props in the opening tag. This rule enforces the use of children as an element. + +## Non-Compliant Code Examples +```typescript +
; + +} />; +; + +React.createElement("div", { children: 'Children' }); +``` + +## Compliant Code Examples +```typescript +
Children
; +Children; + + Child 1 + Child 2 +; +React.createElement("div", {}, 'Children'); +React.createElement("div", 'Child 1', 'Child 2'); +``` diff --git a/content/en/static_analysis/rules/tsx-react/no-danger-with-children.md b/content/en/static_analysis/rules/tsx-react/no-danger-with-children.md new file mode 100644 index 0000000000000..d0585bdede83e --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/no-danger-with-children.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: tsx-react/no-danger-with-children + language: TypeScript + severity: Warning +title: Avoid using children with dangerouslySetInnerHTML +--- +## Metadata +**ID:** `tsx-react/no-danger-with-children` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +If both `children` and `dangerouslySetInnerHTML` are set, it's unclear which one should take precedence, and React will throw a warning. To prevent this mistake, this rule enforces that either children or dangerouslySetInnerHTML are used, but not both. + +## Non-Compliant Code Examples +```typescript +
{Children}
; +Children; +; +React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); +React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); +``` + +## Compliant Code Examples +```typescript +
; +; +
Children
; +Children; +React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }); +React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }); +React.createElement("div", {}, "Children"); +React.createElement("Hello", {}, "Children"); +``` diff --git a/content/en/static_analysis/rules/tsx-react/no-deprecated.md b/content/en/static_analysis/rules/tsx-react/no-deprecated.md new file mode 100644 index 0000000000000..7ed1cae95f933 --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/no-deprecated.md @@ -0,0 +1,73 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: tsx-react/no-deprecated + language: TypeScript + severity: Warning +title: Avoid deprecated methods +--- +## Metadata +**ID:** `tsx-react/no-deprecated` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +As React evolves, methods are deprecated over time. This rule warns you about deprecated methods. + +## Non-Compliant Code Examples +```typescript +React.render(, root); +React.unmountComponentAtNode(root); +React.findDOMNode(this.refs.foo); +React.renderToString(); +React.renderToStaticMarkup(); +React.createClass({ /* Class object */ }); + +//Any factories under React.DOM +React.DOM.div(); + +import React, { PropTypes } from 'react'; + +// old lifecycles (since React 16.9) +componentWillMount() { } +componentWillReceiveProps() { } +componentWillUpdate() { } + +// React 18 deprecations +import { render } from 'react-dom'; +ReactDOM.render(
, container); + +import { hydrate } from 'react-dom'; +ReactDOM.hydrate(
, container); + +import { unmountComponentAtNode } from 'react-dom'; +ReactDOM.unmountComponentAtNode(container); + +import { renderToNodeStream } from 'react-dom/server'; +ReactDOMServer.renderToNodeStream(element); +``` + +## Compliant Code Examples +```typescript +import { PropTypes } from 'prop-types'; + +UNSAFE_componentWillMount() { } +UNSAFE_componentWillReceiveProps() { } +UNSAFE_componentWillUpdate() { } + +ReactDOM.createPortal(child, container); + +import { createRoot } from 'react-dom/client'; +const root = createRoot(container); +root.unmount(); + +import { hydrateRoot } from 'react-dom/client'; +const root = hydrateRoot(container, ); +``` diff --git a/content/en/static_analysis/rules/tsx-react/no-render-return-value.md b/content/en/static_analysis/rules/tsx-react/no-render-return-value.md new file mode 100644 index 0000000000000..32565c66648ba --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/no-render-return-value.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: tsx-react/no-render-return-value + language: TypeScript + severity: Warning +title: Avoid usage of the return value of ReactDOM.render +--- +## Metadata +**ID:** `tsx-react/no-render-return-value` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Using the return value of the render method is a legacy feature. If you have a valid reason to reference the root React instance, you should assign a callback ref to the root component. + +## Non-Compliant Code Examples +```typescript +const inst = ReactDOM.render(, document.body); +``` + +## Compliant Code Examples +```typescript +ReactDOM.render(, document.body); + +ReactDOM.render(, document.body, doSomethingWithInst); +``` diff --git a/content/en/static_analysis/rules/tsx-react/no-string-refs.md b/content/en/static_analysis/rules/tsx-react/no-string-refs.md new file mode 100644 index 0000000000000..8a3b58d373ca0 --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/no-string-refs.md @@ -0,0 +1,58 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: tsx-react/no-string-refs + language: TypeScript + severity: Warning +title: Avoid using string references +--- +## Metadata +**ID:** `tsx-react/no-string-refs` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +String references are a legacy feature of React. Use a reference callback instead. + +## Non-Compliant Code Examples +```typescript +var Hello = createReactClass({ + render: function() { + return
; + } +}); +var Hello = createReactClass({ + render: function() { + return
Hello, world.
; + } +}); +var Hello = createReactClass({ + componentDidMount: function() { + var component = this.refs.hello; + // ...do something with component + }, + render: function() { + return
Hello, world.
; + } +}); +``` + +## Compliant Code Examples +```typescript +var Hello = createReactClass({ + componentDidMount: function() { + var component = this.hello; + // ...do something with component + }, + render() { + return
{ this.hello = c; }}>Hello, world.
; + } +}); +``` diff --git a/content/en/static_analysis/rules/tsx-react/require-render-return.md b/content/en/static_analysis/rules/tsx-react/require-render-return.md new file mode 100644 index 0000000000000..c3c37bdb3abbc --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/require-render-return.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: tsx-react/require-render-return + language: TypeScript + severity: Error +title: Enforce class for returning value in render function +--- +## Metadata +**ID:** `tsx-react/require-render-return` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +It's easy to forget to return a value from a class component render method. This rule warns when the render method does not return a value. + +## Non-Compliant Code Examples +```typescript +var Hello = createReactClass({ + render() { +
Hello
; + } +}); + +class Hello extends React.Component { + render() { +
Hello
; + } +} +``` + +## Compliant Code Examples +```typescript +var Hello = createReactClass({ + render() { + return
Hello
; + } +}); + +class Hello extends React.Component { + render() { + return
Hello
; + } +} +``` diff --git a/content/en/static_analysis/rules/tsx-react/tsx-key.md b/content/en/static_analysis/rules/tsx-react/tsx-key.md new file mode 100644 index 0000000000000..4439171509183 --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/tsx-key.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: tsx-react/tsx-key + language: TypeScript + severity: Error +title: Prevent missing key props in iterators/collection literals +--- +## Metadata +**ID:** `tsx-react/tsx-key` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +In JSX you need to specify a `key` prop for each item of a list. A missing `key` prop can lead to unexpected renders or stale UI. This rule checks for possible JSX lists and warns if the `key` prop is missing. + +## Non-Compliant Code Examples +```typescript +[<>]; +[, foo, ]; +[, foo, ]; +data.map(x => ); +data.map(x => {x}); +data.map(x => {x}); +data.map(x => { return {x}}); +data.map(x => { return {x}}); +data.map(function(x) { return {x}}); +data.map(function(x) { return {x}}); +Array.from([1, 2, 3], (x) => {x}); +``` + +## Compliant Code Examples +```typescript +[, , ]; +data.map((x) => {x}); +Array.from([1, 2, 3], (x) => {x}); + +``` diff --git a/content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md b/content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md new file mode 100644 index 0000000000000..963a8b774d745 --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: tsx-react/tsx-no-duplicate-key + language: TypeScript + severity: Error +title: Ensures unique key prop +--- +## Metadata +**ID:** `tsx-react/tsx-no-duplicate-key` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +Duplicate JSX element keys can lead to unexpected behavior. Keys are meant to be always unique. + +## Non-Compliant Code Examples +```typescript +[, foo, ]; +[, foo]; +[, ]; +data.map(x => ); +data.map(x => {x}); +data.map(x => {x}); +data.map(x => { return {x}}); +data.map(function(x) { return {x}}); +Array.from([1, 2, 3], (x) => {x}); +``` + +## Compliant Code Examples +```typescript +[, foo, ]; +data.map(x => { return {x}}); +``` diff --git a/content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md b/content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md new file mode 100644 index 0000000000000..a20b977a171dc --- /dev/null +++ b/content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md @@ -0,0 +1,49 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: tsx-react/tsx-no-target-blank + language: TypeScript + severity: Warning +title: Prevent target='_blank' security risks +--- +## Metadata +**ID:** `tsx-react/tsx-no-target-blank` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Using `target="_blank"` in an anchor (``) tag allows a link to be opened in a new browser tab or window. + +A malicious website opened through `target="_blank"` can change the `window.opener.location` to a phishing page, potentially misleading users. + +This rule enforces using `rel="noreferrer"` with on links that have the `target="_blank"` attribute. It might not be needed if you target modern browsers, but is still recommended to follow it as a best practice. + +#### Known Limitations + +This rule does not support custom link components without an `href`, `target` and `rel` properties. + +## Non-Compliant Code Examples +```typescript +var Hello = +var Hello = +var Nested = +var Nested = +``` + +## Compliant Code Examples +```typescript +var Hello =

+var Hello =

+var Hello = +var Hello = +var Hello = +var Hello = +var Hello = +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/ban-types.md b/content/en/static_analysis/rules/typescript-best-practices/ban-types.md new file mode 100644 index 0000000000000..ebd6811a2b5c6 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/ban-types.md @@ -0,0 +1,62 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/ban-types + language: TypeScript + severity: Notice +title: Avoid certain types +--- +## Metadata +**ID:** `typescript-best-practices/ban-types` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Some types have several ways to be defined, and some others could be dangerous. This rule suggests a consistent use of types. + +## Non-Compliant Code Examples +```typescript +// use lower-case primitives for consistency +const str: String = 'foo'; +const bool: Boolean = true; +const num: Number = 1; +const symb: Symbol = Symbol('foo'); +const bigInt: BigInt = 1n; + +// use a proper function type +const func: Function = () => 1; + +// use safer object types +const lowerObj: Object = {}; +const capitalObj: Object = { a: 'string' }; + +const curly1: {} = 1; +const curly2: {} = { a: 'string' }; +``` + +## Compliant Code Examples +```typescript +// use lower-case primitives for consistency +const str: string = 'foo'; +const bool: boolean = true; +const num: number = 1; +const symb: symbol = Symbol('foo'); +const bigInt: bigint = 1n; + +// use a proper function type +const func: () => number = () => 1; + +// use safer object types +const lowerObj: object = {}; +const capitalObj: { a: string } = { a: 'string' }; + +const curly1: number = 1; +const curly2: Record<'a', string> = { a: 'string' }; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md b/content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md new file mode 100644 index 0000000000000..ee1c6aa782de0 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-best-practices/boolean-prop-naming + language: TypeScript + severity: Notice +title: Consistent naming for boolean props +--- +## Metadata +**ID:** `typescript-best-practices/boolean-prop-naming` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Enforces a consistent naming pattern for boolean props. + +The pattern is: `"^(is|has)[A-Z]([A-Za-z0-9]?)+"` to enforce `is` and `has` prefixes. + +## Non-Compliant Code Examples +```typescript +type Props = { + enabled: boolean +} + +``` + +## Compliant Code Examples +```typescript +type Props = { + isEnabled: boolean; + hasFoo: boolean; +} + +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/for-direction.md b/content/en/static_analysis/rules/typescript-best-practices/for-direction.md new file mode 100644 index 0000000000000..013d99c73eded --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/for-direction.md @@ -0,0 +1,83 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/for-direction + language: TypeScript + severity: Error +title: Check for loop is moving in the right direction +--- +## Metadata +**ID:** `typescript-best-practices/for-direction` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +This rule prevents you from creating conditions in which a `for` loop might end up in an infinite loop. If you need an infinite loop, use `while` statements. + +## Non-Compliant Code Examples +```typescript +// test if '++', '--' +for(var i = 0; i < 10; i--){} +for(var i = 0; i <= 10; i--){} +for(var i = 10; i > 10; i++){} +for(var i = 10; i >= 0; i++){} + +// test if '+=', '-=' +for(var i = 0; i < 10; i-=1){} +for(var i = 0; i <= 10; i-=1){} +for(var i = 10; i > 10; i+=1){} +for(var i = 10; i >= 0; i+=1){} +for(var i = 0; i < 10; i+=-1){} +for(var i = 0; i <= 10; i+=-1){} +for(var i = 10; i > 10; i-=-1){} +for(var i = 10; i >= 0; i-=-1){} +``` + +## Compliant Code Examples +```typescript +// test if '++', '--' +for(var i = 0; i < 10; i++){} +for(var i = 0; i <= 10; i++){} +for(var i = 10; i > 0; i--){} +for(var i = 10; i >= 0; i--){} + +// test if '+=', '-=', +for(var i = 0; i < 10; i+=1){} +for(var i = 0; i <= 10; i+=1){} +for(var i = 0; i < 10; i-=-1){} +for(var i = 0; i <= 10; i-=-1){} +for(var i = 10; i > 0; i-=1){} +for(var i = 10; i >= 0; i-=1){} +for(var i = 10; i > 0; i+=-1){} +for(var i = 10; i >= 0; i+=-1){} + +// test if no update. +for(var i = 10; i > 0;){} +for(var i = 10; i >= 0;){} +for(var i = 10; i < 0;){} +for(var i = 10; i <= 0;){} +for(var i = 10; i <= 0; j++){} +for(var i = 10; i <= 0; j--){} +for(var i = 10; i >= 0; j++){} +for(var i = 10; i >= 0; j--){} +for(var i = 10; i >= 0; j += 2){} +for(var i = 10; i >= 0; j -= 2){} +for(var i = 10; i >= 0; i |= 2){} +for(var i = 10; i >= 0; i %= 2){} +for(var i = 0; i < MAX; i += STEP_SIZE); +for(var i = 0; i < MAX; i -= STEP_SIZE); +for(var i = 10; i > 0; i += STEP_SIZE); + +// other cond-expressions. +for(var i = 0; i !== 10; i+=1){} +for(var i = 0; i === 10; i+=1){} +for(var i = 0; i == 10; i+=1){} +for(var i = 0; i != 10; i+=1){} +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/new-parens.md b/content/en/static_analysis/rules/typescript-best-practices/new-parens.md new file mode 100644 index 0000000000000..a4f7f0c6daf49 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/new-parens.md @@ -0,0 +1,84 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/new-parens + language: TypeScript + severity: Notice +title: Invoking a constructor must use parentheses +--- +## Metadata +**ID:** `typescript-best-practices/new-parens` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +This rule enforces the consistent use of parentheses in `new` statements. In JavaScript, you can omit parentheses when the constructor has no arguments, but you should always use them for consistency. + +## Non-Compliant Code Examples +```typescript +// Default (Always) +var a = new Date; +var a = new Date +var a = new (Date); +var a = new (Date) +var a = (new Date) + +// This `()` is `CallExpression`'s. This is a call of the result of `new Date`. +var a = new foo.Bar; +var a = (new Foo).bar; + +// Explicit always +var a = new Date; +var a = new foo.Bar; +var a = (new Foo).bar; +var a = new new Foo(); + +// OPTION never not supported +// Never +// var a = new Date(); +// var a = new Date() +// var a = new (Date)(); +// var a = new (Date)() +// var a = (new Date()) +// var a = (new Date())() +// var a = new foo.Bar(); +// var a = (new Foo()).bar; +// var a = new new Foo() +``` + +## Compliant Code Examples +```typescript +// Default (Always) +var a = new Date(); +var a = new Date(function() {}); +var a = new (Date)(); +var a = new ((Date))(); +var a = (new Date()); +var a = new foo.Bar(); +var a = (new Foo()).bar; + +// Explicit Always +var a = new Date(); +var a = new foo.Bar(); +var a = (new Foo()).bar; + +// OPTION never not supported +// Never +// var a = new Date; +// var a = new Date(function() {}); +// var a = new (Date); +// var a = new ((Date)); +// var a = (new Date); +// var a = new foo.Bar; +// var a = (new Foo).bar; +// var a = new Person('Name') +// var a = new Person('Name', 12) +// var a = new ((Person))('Name'); +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-alert.md b/content/en/static_analysis/rules/typescript-best-practices/no-alert.md new file mode 100644 index 0000000000000..4098aa3027b95 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-alert.md @@ -0,0 +1,80 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-alert + language: TypeScript + severity: Notice +title: Avoid the use of alert, confirm, and prompt +--- +## Metadata +**ID:** `typescript-best-practices/no-alert` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +JavaScript’s `alert`, `confirm`, and `prompt` functions present obtrusive UI elements that prevent further user actions by taking control of the focus. These UI elements cannot be styled. + +## Non-Compliant Code Examples +```typescript +alert(foo) +window.alert(foo) +window['alert'](foo) +confirm(foo) +window.confirm(foo) +window['confirm'](foo) +prompt(foo) +window.prompt(foo) +window['prompt'](foo) +function alert() {} window.alert(foo) +var alert = function() {}; +window.alert(foo) +function foo(alert) { window.alert(); } +function foo() { alert(); } +function foo() { var alert = function() {}; } +alert(); +this.alert(foo) +this['alert'](foo) +function foo() { var window = bar; window.alert(); } +window.alert(); +globalThis['alert'](foo) +globalThis.alert(); +function foo() { var globalThis = bar; globalThis.alert(); } +globalThis.alert(); + +// Optional chaining +window?.alert(foo); +(window?.alert)(foo); +``` + +## Compliant Code Examples +```typescript +a[o.k](1) +foo.alert(foo) +foo.confirm(foo) +foo.prompt(foo) +// global overrides are not recommened +// and wont be supported by this rule +// function alert() {} alert(); +// var alert = function() {}; alert(); +// function foo() { var alert = bar; alert(); } +// function foo(alert) { alert(); } +// var alert = function() {}; function test() { alert(); } +// function foo() { var alert = function() {}; function test() { alert(); } } +// function confirm() {} confirm(); +// function prompt() {} prompt(); +window[alert](); +// function foo() { this.alert(); } +// function foo() { var window = bar; window.alert(); } +// globalThis.alert(); +// globalThis['alert'](); +// globalThis.alert(); +// var globalThis = foo; globalThis.alert(); +// function foo() { var globalThis = foo; globalThis.alert(); } +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md b/content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md new file mode 100644 index 0000000000000..b686444c32fac --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-async-promise-executor + language: TypeScript + severity: Error +title: Promise executor cannot be an async function +--- +## Metadata +**ID:** `typescript-best-practices/no-async-promise-executor` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +An async Promise executor won't surface exceptions if it fails. If you are already awaiting results in the executor, the Promise itself might not be required; please review your implementation. + +## Non-Compliant Code Examples +```typescript +new Promise(async function foo(resolve, reject) {}) +new Promise(async (resolve, reject) => {}) +``` + +## Compliant Code Examples +```typescript +new Promise((resolve, reject) => {}) +new Promise((resolve, reject) => {}, async function unrelated() {}) +new Foo(async (resolve, reject) => {}) +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-caller.md b/content/en/static_analysis/rules/typescript-best-practices/no-caller.md new file mode 100644 index 0000000000000..83676bb2be830 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-caller.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-caller + language: TypeScript + severity: Warning +title: Avoid the use of arguments.caller or arguments.callee +--- +## Metadata +**ID:** `typescript-best-practices/no-caller` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +`arguments.caller` and `arguments.callee` has been deprecated and forbidden in ECMAScript 5 strict mode. + +## Non-Compliant Code Examples +```typescript +var x = arguments.callee; +var x = arguments.caller; +``` + +## Compliant Code Examples +```typescript +var x = arguments.length +var x = arguments +var x = arguments[0] +var x = arguments[caller] +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md b/content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md new file mode 100644 index 0000000000000..4c02763c6f993 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md @@ -0,0 +1,69 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-compare-neg-zero + language: TypeScript + severity: Error +title: Direct comparison with -0 detected +--- +## Metadata +**ID:** `typescript-best-practices/no-compare-neg-zero` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +In JavaScript, `-0` and `+0` are considered to be equal (`(-0 === +0) // true`). However, they behave differently in some operations. For instance, `1/-0` results in `-Infinity`, while `1/+0` results in `+Infinity`. Directly comparing with `-0` can produce results that are hard to understand, and may lead to bugs. + +## Non-Compliant Code Examples +```typescript +x === -0; +-0 === x; +x == -0; +-0 == x; +x > -0; +-0 > x; +x >= -0; +-0 >= x; +x < -0; +-0 < x; +x <= -0; +-0 <= x; +``` + +## Compliant Code Examples +```typescript +x === 0 +0 === x +x == 0 +0 == x +x === '0' +'0' === x +x == '0' +'0' == x +x === '-0' +'-0' === x +x == '-0' +'-0' == x +x === -1 +-1 === x +x < 0 +0 < x +x <= 0 +0 <= x +x > 0 +0 > x +x >= 0 +0 >= x +x != 0 +0 != x +x !== 0 +0 !== x +Object.is(x, -0) +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md b/content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md new file mode 100644 index 0000000000000..977feb648fe1f --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md @@ -0,0 +1,74 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-cond-assign + language: TypeScript + severity: Error +title: Avoid assignment operators in conditional expressions +--- +## Metadata +**ID:** `typescript-best-practices/no-cond-assign` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +While there may be valid reasons to use an assignment operation in a condition, it is very easy to mistake `=` with `==`, which is usually what is intended. This rule prevents mistakes like these because it is easier to intentionally disable the rule than identify the error. + +## Non-Compliant Code Examples +```typescript +var x; if (x = 0) { var b = 1; } +var x; while (x = 0) { var b = 1; } +var x = 0, y; do { y = x; } while (x = x + 1); +var x; for(; x+=1 ;){}; +var x; if ((x) = (0)); +if (someNode || (someNode = parentNode)) { } +if (someNode || (someNode = parentNode)) { } +while (someNode || (someNode = parentNode)) { } +do { } while (someNode || (someNode = parentNode)); +for (; typeof l === 'undefined' ? (l = 0) : l; i++) { } +if (x = 0) { } +while (x = 0) { } +do { } while (x = x + 1); +for(; x = y; ) { } +var x; var b = (x = 0) ? 1 : 0; +var x; var b = x && (y = 0) ? 1 : 0; +(((3496.29)).bkufyydt = 2e308) ? foo : bar; + + +if ((someNode = someNode.parentNode) !== null) { } +if ((someNode = someNode.parentNode) !== null) { } +if (someNode || (someNode = parentNode)) { } +while (someNode || (someNode = parentNode)) { } +do { } while (someNode || (someNode = parentNode)); +for (;someNode || (someNode = parentNode);); +``` + +## Compliant Code Examples +```typescript +var x = 0; if (x == 0) { var b = 1; } +var x = 0; if (x == 0) { var b = 1; } +var x = 5; while (x < 5) { x = x + 1; } +if ((a = b)); +while ((a = b)); +do {} while ((a = b)); +for (;(a = b);); +for (;;) {} +if ((function(node) { return node = parentNode; })(someNode)) { } +if ((function(node) { return node = parentNode; })(someNode)) { } +if ((node => node = parentNode)(someNode)) { } +if ((node => node = parentNode)(someNode)) { } +if (function(node) { return node = parentNode; }) { } +if (function(node) { return node = parentNode; }) { } +x = 0; +var x; var b = (x === 0) ? 1 : 0; +switch (foo) { case a = b: bar(); } +switch (foo) { case a = b: bar(); } +switch (foo) { case baz + (a = b): bar(); } +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-console.md b/content/en/static_analysis/rules/typescript-best-practices/no-console.md new file mode 100644 index 0000000000000..ff2cad66719c2 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-console.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-console + language: TypeScript + severity: Warning +title: Avoid leaving console debug statements +--- +## Metadata +**ID:** `typescript-best-practices/no-console` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Debugging with `console` is not considered a bad practice, but it's easy to forget about `console` statements and leave them in production code. There is no need to pollute production builds with debugging statements. + +## Non-Compliant Code Examples +```typescript +console.log(foo) +console.error(foo) +console.info(foo) +console.warn(foo) +``` + +## Compliant Code Examples +```typescript +Console.info(foo) +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-debugger.md b/content/en/static_analysis/rules/typescript-best-practices/no-debugger.md new file mode 100644 index 0000000000000..bdb0df9754fdb --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-debugger.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-debugger + language: TypeScript + severity: Error +title: Disallow the use of debugger +--- +## Metadata +**ID:** `typescript-best-practices/no-debugger` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +The `debugger` statement is used to intentionally stop execution and start debugging at the point where the statement appears in the code. While it can be valuable during development and debugging, it can cause unwanted behaviors if it's present in production code. + +## Non-Compliant Code Examples +```typescript +if (foo) debugger +``` + +## Compliant Code Examples +```typescript +var test = { debugger: 1 }; test.debugger; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md b/content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md new file mode 100644 index 0000000000000..e486f1868ec63 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-delete-var + language: TypeScript + severity: Error +title: Avoid using delete on variables directly +--- +## Metadata +**ID:** `typescript-best-practices/no-delete-var` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +The `delete` operator is designed to remove properties from objects in JavaScript. When used correctly, it can help manage object properties. However, using the `delete` operator on anything other than object properties can lead to unpredictable behavior. + +## Non-Compliant Code Examples +```typescript +delete x +``` + +## Compliant Code Examples +```typescript +delete x.prop; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md b/content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md new file mode 100644 index 0000000000000..5328b1b4ac47f --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md @@ -0,0 +1,68 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-dupe-keys + language: TypeScript + severity: Error +title: Avoid duplicate keys in object literals +--- +## Metadata +**ID:** `typescript-best-practices/no-dupe-keys` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +Object literals should not have duplicate keys. If you define an object with duplicate keys, the last one will overwrite any preceding ones. + +## Non-Compliant Code Examples +```typescript +var x = { a: b, ['a']: b }; +var x = { y: 1, y: 2 }; +var x = { '': 1, '': 2 }; +var x = { '': 1, [``]: 2 }; +var foo = { 0x1: 1, 1: 2}; +// should be captured by no-octal +// var x = { 012: 1, 10: 2 }; +var x = { 0b1: 1, 1: 2 }; +var x = { 0o1: 1, 1: 2 }; +var x = { 1n: 1, 1: 2 }; +var x = { 1_0: 1, 10: 2 }; +var x = { "z": 1, z: 2 }; +var foo = { + bar: 1, + bar: 1, + bar() {} +} +var x = { a: 1, get ['a']() {} }; +var x = { a: 1, set a(value) {} }; +var x = { a: 1, b: { a: 2 }, get b() {} }; +var x = ({ '/(?0)/': 1, [/(?0)/]: 2 }) +``` + +## Compliant Code Examples +```typescript +var foo = { __proto__: 1, two: 2}; +var x = { foo: 1, bar: 2 }; +var x = { '': 1, bar: 2 }; +var x = { '': 1, ' ': 2 }; +var x = { '': 1, [null]: 2 }; +var x = { '': 1, [a]: 2 }; +var x = { [a]: 1, [a]: 2 }; ++{ get a() { }, set a(b) { } }; +var x = { a: b, [a]: b }; +var x = { a: b, ...c } +var x = { get a() {}, set a (value) {} }; +var x = { a: 1, b: { a: 2 } }; +var x = ({ null: 1, [/(?0)/]: 2 }) +var {a, a} = obj +// should be captured by no-octal +// var x = { 012: 1, 12: 2 }; +var x = { 1_0: 1, 1: 2 }; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md b/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md new file mode 100644 index 0000000000000..37508ec8fcbda --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md @@ -0,0 +1,108 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-duplicate-enum-values + language: TypeScript + severity: Warning +title: Avoid duplicate enum member values +--- +## Metadata +**ID:** `typescript-best-practices/no-duplicate-enum-values` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +An `enum` should not have duplicate values, which are usually not expected to be present. + +## Non-Compliant Code Examples +```typescript +enum A { + A = 1, + B = 1, +} +enum B { + A = 'A', + B = 'A', +} +enum C { + A = 'A', + B = 'A', + C = 1, + D = 1, +} +enum E { + A = 'A', + B = 'A', + C = 1, + D = 1, +} + +``` + +## Compliant Code Examples +```typescript +enum A { + A, + B, +} + +enum B { + A = 1, + B, +} + +enum C { + A = 1, + B = 2, +} + +enum D { + A = 'A', + B = 'B', +} + +enum E { + A = 'A', + B = 'B', + C, +} + +enum F { + A = 'A', + B = 'B', + C = 2, + D = 1 + 1, +} + +enum G { + A = 3, + B = 2, + C, +} + +enum H { + A = 'A', + B = 'B', + C = 2, + D = foo(), +} + +enum I { + A = '', + B = 0, +} + +enum J { + A = 0, + B = -0, + C = NaN, +} + +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md b/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md new file mode 100644 index 0000000000000..055e29b8b675b --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md @@ -0,0 +1,112 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-duplicate-type-constituents + language: TypeScript + severity: Warning +title: Avoid duplicate constituents of unions or intersections +--- +## Metadata +**ID:** `typescript-best-practices/no-duplicate-type-constituents` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Union and intersection types could duplicate each other. Duplicate values make the code harder to read and are usually not expected. + +## Non-Compliant Code Examples +```typescript +type A = 1 | 1; +type B = true & true; +type C = null | null; +type D = any | any; +type E = { a: string | string }; +type F = { a: string } | { a: string }; +type G = { a: string; b: number } | { a: string; b: number }; +type H = Set | Set; +type ActuallyDuplicated = IsArray | IsArray; +type I = Class | Class; +type J = string[] | string[]; +type K = string[][] | string[][]; +type L = [1, 2, 3] | [1, 2, 3]; +type M = () => string | string; +type N = () => null | null; +type O = (arg: string | string) => void; +type P = 'A' | 'A'; +type S = A | A; +type T = A | /* comment */ A; +type U = A | B | A; +type V = A | B | A | B; +type W = A | B | A | A; +type X = A | B | A | C; +type Y = (A | B) | (A | B); +type Z = A | (A | A); +type AA = (A | B) | (A | B) | ((C | D) & (A | B)) | (A | B); +type BB = Record; + +``` + +## Compliant Code Examples +```typescript +type A = 1 | 2; +type B = 1 | '1'; +type C = true & boolean; +type D = null | undefined; +type E = any | unknown; +type F = { a: string } | { b: string }; +type G = { a: string; b: number } | { b: number; a: string }; +type H = { a: string | number }; +type I = Set | Set; +type J = Class | Class; +type K = string[] | number[]; +type L = string[][] | string[]; +type M = [1, 2, 3] | [1, 2, 4]; +type N = [1, 2, 3] | [1, 2, 3, 4]; +type O = 'A' | string[]; +type P = (() => string) | (() => void); +type Q = () => string | void; +type R = () => null | undefined; +type S = (arg: string | number) => void; + +type T = 'A'; +type U = 'B'; +type V = A | B; + +type W = 'A'; +type X = 'B'; +const a: A | B = 'A'; + +type Y = 'A'; +type Z = 'B'; +type AA = A | /* comment */ B; + +type BB = 'A'; +type CC = 'B'; +type DD = 'A' | 'B'; + +type EE = 'A'; +type FF = 'B'; +type GG = 'C'; +type HH = A | B | C; + +type JJ = 'A'; +type KK = 'B'; +type LL = 'C'; +type MM = 'D'; +type NN = (A | B) | (C | D); + +type OO = 'A'; +type PP = 'B'; +type QQ = (A | B) | (A & B); + +type RR = 'A'; +type SS = 'B'; +type TT = Record; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md b/content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md new file mode 100644 index 0000000000000..45c430986defb --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md @@ -0,0 +1,52 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-empty-character-class + language: TypeScript + severity: Error +title: Avoid empty character classes in regular expressions +--- +## Metadata +**ID:** `typescript-best-practices/no-empty-character-class` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +In regular expressions, empty character classes do not match anything, and were likely used in error. + +## Non-Compliant Code Examples +```typescript +var foo = /^abc[]/; +var foo = /foo[]bar/; +if (foo.match(/^abc[]/)) {} +if (/^abc[]/.test(foo)) {} +var foo = /[]]/; +var foo = /\[[]/; +var foo = /\\[\\[\\]a-z[]/; +var foo = /[]]/d; +``` + +## Compliant Code Examples +```typescript +var foo = /^abc[a-zA-Z]/; +var regExp = new RegExp("^abc[]"); +var foo = /^abc/; +var foo = /[\\[]/; +var foo = /[\\]]/; +var foo = /[a-zA-Z\\[]/; +var foo = /[[]/; +var foo = /[\\[a-z[]]/; +var foo = /[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\^\\$\\|]/g; +var foo = /\\s*:\\s*/gim; +var foo = /[\\]]/uy; +var foo = /[\\]]/s; +var foo = /[\\]]/d; +var foo = /\[]/ +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md b/content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md new file mode 100644 index 0000000000000..da58d32f8194e --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-empty-pattern + language: TypeScript + severity: Error +title: Avoid empty destructuring patterns +--- +## Metadata +**ID:** `typescript-best-practices/no-empty-pattern` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +An empty destructuring pattern doesn't provide any value and might be confusing, as it looks similar to the default assignment. + +## Non-Compliant Code Examples +```typescript +var {} = foo +var [] = foo +var {a: {}} = foo +var {a, b: {}} = foo +var {a: []} = foo +function foo({}) {} +function foo([]) {} +function foo({a: {}}) {} +function foo({a: []}) {} +``` + +## Compliant Code Examples +```typescript +var {a = {}} = foo; +var {a, b = {}} = foo; +var {a = []} = foo; +function foo({a = {}}) {} +function foo({a = []}) {} +var [a] = foo +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-empty.md b/content/en/static_analysis/rules/typescript-best-practices/no-empty.md new file mode 100644 index 0000000000000..a7ea1048599b5 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-empty.md @@ -0,0 +1,77 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-empty + language: TypeScript + severity: Error +title: Avoid empty block statements +--- +## Metadata +**ID:** `typescript-best-practices/no-empty` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +Empty or non-functional blocks in the code can be misleading and lead to maintenance difficulties. They can also lead to a false sense of security or functionality. While they may not directly introduce security issues, their presence can suggest that some logic or error handling is implemented when it is not. + +## Non-Compliant Code Examples +```typescript +try {} catch (ex) {throw ex} +try { foo() } catch (ex) {} +try { foo() } catch (ex) {throw ex} finally {} +if (foo) {} +while (foo) {} +for (;foo;) {} +switch(foo) {} +switch (foo) { /* empty */ } +try {} catch (ex) {} +try { foo(); } catch (ex) {} finally {} +try {} catch (ex) {} finally {} +try { foo(); } catch (ex) {} finally {} +(function() { }()) +var foo = () => {} +function foo() { } +function bla() { + +} +``` + +## Compliant Code Examples +```typescript +export async function foo() { + const test = {}; +} +if (foo) { bar() } +while (foo) { bar() } +for (;foo;) { bar() } +try { foo() } catch (ex) { foo() } +switch(foo) {case 'foo': break;} +if (foo) {/* empty */} +while (foo) {/* empty */} +for (;foo;) {/* empty */} +try { foo() } catch (ex) {/* empty */} +try { foo() } catch (ex) {// empty +} +try { foo() } finally {// empty +} +try { foo() } finally {// test +} +try { foo() } finally { + + // hi i am off no use +} +try { foo() } catch (ex) {/* test111 */} +if (foo) { bar() } else { // nothing in me +} +if (foo) { bar() } else { /**/ +} +if (foo) { bar() } else { // +} +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md b/content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md new file mode 100644 index 0000000000000..59233b530f1a1 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-ex-assign + language: TypeScript + severity: Error +title: Avoid reassigning exceptions in catch clauses +--- +## Metadata +**ID:** `typescript-best-practices/no-ex-assign` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +Catching an exception and assigning a different value to the error parameter will overwrite the reference to the original error data, which will be lost since there is no `arguments` object in a catch clause. + +## Non-Compliant Code Examples +```typescript +try { } catch (e) { e = 10; } +try { } catch (ex) { ex = 10; } +try { } catch (ex) { [ex] = []; } +try { } catch (ex) { ({x: ex = 0} = {}); } +try { } catch ({message}) { message = 10; } +``` + +## Compliant Code Examples +```typescript +try { } catch (e) { three = 2 + 1; } +try { } catch ({e}) { this.something = 2; } +function foo() { try { } catch (e) { return false; } } +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md b/content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md new file mode 100644 index 0000000000000..62a352163ae8a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md @@ -0,0 +1,175 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-explicit-any + language: TypeScript + severity: Notice +title: Avoid the any type +--- +## Metadata +**ID:** `typescript-best-practices/no-explicit-any` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not use the `any` type, as it is too broad and can lead to unexpected behavior. + +## Non-Compliant Code Examples +```typescript +const number: any = 1 +function generic(): any {} +function generic(): Array {} +function generic(): any[] {} +function generic(param: Array): number {} +function generic(param: any[]): number {} +function generic(param: Array): Array {} + +function generic(): Array> {} +function generic(): Array {} + +class Greeter { constructor(param: Array) {} } +class Greeter { message: any; } + +class Greeter { message: Array; } +class Greeter { message: any[]; } +class Greeter { message: Array>; } +class Greeter { message: Array; } + +interface Greeter { message: any; } +interface Greeter { message: Array; } +interface Greeter { message: any[]; } +interface Greeter { message: Array>; } +interface Greeter { message: Array; } +type obj = { message: any; } +type obj = { message: Array; } +type obj = { message: any[]; } +type obj = { message: Array>; } +type obj = { message: Array; } +type obj = { message: string | any; } +type obj = { message: string | Array; } +type obj = { message: string | any[]; } +type obj = { message: string | Array>; } +type obj = { message: string | Array; } +type obj = { message: string & any; } +type obj = { message: string & Array; } +type obj = { message: string & any[]; } +type obj = { message: string & Array>; } +type obj = { message: string & Array; } +class Foo extends Bar {} +abstract class Foo extends Bar {} +abstract class Foo implements Bar, Baz {} +new Foo() +Foo() + +// https://github.com/typescript-eslint/typescript-eslint/issues/64 +function test>() {} +const test = >() => {}; +function foo(a: number, ...rest: any[]): void { return; } +type Any = any; +function foo5(...args: any) {} + +const bar5 = function (...args: any) {} +const baz5 = (...args: any) => {} +interface Qux5 { (...args: any): void; } +function quux5(fn: (...args: any) => void): void {} +function quuz5(): ((...args: any) => void) {} +type Fred5 = (...args: any) => void; +type Corge5 = new (...args: any) => void; +interface Grault5 { new (...args: any): void; } +interface Garply5 { f(...args: any): void; } +declare function waldo5(...args: any): void; +``` + +## Compliant Code Examples +```typescript +const number: number = 1; +function greet(): string {} +function greet(): Array {} +function greet(): string[] {} +function greet(): Array> {} +function greet(): Array {} +function greet(param: Array): Array {} + +class Greeter { message: string; } +class Greeter { message: Array; } +class Greeter { message: string[]; } +class Greeter { message: Array>; } +class Greeter { message: Array; } +interface Greeter { message: string; } +interface Greeter { message: Array; } +interface Greeter { message: string[]; } +interface Greeter { message: Array>; } +interface Greeter { message: Array; } +type obj = { message: string; }; +type obj = { message: Array; }; +type obj = { message: string[]; }; +type obj = { message: Array>; }; +type obj = { message: Array; }; +type obj = { message: string | number }; +type obj = { message: string | Array; }; +type obj = { message: string | string[]; }; +type obj = { message: string | Array>; }; +type obj = { message: string & number; }; +type obj = { message: string & Array; }; +type obj = { message: string & string[]; }; +type obj = { message: string & Array>; }; + +// rest params enforces due to no options +// https://github.com/eslint/typescript-eslint-parser/issues/397 +// function foo(a: number, ...rest: any[]): void { return; } +// function foo1(...args: any[]) {} +// const bar1 = function (...args: any[]) {}; +// const baz1 = (...args: any[]) => {}; +// function foo2(...args: readonly any[]) {} +// const bar2 = function (...args: readonly any[]) {}; +// const baz2 = (...args: readonly any[]) => {}; +// function foo3(...args: Array) {} +// const bar3 = function (...args: Array) {}; +// const baz3 = (...args: Array) => {}; +// function foo4(...args: ReadonlyArray) {} +// const bar4 = function (...args: ReadonlyArray) {}; +// const baz4 = (...args: ReadonlyArray) => {}; + +// interface Qux1 { (...args: any[]): void; } +// interface Qux2 { (...args: readonly any[]): void; } +// interface Qux3 { (...args: Array): void; } +// interface Qux4 { (...args: ReadonlyArray): void; } + +// function quux1(fn: (...args: any[]) => void): void {} +// function quux2(fn: (...args: readonly any[]) => void): void {} +// function quux3(fn: (...args: Array) => void): void {} +// function quux4(fn: (...args: ReadonlyArray) => void): void {} +// function quuz1(): (...args: any[]) => void {} +// function quuz2(): (...args: readonly any[]) => void {} +// function quuz3(): (...args: Array) => void {} +// function quuz4(): (...args: ReadonlyArray) => void {} +// type Fred1 = (...args: any[]) => void; +// type Fred2 = (...args: readonly any[]) => void; +// type Fred3 = (...args: Array) => void; +// type Fred4 = (...args: ReadonlyArray) => void; +// type Corge1 = new (...args: any[]) => void; +// type Corge2 = new (...args: readonly any[]) => void; +// type Corge3 = new (...args: Array) => void; +// type Corge4 = new (...args: ReadonlyArray) => void; + +// interface Grault1 { new (...args: any[]): void; } +// interface Grault2 { new (...args: readonly any[]): void; } +// interface Grault3 { new (...args: Array): void; } +// interface Grault4 { new (...args: ReadonlyArray): void; } +// interface Garply1 { f(...args: any[]): void; } +// interface Garply2 { f(...args: readonly any[]): void; } +// interface Garply3 { f(...args: Array): void; } +// interface Garply4 { f(...args: ReadonlyArray): void; } + +// declare function waldo1(...args: any[]): void; +// declare function waldo2(...args: readonly any[]): void; +// declare function waldo3(...args: Array): void; +// declare function waldo4(...args: ReadonlyArray): void; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md b/content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md new file mode 100644 index 0000000000000..a5a34d5c0d9ed --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md @@ -0,0 +1,58 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-extra-non-null-assertion + language: TypeScript + severity: Error +title: Avoid extra non-null assertions +--- +## Metadata +**ID:** `typescript-best-practices/no-extra-non-null-assertion` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +The non `null` or `undefined` assertion operation should not be used twice in a single expression. + +## Non-Compliant Code Examples +```typescript +const bar = foo!!.bar; +function foo(bar: number | undefined) { const bar: number = bar!!; } +function foo(bar?: { n: number }) { return bar!?.n; } +function foo(bar?: { n: number }) { return bar!?.(); } + +// parentheses +const foo: { bar: number } | null = null; const bar = (foo!)!.bar; +function foo(bar?: { n: number }) { return (bar!)?.n; } +function foo(bar?: { n: number }) { return (bar)!?.n; } +function foo(bar?: { n: number }) { return (bar!)?.(); } +``` + +## Compliant Code Examples +```typescript +const bar = foo!.bar; + +function foo(bar: number | undefined) { + const bar: number = bar!; +} + +function foo(bar?: { n: number }) { + return bar?.n; +} + +// https://github.com/typescript-eslint/typescript-eslint/issues/2166 +checksCounter?.textContent!.trim(); + +// https://github.com/typescript-eslint/typescript-eslint/issues/2732 +function foo(key: string | null) { + const obj = {}; + return obj?.[key!]; +} +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md b/content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md new file mode 100644 index 0000000000000..cb33644ff17d7 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md @@ -0,0 +1,180 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-best-practices/no-implied-eval + language: TypeScript + severity: Warning +title: Prevent the use methods similar to eval() +--- +## Metadata +**ID:** `typescript-best-practices/no-implied-eval` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +JavaScript methods like `setTimeout()`, `setInterval()`, or `execScript()` can accept a string of code as their first argument. This code will be executed at runtime, opening a vector for potential attacks. + +It is generally considered a bad practice to execute code at runtime. This rule considers these methods as implied evaluations when their parameter is a piece of code. + +## Non-Compliant Code Examples +```typescript +setTimeout("x = 1;"); +setTimeout("x = 1;", 100); +setInterval("x = 1;"); +execScript("x = 1;"); +// const s = 'x=1'; setTimeout(s, 100); +setTimeout(String('x=1'), 100); + +// member expressions +window.setTimeout('foo'); +window.setInterval('foo'); +window['setTimeout']('foo'); +window['setInterval']('foo'); +window[`setInterval`]('foo'); +window.window['setInterval']('foo'); +global.setTimeout('foo'); +global.setInterval('foo'); +global['setTimeout']('foo'); +global['setInterval']('foo'); +global[`setInterval`]('foo'); +global.global['setInterval']('foo'); +globalThis.setTimeout('foo'); +globalThis.setInterval('foo'); + +// template literals +setTimeout(`foo${bar}`); +window.setTimeout(`foo${bar}`); +window.window.setTimeout(`foo${bar}`); +global.global.setTimeout(`foo${bar}`); + +// string concatenation +setTimeout('foo' + bar); +setTimeout(foo + 'bar'); +setTimeout(`foo` + bar); +setTimeout(1 + ';' + 1); +window.setTimeout('foo' + bar); +window.setTimeout(foo + 'bar'); +window.setTimeout(`foo` + bar); +window.setTimeout(1 + ';' + 1); +window.window.setTimeout(1 + ';' + 1); +global.setTimeout('foo' + bar); +global.setTimeout(foo + 'bar'); +global.setTimeout(`foo` + bar); +global.setTimeout(1 + ';' + 1); +global.global.setTimeout(1 + ';' + 1); +globalThis.setTimeout('foo' + bar); + +// gives the correct node when dealing with nesting +setTimeout('foo' + (function() { + setTimeout(helper); + execScript('str'); + return 'bar'; +})()); + +window.setTimeout('foo' + (function() { + setTimeout(helper); + window.execScript('str'); + return 'bar'; +})()); + +global.setTimeout('foo' + (function() { + setTimeout(helper); + global.execScript('str'); + return 'bar'; +})()); + +// Optional chaining +window?.setTimeout('code', 0); +(window?.setTimeout)('code', 0); +``` + +## Compliant Code Examples +```typescript +setTimeout(); + +setTimeout; +setTimeout = foo; +window.setTimeout; +window.setTimeout = foo; +window['setTimeout']; +window['setTimeout'] = foo; +global.setTimeout; +global.setTimeout = foo; +global['setTimeout']; +global['setTimeout'] = foo; +globalThis['setTimeout'] = foo; + +window[`SetTimeOut`]('foo', 100); +global[`SetTimeOut`]('foo', 100); +global[`setTimeout${foo}`]('foo', 100); +global[`setTimeout${foo}`]('foo', 100); +globalThis[`setTimeout${foo}`]('foo', 100); + +// normal usage +setTimeout(function() { x = 1; }, 100); +setInterval(function() { x = 1; }, 100) +execScript(function() { x = 1; }, 100) +window.setTimeout(function() { x = 1; }, 100); +window.setInterval(function() { x = 1; }, 100); +window.execScript(function() { x = 1; }, 100); +window.setTimeout(foo, 100); +window.setInterval(foo, 100); +window.execScript(foo, 100); +global.setTimeout(function() { x = 1; }, 100); +global.setInterval(function() { x = 1; }, 100); +global.execScript(function() { x = 1; }, 100); +global.setTimeout(foo, 100); +global.setInterval(foo, 100); +global.execScript(foo, 100); +globalThis.setTimeout(foo, 100); + +// only checks on top-level statements or window.* +foo.setTimeout('hi') + +// identifiers are fine +setTimeout(foo, 10) +setInterval(1, 10) +execScript(2) + +// as are function expressions +setTimeout(function() {}, 10) + +// setInterval +foo.setInterval('hi') +setInterval(foo, 10) +setInterval(function() {}, 10) + +// execScript +foo.execScript('hi') +execScript(foo) +execScript(function() {}) + +// a binary plus on non-strings doesn't guarantee a string +// setTimeout(foo + bar, 10) + +// doesn't check anything but the first argument +setTimeout(foobar, 'buzz') +setTimeout(foobar, foo + 'bar') + +// only checks immediate subtrees of the argument +setTimeout(function() { return 'foobar'; }, 10) + +// https://github.com/eslint/eslint/issues/7821 +setTimeoutFooBar('Foo Bar') + +foo.window.setTimeout('foo', 100); +foo.global.setTimeout('foo', 100); +// var window; window.setTimeout('foo', 100); +// var global; global.setTimeout('foo', 100); +// function foo(window) { window.setTimeout('foo', 100); } +// function foo(global) { global.setTimeout('foo', 100); } +foo('', window.setTimeout); +foo('', global.setTimeout); +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md b/content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md new file mode 100644 index 0000000000000..378c9351911a9 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md @@ -0,0 +1,71 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-inner-declarations + language: TypeScript + severity: Warning +title: Avoid variable or function declaration in nested blocks +--- +## Metadata +**ID:** `typescript-best-practices/no-inner-declarations` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Function declarations in JavaScript are generally not block scoped. This rule prevents function declarations inside nested blocks like `if` statements. Move your declarations to the root of your program, body, or class. + +## Non-Compliant Code Examples +```typescript +if (test) { function doSomething() { } } +if (foo) var a; +if (foo) /* some comments */ var a; +if (foo){ function f(){ if(bar){ var a; } } } +if (foo) function f(){ if(bar) var a; } +if (foo) { var fn = function(){} } +if (foo) function f(){} +function bar() { if (foo) var a; } +if (foo){ var a; } +class C { method() { if(test) { var foo; } } } +class C { static { if (test) { function foo() {} } } } +class C { static { if (test) { var foo; } } } +class C { static { if (test) { if (anotherTest) { var foo; } } } } +``` + +## Compliant Code Examples +```typescript +function doSomething() { } +function doSomething() { function somethingElse() { } } +(function() { function doSomething() { } }()); +function decl() { var fn = function expr() { }; } +function decl(arg) { var fn; if (arg) { fn = function() { }; } } +var x = {doSomething() {function doSomethingElse() {}}} +function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } +function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } +if (test) { let x = 1; } +if (test) { const x = 1; } +function doSomething() { while (test) { var foo; } } +var foo; +var foo = 42; +function doSomething() { var foo; } +(function() { var foo; }()); +foo(() => { function bar() { } }); +var fn = () => {var foo;} +var x = {doSomething() {var foo;}} +export var foo; +export function bar() {} +export default function baz() {} +exports.foo = () => {} +exports.foo = function(){} +module.exports = function foo(){} +class C { method() { function foo() {} } } +class C { method() { var x; } } +class C { static { function foo() {} } } +class C { static { var x; } } +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-iterator.md b/content/en/static_analysis/rules/typescript-best-practices/no-iterator.md new file mode 100644 index 0000000000000..036a57533274f --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-iterator.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-iterator + language: TypeScript + severity: Warning +title: Avoid the use of the __iterator__ property +--- +## Metadata +**ID:** `typescript-best-practices/no-iterator` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +The `__iterator__` property was exclusive to the SpiderMonkey engine. Avoid using it as other JavaScript engines do not implement it. + +## Non-Compliant Code Examples +```typescript +var a = test.__iterator__; +Foo.prototype.__iterator__ = function() {}; +var a = test['__iterator__']; +var a = test[`__iterator__`]; +test[`__iterator__`] = function () {}; +``` + +## Compliant Code Examples +```typescript +var a = test[__iterator__]; +var __iterator__ = null; +foo[`__iterator`] = null; +foo[`__iterator__ +`] = null; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md b/content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md new file mode 100644 index 0000000000000..1b84ebcec6404 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md @@ -0,0 +1,131 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-loss-of-precision + language: TypeScript + severity: Error +title: Avoid numbers that lose precision +--- +## Metadata +**ID:** `typescript-best-practices/no-loss-of-precision` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +JavaScript uses double-precision, floating-point numbers in accordance with the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754). This means numbers are only accurate until a certain amount of digits. Adding more digits will make the number lose precision, as the added digits will be lost in the conversion to the `Number` type, causing unexpected behavior. + +## Non-Compliant Code Examples +```typescript +var x = 9007199254740993 +var x = 9007199254740.993e3 +var x = 9.007199254740993e15 +var x = -9007199254740993 +var x = 900719.9254740994 +var x = -900719.9254740994 +var x = 900719925474099_3 +var x = 90_0719925_4740.9_93e3 +var x = 9.0_0719925_474099_3e15 +var x = -9_00719_9254_740993 +var x = 900_719.92_54740_994 +var x = -900_719.92_5474_0994 +var x = 5123000000000000000000000000001 +var x = -5123000000000000000000000000001 +var x = 1230000000000000000000000.0 +var x = 1.0000000000000000000000123var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 +var x = 2e999 +var x = .1230000000000000000000000 +var x = 0b100000000000000000000000000000000000000000000000000001 +var x = 0B100000000000000000000000000000000000000000000000000001 +var x = 0o400000000000000001 +var x = 0O400000000000000001 +var x = 0400000000000000001 +var x = 0x20000000000001 +var x = 0X20000000000001 +var x = 5123_00000000000000000000000000_1 +var x = -5_12300000000000000000000_0000001 +var x = 123_00000000000000000000_00.0_0 +var x = 1.0_00000000000000000_0000123 +var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 +var x = 2e9_99 +var x = .1_23000000000000_00000_0000_0 +var x = 0b1_0000000000000000000000000000000000000000000000000000_1 +var x = 0B10000000000_0000000000000000000000000000_000000000000001 +var x = 0o4_00000000000000_001 +var x = 0O4_0000000000000000_1 +var x = 0x2_0000000000001 +var x = 0X200000_0000000_1 +``` + +## Compliant Code Examples +```typescript +var x = 12345 +var x = 123.456 +var x = -123.456 +var x = -123456 +var x = 123e34 +var x = 123.0e34 +var x = 123e-34 +var x = -123e34 +var x = -123e-34 +var x = 12.3e34 +var x = 12.3e-34 +var x = -12.3e34 +var x = -12.3e-34 +var x = 12300000000000000000000000 +var x = -12300000000000000000000000 +var x = 0.00000000000000000000000123 +var x = -0.00000000000000000000000123 +var x = 9007199254740991 +var x = 0 +var x = 0.0 +var x = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000 +var x = -0 +var x = 123.0000000000000000000000 +var x = 0e5 +var x = 12_34_56 +var x = 12_3.4_56 +var x = -12_3.4_56 +var x = -12_34_56 +var x = 12_3e3_4 +var x = 123.0e3_4 +var x = 12_3e-3_4 +var x = 12_3.0e-3_4 +var x = -1_23e-3_4 +var x = -1_23.8e-3_4 +var x = 1_230000000_00000000_00000_000 +var x = -1_230000000_00000000_00000_000 +var x = 0.0_00_000000000_000000000_00123 +var x = -0.0_00_000000000_000000000_00123 +var x = 0e5_3 + +var x = 0b11111111111111111111111111111111111111111111111111111 +var x = 0b111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 +var x = 0B11111111111111111111111111111111111111111111111111111 +var x = 0B111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 +var x = 0o377777777777777777 +var x = 0o3_77_777_777_777_777_777 +var x = 0O377777777777777777 + +var x = 0377777777777777777 +var x = 0x1FFFFFFFFFFFFF +var x = 0X1FFFFFFFFFFFFF +var x = true +var x = 'abc' +var x = '' +var x = null +var x = undefined +var x = {} +var x = ['a', 'b'] +var x = new Date() +var x = '9007199254740993' + +var x = 0x1FFF_FFFF_FFF_FFF +var x = 0X1_FFF_FFFF_FFF_FFF +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-namespace.md b/content/en/static_analysis/rules/typescript-best-practices/no-namespace.md new file mode 100644 index 0000000000000..b29de7a2733ab --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-namespace.md @@ -0,0 +1,73 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-namespace + language: TypeScript + severity: Notice +title: Avoid TypeScript namespaces +--- +## Metadata +**ID:** `typescript-best-practices/no-namespace` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Namespaces should be avoided as an outdated feature of TypeScript. Use module syntax instead. + +## Non-Compliant Code Examples +```typescript +module foo {} +namespace foo {} +module foo {} +namespace foo {} +module foo {} +namespace foo {} +declare module foo {} +declare namespace foo {} +declare module foo {} +declare namespace foo {} +namespace foo {} +module foo {} +declare module foo {} +declare namespace foo {} +namespace Foo.Bar {} +namespace Foo.Bar { namespace Baz.Bas { interface X {} } } +namespace A { namespace B { declare namespace C {} } +namespace A { namespace B { export declare namespace C {} } } +namespace A { declare namespace B { namespace C {} } } +namespace A { export declare namespace B { namespace C {} } } +namespace A { export declare namespace B { declare namespace C {} } } +namespace A { export declare namespace B { export declare namespace C {} } } +namespace A { declare namespace B { export declare namespace C {} } } +namespace A { export namespace B { export declare namespace C {} } } +export namespace A { namespace B { declare namespace C {} } } +export namespace A { namespace B { export declare namespace C {} } } +export namespace A { declare namespace B { namespace C {} } } +export namespace A { export declare namespace B { namespace C {} } } +export namespace A { export declare namespace B { declare namespace C {} } } +export namespace A { export declare namespace B { export declare namespace C {} } } +export namespace A { declare namespace B { export declare namespace C {} } } +export namespace A { export namespace B { export declare namespace C {} } } +``` + +## Compliant Code Examples +```typescript +declare global {} +declare module 'foo' {} +declare module foo {} +declare namespace foo {} +declare global { namespace foo {} } +declare module foo { namespace bar {} } +declare global { namespace foo { namespace bar {} } } +declare namespace foo { namespace bar { namespace baz {} } } +export declare namespace foo { export namespace bar { namespace baz {} } } +namespace foo {} +module foo {} +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md b/content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md new file mode 100644 index 0000000000000..a55d8adccaa00 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md @@ -0,0 +1,53 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-non-null-optional-chain + language: TypeScript + severity: Warning +title: Avoid non-null assertions after an optional chain +--- +## Metadata +**ID:** `typescript-best-practices/no-non-null-optional-chain` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Using a non-null assertion after an optional chain expression indicates bad type safety. + +## Non-Compliant Code Examples +```typescript +foo?.bar!; +foo?.['bar']!; +foo?.bar()!; +foo.bar?.()!; +(foo?.bar)!.baz; +(foo?.bar)!().baz; +(foo?.bar)!; +(foo?.bar)!(); +(foo?.bar!); +(foo?.bar!)(); +``` + +## Compliant Code Examples +```typescript +foo.bar!; +foo.bar!.baz; +foo.bar!.baz(); +foo.bar()!; +foo.bar()!(); +foo.bar()!.baz; +foo?.bar; +foo?.bar(); +(foo?.bar).baz!; +(foo?.bar()).baz!; +foo?.bar!.baz; +foo?.bar!(); +foo?.['bar']!.baz; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-proto.md b/content/en/static_analysis/rules/typescript-best-practices/no-proto.md new file mode 100644 index 0000000000000..557185e061623 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-proto.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-proto + language: TypeScript + severity: Warning +title: Avoid the use of the __proto__ property +--- +## Metadata +**ID:** `typescript-best-practices/no-proto` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +The `__proto__` property has been deprecated as of ECMAScript 3.1. + +Use a suitable alternative to `__proto__` like `Object.getPrototypeOf` and `Object.setPrototypeOf` instead. + +## Non-Compliant Code Examples +```typescript +var a = test.__proto__; +var a = test['__proto__']; +var a = test[`__proto__`]; +test[`__proto__`] = function () {}; +``` + +## Compliant Code Examples +```typescript +var a = test[__proto__]; +var __proto__ = null; +foo[`__proto`] = null; +foo[`__proto__\n`] = null; +class C { #__proto__; foo() { this.#__proto__; } } +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-script-url.md b/content/en/static_analysis/rules/typescript-best-practices/no-script-url.md new file mode 100644 index 0000000000000..87e97ee1f0365 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-script-url.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-script-url + language: TypeScript + severity: Notice +title: Avoid using Javascript in URLs +--- +## Metadata +**ID:** `typescript-best-practices/no-script-url` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +JavaScript URLs are evaluated the same way `eval` is executed. This can lead to arbitrary code execution. + +## Non-Compliant Code Examples +```typescript +var a = 'javascript:void(0);'; +var a = 'javascript:'; +var a = `javascript:`; +var a = `JavaScript:`; +``` + +## Compliant Code Examples +```typescript +var a = 'Hello World!'; +var a = 10; +var url = 'xjavascript:' +var url = `xjavascript:` +var url = `${foo}javascript:` +var a = foo`javaScript:`; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md b/content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md new file mode 100644 index 0000000000000..95ec2d5306e6e --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md @@ -0,0 +1,74 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-unnecessary-type-constraint + language: TypeScript + severity: Notice +title: Avoid unnecessary constraints on generic types +--- +## Metadata +**ID:** `typescript-best-practices/no-unnecessary-type-constraint` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +It is redundant to `extend` from `any` or `unknown`. + +## Non-Compliant Code Examples +```typescript +function data() {} +function data() {} +function data() {} +function data() {} +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +function data() {} +const data = () => {}; +const data = () => {}; +class Data {} +const Data = class {}; + +class Data { + member() {} +} + +const Data = class { + member() {} +}; + +interface Data {} +type Data = {}; +``` + +## Compliant Code Examples +```typescript +function data() {} +function data() {} +function data() {} +function data() {} +function data() {} +function data() {} + +type TODO = any; +function data() {} + +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +const data = () => {}; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md new file mode 100644 index 0000000000000..06b497d47c7b8 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md @@ -0,0 +1,74 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-unsafe-assignment + language: TypeScript + severity: Warning +title: Avoid assigning a value with type any +--- +## Metadata +**ID:** `typescript-best-practices/no-unsafe-assignment` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +The `any` type in TypeScript is dangerously broad, leading to unexpected behavior. Using `any` should be avoided. + +## Non-Compliant Code Examples +```typescript +const x = 1 as any; +const x = 1 as any, +function foo(a = 1 as any) {} +class Foo { constructor(private a = 1 as any) {} } +class Foo { private a = 1 as any; } +const [x] = 1 as any; +const [x] = [] as any[]; + +// TS treats the assignment pattern weirdly in this case +[[[[x]]]] = [1 as any]; +const x = [...(1 as any)]; +const x = [...([] as any[])]; + +const x = { y: 1 as any }; +const x = { y: { z: 1 as any } }; +const x = { ...(1 as any) }; +; +``` + +## Compliant Code Examples +```typescript +const x = 1; +const x: number = 1; +const x = 1, y = 1; +let x; +let x = 1, y; +function foo(a = 1) {} +class Foo { constructor(private a = 1) {} } +class Foo { private a = 1; } +const x: Set = new Set(); +const x: Set = new Set(); +const [x] = [1]; +const [x, y] = [1, 2] as number[]; +const [x, ...y] = [1, 2, 3, 4, 5]; +const [x, ...y] = [1]; +const [{ ...x }] = [{ x: 1 }] as [{ x: any }]; +function foo(x = 1) {} +function foo([x] = [1]) {} +function foo([x, ...y] = [1, 2, 3, 4, 5]) {} +function foo([x, ...y] = [1]) {} +// this is not checked, because there's no annotation to compare it with +const x = new Set(); +const x = { y: 1 }; +const x = { y = 1 }; +const x = { y(){} }; +const x: { y: number } = { y: 1 }; +const x = [...[1, 2, 3]]; +const [{ [`x${1}`]: x }] = [{ [`x`]: 1 }] as [{ [`x`]: any }]; +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md new file mode 100644 index 0000000000000..723cdbf33a83f --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-best-practices/no-unsafe-declaration-merging + language: TypeScript + severity: Error +title: Avoid unsafe declaration merging +--- +## Metadata +**ID:** `typescript-best-practices/no-unsafe-declaration-merging` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Error Prone + +## Description +Do not merge class and interface declarations. The compiler won't check property initialization, which might lead to runtime errors. + +## Non-Compliant Code Examples +```typescript +interface Foo {} +class Foo {} +``` + +## Compliant Code Examples +```typescript +interface Foo {} +class Bar implements Foo {} + +namespace Baz {} +namespace Baz {} +enum Baz {} + +namespace Qux {} +function Qux() {} +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md new file mode 100644 index 0000000000000..bf26ed59237f5 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-unsafe-negation + language: TypeScript + severity: Warning +title: Avoid negating the left operand of relational operators +--- +## Metadata +**ID:** `typescript-best-practices/no-unsafe-negation` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Negation of the left-hand side of an expression is often unintended. + +## Non-Compliant Code Examples +```typescript +!a in b +(!a in b) +!(a) in b +!a instanceof b +(!a instanceof b) +!(a) instanceof b +``` + +## Compliant Code Examples +```typescript +a in b +a in b === false +!(a in b); +(!a) in b +a instanceof b +a instanceof b === false; +!(a instanceof b); +(!a) instanceof b; + +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md b/content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md new file mode 100644 index 0000000000000..3dbd083914b25 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/no-var-requires + language: TypeScript + severity: Warning +title: Avoid require statements +--- +## Metadata +**ID:** `typescript-best-practices/no-var-requires` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Use ESM instead of CommonJS imports. + +## Non-Compliant Code Examples +```typescript +var foo = require('foo'); +const foo = require('foo'); +let foo = require('foo'); +let foo = trick(require('foo')); +var foo = require?.('foo'); +const foo = require?.('foo'); +let foo = require?.('foo'); +let foo = trick(require?.('foo')); +let foo = trick?.(require('foo')); +const foo = require('./foo.json') as Foo; +const foo: Foo = require('./foo.json').default; + +// const foo = require('./foo.json'); + +// https://github.com/typescript-eslint/typescript-eslint/issues/3883 +// const configValidator = new Validator(require('./a.json')); +// configValidator.addSchema(require('./a.json')); +``` + +## Compliant Code Examples +```typescript +import foo = require('foo'); +require('foo'); +require?.('foo'); + +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/require-yield.md b/content/en/static_analysis/rules/typescript-best-practices/require-yield.md new file mode 100644 index 0000000000000..7a4f26d12bcb6 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/require-yield.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/require-yield + language: TypeScript + severity: Error +title: Require yield in generator functions +--- +## Metadata +**ID:** `typescript-best-practices/require-yield` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Best Practices + +## Description +Generator functions must yield at some point. Otherwise, use a normal function. + +## Non-Compliant Code Examples +```typescript +function* foo() { return 0; } +(function* foo() { return 0; })(); +var obj = { *foo() { return 0; } } +class A { *foo() { return 0; } } +function* foo() { function* bar() { yield 0; } } +function* foo() { function* bar() { return 0; } yield 0; } +``` + +## Compliant Code Examples +```typescript +function foo() { return 0; } +function* foo() { yield 0; } +function* foo() { } +(function* foo() { yield 0; })(); +(function* foo() { })(); +var obj = { *foo() { yield 0; } }; +var obj = { *foo() { } }; +class A { *foo() { yield 0; } }; +class A { *foo() { } } +``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md b/content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md new file mode 100644 index 0000000000000..b48da0f6336c6 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-best-practices/triple-slash-reference + language: TypeScript + severity: Notice +title: Avoid triple slash in favor of ES6 import declarations +--- +## Metadata +**ID:** `typescript-best-practices/triple-slash-reference` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Use ESM instead of references. + +## Non-Compliant Code Examples +```typescript +/// +/// +/// +``` + +## Compliant Code Examples +```typescript +import * as foo from 'foo'; +import * as bar from 'bar'; +import * as baz from 'baz'; +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md b/content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md new file mode 100644 index 0000000000000..f83ce4271fd99 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/event-check-origin + language: TypeScript + severity: Warning +title: Check origin of events +--- +## Metadata +**ID:** `typescript-browser-security/event-check-origin` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Not checking the rule origin can lead to XSS attacks. Always check the event origin. + +#### Learn More + + - [XSS and CSS Cheat Sheet from OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) + +## Non-Compliant Code Examples +```typescript +window.addEventListener('message', (event: Event) => { + processing(); +}) +``` + +## Compliant Code Examples +```typescript +window.addEventListener('message', (event: Event) => { + if (event.origin != 'https://app.domain.tld') { + throw new Error('invalid origin') + } + + processing(); +}) +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md b/content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md new file mode 100644 index 0000000000000..1c16b8eb4ae3d --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md @@ -0,0 +1,81 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/inner-outer-html + language: TypeScript + severity: Warning +title: Do not modify innerHTML or outerHTML +--- +## Metadata +**ID:** `typescript-browser-security/inner-outer-html` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Properties like `innerHTML` and `outerHTML` should not be modified directly unless such modifications are clearly reviewed. Modifying `innerHTML` or `outerHTML` using user inputs that has not been validated can lead to XSS injection. + +#### Learn More + + - [Why InnerHTML Is a Bad Idea and How to Avoid It?](https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/) + - [CWE-79 - Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) + + +## Non-Compliant Code Examples +```typescript +function nonCompliant(argument) { + const content = '
' + argument + '
'; + document.write(content); +} +``` + +```typescript +function nonCompliant(myArgument) { + document.body.outerHTML = myArgument; +} +``` + +```typescript +if (typeof(SERVER_DOMAIN) === 'undefined') { + window.location.replace("/unconfigured.html"); +} + +const RECEIVE_URL = SERVER_DOMAIN + "/challenge_scoreboard.html" + "?origin=" + get_domain(); + +var window_ref = null; + +document.getElementById("username").focus(); + +function store_username() { + var username; + var username_obj; + + username_obj = document.getElementById("username"); + username = username_obj.value + + var welcome; + welcome = document.getElementById("welcome"); + welcome.innerHTML = "Welcome " + html_encode (username); + + var set_username; + set_username = document.getElementById("set_username"); + set_username.style.display="none"; + + var game; + game = document.getElementById("game"); + game.style.display="inline"; + + start_game(); + // have to do time out so the window can open + setTimeout (function () {send_username(username);}, 1000); + + return false; +} + +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md b/content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md new file mode 100644 index 0000000000000..01f534915eb50 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/insecure-websocket + language: TypeScript + severity: Warning +title: Websockets must use SSL connections +--- +## Metadata +**ID:** `typescript-browser-security/insecure-websocket` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always use secure websocket communication. When using websocket, use addresses that are SSL-enabled. + + + +## Non-Compliant Code Examples +```typescript +const client = new WebSocket('ws://app.domain.tld') +``` + +## Compliant Code Examples +```typescript +const client = new WebSocket('wss://app.domain.tld') +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md b/content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md new file mode 100644 index 0000000000000..4215b600a5a1c --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/local-storage-sensitive-data + language: TypeScript + severity: Warning +title: Do not store sensitive data to local storage +--- +## Metadata +**ID:** `typescript-browser-security/local-storage-sensitive-data` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not store sensitive data in `localStorage` and keep the data safe from any malicious software that could read this data. + +#### Learn More + - [CWE-312 - Cleartext Storage of Sensitive Information](https://cwe.mitre.org/data/definitions/312.html) + +## Non-Compliant Code Examples +```typescript +localStorage.setItem('user', email) + +localStorage.setItem('user', user.email) +``` + +## Compliant Code Examples +```typescript +localStorage.setItem('user', uuid) + +localStorage.setItem('user', user.id) +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md b/content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md new file mode 100644 index 0000000000000..37578e2cbe5fb --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/manual-sanitization + language: TypeScript + severity: Warning +title: Avoid manual sanitization of inputs +--- +## Metadata +**ID:** `typescript-browser-security/manual-sanitization` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Never sanitize HTML input manually. This can lead to vulnerabilities. Use dedicated modules such as `sanitize-html` to sanitize user inputs. + +## Non-Compliant Code Examples +```typescript +const sanitizedInput = input + .replaceAll('<', '<') + .replaceAll('>', '>'); +const html = `${sanitizedInput}`; + +const sanitizedInput2 = input + .replaceAll('bla', '<') + .replaceAll('foo', '>'); + +const sanitizedInput3 = input + .replaceAll('<', '<') + .replaceAll('>', 'gt;'); +``` + +## Compliant Code Examples +```typescript +import sanitizeHtml from 'sanitize-html'; + +const html = sanitizeHtml(`${input}`); +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md b/content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md new file mode 100644 index 0000000000000..33c8cadf86a08 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/postmessage-permissive-origin + language: TypeScript + severity: Warning +title: Specify origin in postMessage +--- +## Metadata +**ID:** `typescript-browser-security/postmessage-permissive-origin` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always specify the origin of the message for security reasons and to avoid spoofing attacks. Always specify an exact target origin, not `*`, when you use `postMessage` to send data to other windows. + +#### Learn More + + - [window.postMessage documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) + +## Non-Compliant Code Examples +```typescript +window.postMessage(message, '*') + +``` + +## Compliant Code Examples +```typescript +window.postMessage(message, 'https://app.domain.tld') + +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md b/content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md new file mode 100644 index 0000000000000..1a8b13ef75f22 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/react-dangerously-inner-html + language: TypeScript + severity: Warning +title: Do not inject unsanitized HTML +--- +## Metadata +**ID:** `typescript-browser-security/react-dangerously-inner-html` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always sanitize HTML data before injecting it in the DOM. Use libraries such as [DOMPurify](https://github.com/cure53/DOMPurify) before using it. + +## Non-Compliant Code Examples +```typescript +const App = () => { + const data = `lorem ipsum`; + + return ( +
+
+ ); +} +``` + +## Compliant Code Examples +```typescript +const App = () => { + const data = `lorem ipsum`; + + return ( +
+ ); +} +``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md b/content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md new file mode 100644 index 0000000000000..e7fe811dea61a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-browser-security/regexp-non-literal + language: TypeScript + severity: Warning +title: Do not use variable for regular expressions +--- +## Metadata +**ID:** `typescript-browser-security/regexp-non-literal` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Regular expressions should not use a variable as an argument since an attacker may inject values and cause a regular expression denial of service (ReDoS). Instead, use a library like [recheck](https://www.npmjs.com/package/recheck) to check that no DoS can be triggered by regular expression. + +## Non-Compliant Code Examples +```typescript +const foo = new RegExp(req.something); +const bar = new RegExp(variable); +``` + +## Compliant Code Examples +```typescript +const foo = new RegExp(`^\\d+-${topicId}$`); +const foo = new RegExp(/something/); +const foo = new RegExp("weofiwje"); +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/array-type.md b/content/en/static_analysis/rules/typescript-code-style/array-type.md new file mode 100644 index 0000000000000..7d01ecfdc5553 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/array-type.md @@ -0,0 +1,129 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/array-type + language: TypeScript + severity: Notice +title: Require consistently using either T[] or Array for arrays +--- +## Metadata +**ID:** `typescript-code-style/array-type` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Chose between: `T[]` and `Array`. These types are equivalent and it should be consistent across the code base. + +## Non-Compliant Code Examples +```typescript +// Base cases from https://github.com/typescript-eslint/typescript-eslint/issues/2323#issuecomment-663977655 +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: ReadonlyArray = []; +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: ReadonlyArray = []; +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: Array = []; +let a: Array = []; +let a: Array = []; +let a: Array = []; +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: ReadonlyArray = []; +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: ReadonlyArray = []; +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: Array = []; +let a: Array = []; +let a: ReadonlyArray = []; +let a: ReadonlyArray = []; + +// End of base cases +type Arr = Array; +let a: Array<{ foo: Array }> = []; +let a: Array<{ foo: Foo | Array }> = []; +let ya = [[1, '2']] as Array<[number, string]>; +// Ignore user-defined aliases +let yyyy: Arr>>> = [[[['2']]]]; +interface ArrayClass { + foo: T[]; + bar: T[]; + baz: Arr; + xyz: this[]; +} +function barFunction(bar: Array>) { + return bar.map(e => e.bar); +} +let barVar: Array<(c: number) => number> = []; +type barUnion = Array; +type barIntersection = Array; +let w: Array> = [['baz']]; +type Unwrap = T extends Array ? E : T; +``` + +## Compliant Code Examples +```typescript +// Base cases from https://github.com/typescript-eslint/typescript-eslint/issues/2323#issuecomment-663977655 +let a: number[] = []; +let a: (string | number)[] = []; +let a: readonly number[] = []; +let a: readonly (string | number)[] = []; +let a: number[] = []; +let a: (string | number)[] = []; +let a: readonly number[] = []; +let a: readonly (string | number)[] = []; +let a: number[] = []; +let a: (string | number)[] = []; +let a: readonly number[] = []; +let a: number[] = []; +let a: (string | number)[] = []; +let a: number[] = []; +let a: readonly number[] = []; +let a: number[] = []; +let a: readonly number[] = []; +let a: readonly (string | number)[] = []; +let a: number[] = []; +let a: readonly number[] = []; +let a: readonly number[] = []; +let a: readonly (string | number)[] = []; +let a: readonly bigint[] = []; + +// End of base cases +let a = new Array(); +let a: { foo: Bar[] }[] = []; +let yy: number[][] = [[4, 5], [6]]; +function bazFunction(baz: Arr>) { return baz.map(e => e.baz); } +namespace fooName { type BarType = { bar: string }; type BazType = Arr; } +interface FooInterface { '.bar': { baz: string[] }; } +let yy: number[][] = [[4, 5], [6]]; +let ya = [[1, '2']] as [number, string][]; +function barFunction(bar: ArrayClass[]) { return bar.map(e => e.bar); } +function bazFunction(baz: Arr>) { return baz.map(e => e.baz); } +let barVar: ((c: number) => number)[]; +type barUnion = (string | number | boolean)[]; +type barIntersection = (string & number)[]; +interface FooInterface { '.bar': { baz: string[] }; } +type Unwrap = T extends (infer E)[] ? E : T; +function bazFunction(baz: Arr>) { return baz.map(e => e.baz); } + +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/assignment-name.md b/content/en/static_analysis/rules/typescript-code-style/assignment-name.md new file mode 100644 index 0000000000000..ccaa1a75125b4 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/assignment-name.md @@ -0,0 +1,94 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/assignment-name + language: TypeScript + severity: Notice +title: Assigment name should use camelCase +--- +## Metadata +**ID:** `typescript-code-style/assignment-name` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that variables and properties names use `camelCase` and not `snake_case` or `PascalCase`. + +## Non-Compliant Code Examples +```typescript +var a = { + MyProp: "should be camelCase", + #Priv: 2, +}; +const my_var = {}; +let FooBar = {}; +const { a_b, ...Bla } = c; +const [a_b, ...Bla] = c; + +``` + +## Compliant Code Examples +```typescript +/* The BenefitsDAO must be constructed with a connected database object */ +function BenefitsDAO(db) { + + "use strict"; + + /* If this constructor is called without the "new" operator, "this" points + * to the global object. Log a warning and call it correctly. */ + if (false === (this instanceof BenefitsDAO)) { + console.log("Warning: BenefitsDAO constructor called without 'new' operator"); + return new BenefitsDAO(db); + } + + const usersCol = db.collection("users"); + const UsersCol = db.collection("users"); + const {foo_bar} = bla; + this.getAllNonAdminUsers = callback => { + usersCol.find({ + "isAdmin": { + $ne: true + } + }).toArray((err, users) => callback(null, users)); + }; + + this.updateBenefits = (userId, startDate, callback) => { + usersCol.update({ + _id: parseInt(userId) + }, { + $set: { + benefitStartDate: startDate + } + }, + (err, result) => { + if (!err) { + console.log("Updated benefits"); + return callback(null, result); + } + + return callback(err, null); + } + ); + }; +} + +module.exports = { BenefitsDAO }; +``` + +```typescript +const a = { myProp: "", #priv: 1 }; +const myVar = {}; +const { a } = c; +const { a, ...b } = c; +const [a, ...b] = c; +process.env.PCKG_OS_NAME; +const md5 = 'foo'; +const PCKG_OS_NAME = 'foo'; +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md b/content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md new file mode 100644 index 0000000000000..b8796dbdcceac --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md @@ -0,0 +1,39 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/ban-ts-comment + language: TypeScript + severity: Notice +title: Avoid @ts- comments +--- +## Metadata +**ID:** `typescript-code-style/ban-ts-comment` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Correct your types instead of disabling TypeScript. + +## Non-Compliant Code Examples +```typescript +// @ts-expect-error +// @ts-ignore +// @ts-nocheck +// @ts-check +``` + +## Compliant Code Examples +```typescript +// just a comment containing @ts-expect-error somewhere +// just a comment containing @ts-ignore somewhere +// just a comment containing @ts-nocheck somewhere +// just a comment containing @ts-check somewhere + +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md b/content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md new file mode 100644 index 0000000000000..fa6aa7c643754 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-code-style/ban-tslint-comment + language: TypeScript + severity: Warning +title: Avoid using TSLint comments +--- +## Metadata +**ID:** `typescript-code-style/ban-tslint-comment` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Do not disable TypeScript checks. + +## Non-Compliant Code Examples +```typescript +/* tslint:disable */ +/* tslint:enable */ +/* tslint:disable:rule1 rule2 rule3... */ +/* tslint:enable:rule1 rule2 rule3... */ +// tslint:disable-next-line +someCode(); // tslint:disable-line +// tslint:disable-next-line:rule1 rule2 rule3... +``` + +## Compliant Code Examples +```typescript +// This is a comment that just happens to mention tslint +/* This is a multiline comment that just happens to mention tslint */ +someCode(); // This is a comment that just happens to mention tslint +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/class-name.md b/content/en/static_analysis/rules/typescript-code-style/class-name.md new file mode 100644 index 0000000000000..630cca82b39f0 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/class-name.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/class-name + language: TypeScript + severity: Warning +title: Class name should be PascalCase +--- +## Metadata +**ID:** `typescript-code-style/class-name` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Code Style + +## Description +Class names should be `PascalCase` and not `camelCase` or `snake_case`. + +## Non-Compliant Code Examples +```typescript +class _runtimeMetricsStatus {} +class runtimeMetricsStatus {} +``` + +## Compliant Code Examples +```typescript +class MyClass {} +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/eqeqeq.md b/content/en/static_analysis/rules/typescript-code-style/eqeqeq.md new file mode 100644 index 0000000000000..f926e70804e57 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/eqeqeq.md @@ -0,0 +1,85 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/eqeqeq + language: TypeScript + severity: Notice +title: Enforce the use of === and !== +--- +## Metadata +**ID:** `typescript-code-style/eqeqeq` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +In JavaScript, `==` and `!=` comparisons do type coercion, which can be confusing and may introduce potential errors. Use the type-safe equality operators `===` and `!==` instead. + +## Non-Compliant Code Examples +```typescript +a == b +a != b +typeof a == 'number' +typeof a == 'number' +'string' != typeof a +true == true +2 == 3 +2 == 3 +'hello' != 'world' +'hello' != 'world' +a == null +a == null +null != a +true == 1 +0 != '1' +'wee' == /wee/ +typeof a == 'number' +'string' != typeof a +'hello' != 'world' +2 == 3 +true == true +true == null +true != null +null == null +null != null +a +== +b +(a) == b +(a) != b +a == (b) +a != (b) +(a) == (b) +(a == b) == (c) +(a != b) != (c) +a == b; +a!=b; +(a + b) == c; +(a + b) != c; +((1) ) == (2); + +``` + +## Compliant Code Examples +```typescript +a === b +a !== b +a === b +a !== null +a === null +a !== null +null === null +null !== null + +// https://github.com/eslint/eslint/issues/8020 +foo === /abc/u + +// bigint +foo === 1n +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/func-name-matching.md b/content/en/static_analysis/rules/typescript-code-style/func-name-matching.md new file mode 100644 index 0000000000000..ddd4947767bc7 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/func-name-matching.md @@ -0,0 +1,195 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/func-name-matching + language: TypeScript + severity: Notice +title: Function names must match the name of the assignation +--- +## Metadata +**ID:** `typescript-code-style/func-name-matching` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Use the same name between your function declaration and the variable or property to which it is assigned. + +## Non-Compliant Code Examples +```typescript +let foo = function bar() {}; +let foo = function bar() {}; +foo = function bar() {}; +foo &&= function bar() {}; +obj.foo ||= function bar() {}; +obj['foo'] ??= function bar() {}; +obj.foo = function bar() {}; +obj.bar.foo = function bar() {}; +obj['foo'] = function bar() {}; +let obj = {foo: function bar() {}}; +let obj = {'foo': function bar() {}}; +({['foo']: function bar() {}}); +// NOT SUPPORTED +// module.exports = function foo(name) {}; +// module.exports = function foo(name) {}; +// module.exports = function exports(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function exports(name) {}; +// Object.defineProperty(foo, 'bar', { value: function baz() {} }); +// Object.defineProperties(foo, { bar: { value: function baz() {} } }); +// Object.create(proto, { bar: { value: function baz() {} } }); +// var obj = { value: function foo(name) {} }; +// Object.defineProperty(foo, 'bar', { value: function bar() {} }); +// Object.defineProperties(foo, { bar: { value: function bar() {} } }); +// Object.create(proto, { bar: { value: function bar() {} } }); +// Reflect.defineProperty(foo, 'bar', { value: function baz() {} }); +// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }); +foo({ value: function bar() {} }); +(obj?.aaa).foo = function bar() {}; +// Object?.defineProperty(foo, 'bar', { value: function baz() {} }); +// (Object?.defineProperty)(foo, 'bar', { value: function baz() {} }); +// Object?.defineProperty(foo, 'bar', { value: function bar() {} }); +// (Object?.defineProperty)(foo, 'bar', { value: function bar() {} }); +// Object?.defineProperties(foo, { bar: { value: function baz() {} } }); +// (Object?.defineProperties)(foo, { bar: { value: function baz() {} } }); +// Object?.defineProperties(foo, { bar: { value: function bar() {} } }); +// (Object?.defineProperties)(foo, { bar: { value: function bar() {} } }); +class C { x = function y() {}; } +class C { 'x' = function y() {}; } +class C { ['x'] = function y() {}; } +class C { static x = function y() {}; } +(class { x = function y() {}; }) +var obj = { '\u1885': function foo() {} }; + +``` + +## Compliant Code Examples +```typescript +var foo; +var foo = function foo() {}; +var foo = function foo() {}; +var foo = function() {} +var foo = () => {} +foo = function foo() {}; +foo = function foo() {}; +foo &&= function foo() {}; +obj.foo ||= function foo() {}; +obj['foo'] ??= function foo() {}; +obj.foo = function foo() {}; +obj.foo = function foo() {}; +obj.foo = function() {}; +obj.foo = function() {}; +obj.bar.foo = function foo() {}; +obj.bar.foo = function foo() {}; +obj['foo'] = function foo() {}; +obj['foo'] = function foo() {}; +// This are not equal not sure why eslint skips them +// obj['foo//bar'] = function foo() {}; +// obj['foo//bar'] = function foo() {}; +// obj['foo//bar'] = function foo() {}; +obj[foo] = function bar() {}; +obj[foo] = function bar() {}; +var obj = {foo: function foo() {}}; +var obj = {foo: function foo() {}}; +var obj = {'foo': function foo() {}}; +var obj = {'foo': function foo() {}}; +var obj = {foo: function() {}}; +var obj = {foo: function() {}}; +var obj = {foo: function() {}}; +var obj = {[foo]: function bar() {}} +var obj = {['x' + 2]: function bar() {}}; +obj['x' + 2] = function bar(){}; +var [ bar ] = [ function bar(){} ]; +function a(foo = function bar() {}) {} +// NOT SUPPORTED +// module.exports = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module.exports = function foo(name) {}; +// module.exports = function foo(name) {}; +// module.exports = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function foo(name) {}; +// module['exports'] = function foo(name) {}; +({['foo']: function foo() {}}) +({['foo']: function foo() {}}) +({[foo]: function bar() {}}) +({[null]: function foo() {}}) +({[1]: function foo() {}}) +({[true]: function foo() {}}) +({[`x`]: function foo() {}}) +({[/abc/]: function foo() {}}) +({[[1, 2, 3]]: function foo() {}}) +({[{x: 1}]: function foo() {}}) +[] = function foo() {} +({} = function foo() {}) +[a] = function foo() {} +({a} = function foo() {}) +var [] = function foo() {} +var {} = function foo() {} +var [a] = function foo() {} +var {a} = function foo() {} +({ value: function value() {} }) +obj.foo = function foo() {}; +obj.bar.foo = function foo() {}; +var obj = {foo: function foo() {}}; +var obj = {foo: function() {}}; +var obj = { value: function value() {} } +// NOT SUPPORTED +// Object.defineProperty(foo, 'bar', { value: function bar() {} }) +// Object.defineProperties(foo, { bar: { value: function bar() {} } }) +// Object.create(proto, { bar: { value: function bar() {} } }) +// Object.defineProperty(foo, 'b' + 'ar', { value: function bar() {} }) +// Object.defineProperties(foo, { ['bar']: { value: function bar() {} } }) +// Object.create(proto, { ['bar']: { value: function bar() {} } }) +// Object.defineProperty(foo, 'bar', { value() {} }) +// Object.defineProperties(foo, { bar: { value() {} } }) +// Object.create(proto, { bar: { value() {} } }) +// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }) +// Reflect.defineProperty(foo, 'b' + 'ar', { value: function baz() {} }) +// Reflect.defineProperty(foo, 'bar', { value() {} }) +foo({ value: function value() {} }) +class C { x = function () {}; } +class C { x = function () {}; } +class C { 'x' = function () {}; } +class C { #x = function () {}; } +class C { #x = function () {}; } +class C { [x] = function () {}; } +class C { [x] = function () {}; } +class C { ['x'] = function () {}; } +class C { x = function x() {}; } +class C { 'x' = function x() {}; } +class C { #x = function x() {}; } +class C { #x = function x() {}; } +class C { #x = function y() {}; } +class C { #x = function y() {}; } +class C { [x] = function x() {}; } +class C { [x] = function x() {}; } +class C { [x] = function y() {}; } +class C { [x] = function y() {}; } +class C { ['x'] = function x() {}; } +class C { 1 = function x0() {}; } +class C { 1 = function x1() {}; } +class C { [1] = function x0() {}; } +class C { [1] = function x1() {}; } +class C { [f()] = function g() {}; } +class C { [f()] = function f() {}; } +class C { static x = function x() {}; } +class C { x = (function y() {})(); } +class C { x = (function x() {})(); } +(class { x = function x() {}; }) +class C { #x; foo() { this.#x = function x() {}; } } +class C { #x; foo() { this.#x = function x() {}; } } +class C { #x; foo() { this.#x = function y() {}; } } +class C { #x; foo() { this.#x = function y() {}; } } +class C { #x; foo() { a.b.#x = function x() {}; } } +class C { #x; foo() { a.b.#x = function x() {}; } } +class C { #x; foo() { a.b.#x = function y() {}; } } +class C { #x; foo() { a.b.#x = function y() {}; } } +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/func-names.md b/content/en/static_analysis/rules/typescript-code-style/func-names.md new file mode 100644 index 0000000000000..0bd5b0759b5fc --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/func-names.md @@ -0,0 +1,96 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/func-names + language: TypeScript + severity: Notice +title: Enforce named function expressions +--- +## Metadata +**ID:** `typescript-code-style/func-names` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +It is easier to debug your application code when you avoid anonymous functions so that the stack trace can show you meaningful error messages. This rule enforces all your function to be consistently declared with a name. + +## Non-Compliant Code Examples +```typescript +Foo.prototype.bar = function() {}; +(function(){}()) +f(function(){}) +var a = new Date(function() {}); +var test = function(d, e, f) {}; +new function() {} +Foo.prototype.bar = function() {}; +(function(){}()) +f(function(){}) +var a = new Date(function() {}); +new function() {} +var {foo} = function(){}; +({ a: obj.prop = function(){} } = foo); +[obj.prop = function(){}] = foo; +var { a: [b] = function(){} } = foo; +function foo({ a } = function(){}) {}; +export default function() {} +export default function() {} +export default (function(){}); +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +(function*() {}()) +var foo = bar(function *() {}); +(function*() {}()) +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +var foo = bar(function *() {}); +var foo = function*() {}; +(function*() {}()) +class C { foo = function() {} } +class C { [foo] = function() {} } +class C { #foo = function() {} } +``` + +## Compliant Code Examples +```typescript +Foo.prototype.bar = function bar(){}; +Foo.prototype.bar = () => {}; +function foo(){} +function test(d, e, f) {} +new function bar(){} +exports = { get foo() { return 1; }, set bar(val) { return val; } }; +({ foo() { return 1; } }); +class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} +function foo() {} +var a = function foo() {}; +class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} +({ foo() {} }); +function foo() {} +var a = function foo() { foo(); }; +class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} +({ foo() {} }); +export default function foo() {} +export default function foo() {} +export default function foo() {} +var foo = bar(function *baz() {}); +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/function-naming.md b/content/en/static_analysis/rules/typescript-code-style/function-naming.md new file mode 100644 index 0000000000000..be79541677604 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/function-naming.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/function-naming + language: TypeScript + severity: Notice +title: Function name should use camelCase or PascalCase +--- +## Metadata +**ID:** `typescript-code-style/function-naming` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that the function uses `camelCase` or `PascalCase` in case it is an `Object`. Generator functions should always be `camelCase`. + +## Non-Compliant Code Examples +```typescript +function My_Class() {} +function get_value() {} +function* GetValue() {} +function *get_value() {} +``` + +## Compliant Code Examples +```typescript +function MyClass() {} +function getValue() {} +function* getValue() {} +function *getValue() {} +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/max-class-lines.md b/content/en/static_analysis/rules/typescript-code-style/max-class-lines.md new file mode 100644 index 0000000000000..93dca19089094 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/max-class-lines.md @@ -0,0 +1,258 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/max-class-lines + language: TypeScript + severity: Warning +title: Classes must be less than 100 lines +--- +## Metadata +**ID:** `typescript-code-style/max-class-lines` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Code Style + +## Description +A class must stay short (less than 100 lines) to be easy to understand. If your class or function is more than 100 lines, you should refactor your code and ensure that your class is less than 100 lines. + +## Non-Compliant Code Examples +```typescript +class DummyClass { + constructor() { + this.name = "John"; + this.age = 30; + this.email = "john@example.com"; + this.address = "123 Main St"; + this.phone = "555-1234"; + this.salary = 50000; + this.skills = ["JavaScript", "HTML", "CSS"]; + this.projects = [ + { name: "Project 1", duration: 6 }, + { name: "Project 2", duration: 4 }, + { name: "Project 3", duration: 8 } + ]; + this.status = "active"; + + // Initialize more properties... + // ... + // ... + } + + sayHello() { + console.log(`Hello, my name is ${this.name}.`); + } + + calculateSalary() { + let total = this.salary; + for (let project of this.projects) { + total += project.duration * 1000; + } + return total; + } + + updateEmail(newEmail) { + if (newEmail.includes("@")) { + this.email = newEmail; + console.log("Email updated successfully."); + } else { + console.log("Invalid email format."); + } + } + + addSkill(skill) { + this.skills.push(skill); + console.log("Skill added."); + } + + removeSkill(skill) { + const index = this.skills.indexOf(skill); + if (index !== -1) { + this.skills.splice(index, 1); + console.log("Skill removed."); + } else { + console.log("Skill not found."); + } + } + + promote() { + if (this.status === "active") { + this.salary *= 1.1; + console.log("Promoted successfully."); + } else { + console.log("Cannot promote an inactive employee."); + } + } + + resign() { + if (this.status === "active") { + this.status = "inactive"; + console.log("Resigned successfully."); + } else { + console.log("Already inactive."); + } + } + + // More methods... + // ... + // ... + + // Long method 1 + longMethod1() { + // Implementation goes here... + // ... + // ... + } + + // Long method 2 + longMethod2() { + // Implementation goes here... + // ... + // ... + } + + // Long method 3 + longMethod3() { + // Implementation goes here... + // ... + // ... + } + + // Long method 4 + longMethod4() { + // Implementation goes here... + // ... + // ... + } + + // Long method 5 + longMethod5() { + // Implementation goes here... + // ... + // ... + } + + // More long methods... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final method + finalMethod() { + // Implementation goes here... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + } +} + +``` + +## Compliant Code Examples +```typescript +class DummyClass { + constructor() { + this.name = "John"; + this.age = 30; + this.email = "john@example.com"; + this.address = "123 Main St"; + this.phone = "555-1234"; + this.salary = 50000; + this.skills = ["JavaScript", "HTML", "CSS"]; + this.projects = [ + { name: "Project 1", duration: 6 }, + { name: "Project 2", duration: 4 }, + { name: "Project 3", duration: 8 } + ]; + this.status = "active"; + } + + sayHello() { + console.log(`Hello, my name is ${this.name}.`); + } + + calculateSalary() { + let total = this.salary; + for (let project of this.projects) { + total += project.duration * 1000; + } + return total; + } +} + +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/max-function-lines.md b/content/en/static_analysis/rules/typescript-code-style/max-function-lines.md new file mode 100644 index 0000000000000..e0da01747fdaa --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/max-function-lines.md @@ -0,0 +1,952 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/max-function-lines + language: TypeScript + severity: Warning +title: Functions must be less than 200 lines +--- +## Metadata +**ID:** `typescript-code-style/max-function-lines` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Code Style + +## Description +This rule ensures that a function is not too long. A function should be less than 200 lines, or it will be hard to understand. + +## Non-Compliant Code Examples +```typescript +function dummyFunction() { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; +} + +() => { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; +} + +const dummyFunction = function() { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; +} + +class A { + dummyFunction() { + var x = 0; + var y = 1; + var z = 2; + var arr = [1, 2, 3, 4, 5]; + var obj = { name: "John", age: 30 }; + + // Start of dummy code + for (var i = 0; i < 10; i++) { + x += i; + y *= i; + z -= i; + + if (x > y && y < z) { + x--; + z++; + } else { + y++; + } + } + + if (x > 100) { + arr.push(6); + } else if (x < 0) { + arr.pop(); + } else { + arr.splice(2, 1, 7); + } + + for (var j = 0; j < arr.length; j++) { + if (arr[j] % 2 === 0) { + arr[j] *= 2; + } else { + arr[j] += 2; + } + } + + var sum = 0; + arr.forEach(function(num) { + sum += num; + }); + + if (sum > 20) { + obj.name = "Jane"; + obj.age = 25; + } else { + obj.name = "Alice"; + obj.age = 40; + } + + // End of dummy code + + // More dummy code... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + // ... + + // Final dummy code + var result = "Result: "; + if (obj.age < 30) { + result += "Young "; + } else if (obj.age > 30) { + result += "Old "; + } else { + result += "Middle-aged "; + } + + result += obj.name; + + return result; + } +} +``` + +## Compliant Code Examples +```typescript +function myTest() { + // less than 200 lines +} + +() => { + // less than 200 lines +} + +class A { + foo() { + // less than 200 lines + } +} +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/max-params.md b/content/en/static_analysis/rules/typescript-code-style/max-params.md new file mode 100644 index 0000000000000..08877f119d92b --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/max-params.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/max-params + language: TypeScript + severity: Notice +title: Enforce a maximum number of parameters in a function +--- +## Metadata +**ID:** `typescript-code-style/max-params` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Having too many parameters can make your code hard to read. The parameters must be used in appropriate order. Forgetting the order of parameters can cause mistakes. + +Too many parameters is a code smell. You should refactor your code in smaller reusable bits. While it may be valid to require more than four parameters, you should use object destructuring. + +## Non-Compliant Code Examples +```typescript +function test(a, b, c, d) {} +var test = function(a, b, c, d, e) {}; +var test = (a, b, c, d) => {}; +(function(a, b, c, d) {}); + +// object property options +function test(a, b, c, d) {} +``` + +## Compliant Code Examples +```typescript +function test(d, e, f) {} +var test = function(a, b, c) {}; +var test = (a, b, c) => {}; +var test = function test(a, b, c) {}; + +// object property options +var test = function(a, b, c) {}; +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/method-name.md b/content/en/static_analysis/rules/typescript-code-style/method-name.md new file mode 100644 index 0000000000000..985954959526a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/method-name.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/method-name + language: TypeScript + severity: Notice +title: Method name should use camelCase +--- +## Metadata +**ID:** `typescript-code-style/method-name` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that method names use `camelCase` and not `snake_case` or `PascalCase`. + +## Non-Compliant Code Examples +```typescript +const a = { GetValue() {} } +class A { set_value() {} } +class A { *set_value() {} } +class A { #set_value() {} } +class A { #SetValue() {} } +``` + +## Compliant Code Examples +```typescript +const a = { getValue() {} } +class A { setValue() {} } +class A { #fooBla() {} } +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md b/content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md new file mode 100644 index 0000000000000..c128bee9731bf --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-code-style/no-array-constructor + language: TypeScript + severity: Warning +title: Avoid Array constructors +--- +## Metadata +**ID:** `typescript-code-style/no-array-constructor` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Array literal notation cannot be redefined. It is preferred over the Array constructor. + +The Array constructor is a common source of errors as it might behave unexpectedly when used with a single parameter. It creates an array with of N length instead of initializing an Array with the provided param. + + +## Non-Compliant Code Examples +```typescript +new Array(); +new Array; +new Array(x, y); +new Array(0, 1, 2); +``` + +## Compliant Code Examples +```typescript +new Array(x) +Array(x) +new Array(9) +Array(9) +new foo.Array() +foo.Array() +new Array.foo +Array.foo() +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md b/content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md new file mode 100644 index 0000000000000..fa6d62dcb12b2 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-code-style/no-confusing-non-null-assertion + language: TypeScript + severity: Warning +title: Avoid non-null assertion in confusing locations +--- +## Metadata +**ID:** `typescript-code-style/no-confusing-non-null-assertion` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Using a non-null assertion (`!`) next to an assign or equals check (`=` or `==` or `===`) could be confusing. + +## Non-Compliant Code Examples +```typescript +a! == b; +a! === b; +a + b! == c; +(obj = new new OuterObj().InnerObj).Name! == c; +(a==b)! ==c; +a! = b; +(obj = new new OuterObj().InnerObj).Name! = c; +(a=b)! =c; +``` + +## Compliant Code Examples +```typescript +a == b!; +a = b!; +a !== b; +a != b; +(a + b!) == c; +(a + b!) = c; +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-div-regex.md b/content/en/static_analysis/rules/typescript-code-style/no-div-regex.md new file mode 100644 index 0000000000000..297110e33364e --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-div-regex.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-code-style/no-div-regex + language: TypeScript + severity: Notice +title: Avoid equal signs explicitly at the beginning of regex +--- +## Metadata +**ID:** `typescript-code-style/no-div-regex` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Error Prone + +## Description +At the start of a regular expression literal, the characters `/=` can be mistaken for a division assignment operator. + +## Non-Compliant Code Examples +```typescript +var f = function() { return /=foo/; }; +``` + +## Compliant Code Examples +```typescript +var f = function() { return /foo/ig.test('bar'); }; +var f = function() { return /\\=foo/; }; +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md b/content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md new file mode 100644 index 0000000000000..601c6fe06e934 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-duplicate-imports + language: TypeScript + severity: Warning +title: Avoid duplicate module imports +--- +## Metadata +**ID:** `typescript-code-style/no-duplicate-imports` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +Single imports are easier to read and maintain you can see everything being imported from a module in one line. + +## Non-Compliant Code Examples +```typescript +import { merge } from 'module'; +import something from 'another-module'; +import { find } from 'module'; + +import something from 'something'; +import { find } from 'something'; +``` + +## Compliant Code Examples +```typescript +import { merge, find } from 'module'; +import something from 'another-module'; + +// not mergeable +import { merge } from 'something'; +import * as something from 'something'; +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md b/content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md new file mode 100644 index 0000000000000..fa13985556388 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-empty-interface + language: TypeScript + severity: Notice +title: Avoid the declaration of empty interfaces +--- +## Metadata +**ID:** `typescript-code-style/no-empty-interface` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not use empty interfaces. + +## Non-Compliant Code Examples +```typescript +interface Foo {} +interface Foo extends {} +interface Bar extends Foo {} +interface Foo extends Array {} +interface Foo extends Array {} +interface Foo extends Array {} +interface Foo extends R {} +interface Foo extends Bar {} +declare module FooBar { type Baz = typeof baz; export interface Bar extends Baz {} } +interface Foo { + +} +``` + +## Compliant Code Examples +```typescript +interface Foo { name: string; } +interface Foo { name: string; } +interface Bar { age: number; } + +// valid because extending multiple interfaces can be used instead of a union type +interface Baz extends Foo, Bar {} +interface Foo { name: string; } +interface Foo { props: string; } +class Bar {} +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md b/content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md new file mode 100644 index 0000000000000..2ed67f5d1c293 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md @@ -0,0 +1,41 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/no-floating-decimal + language: TypeScript + severity: Notice +title: Avoid leading or trailing decimal points in numbers +--- +## Metadata +**ID:** `typescript-code-style/no-floating-decimal` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +To prevent confusion between the dot operator and the decimal point, always use a leading number when writing floating point numbers. + +## Non-Compliant Code Examples +```typescript +var x = .5; +var x = -.5; +var x = 2.; +var x = -2.; +typeof.2 +for(foo of.2); +``` + +## Compliant Code Examples +```typescript +var x = 2.5; +var x = "2.5"; +var t = { + ecmaVersion: 2018, +} +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md b/content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md new file mode 100644 index 0000000000000..d616fbb3ad86c --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md @@ -0,0 +1,111 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-inferrable-types + language: TypeScript + severity: Notice +title: Avoid explicit type declarations for variables and params +--- +## Metadata +**ID:** `typescript-code-style/no-inferrable-types` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When you set an initial primitive value to a TypeScript parameter, property, or variable their respective type can be inferred. Explicitly adding type annotations in some cases can make your code more verbose and prevent TypeScript from inferring a more specific literal type. + +## Non-Compliant Code Examples +```typescript +const a: bigint = 10n; +const a: bigint = -10n; +const a: bigint = BigInt(10); +const a: bigint = -BigInt(10); +const a: bigint = BigInt?.(10); +const a: bigint = -BigInt?.(10); +const a: boolean = false; +const a: boolean = true; +const a: boolean = Boolean(null); +const a: boolean = Boolean?.(null); +const a: boolean = !0; +const a: number = 10; +const a: number = +10; +const a: number = -10; +const a: number = Number("1"); +const a: number = +Number("1"); +const a: number = -Number("1"); +const a: number = Number?.("1"); +const a: number = +Number?.("1"); +const a: number = -Number?.("1"); +const a: number = Infinity; +const a: number = +Infinity; +const a: number = -Infinity; +const a: number = NaN; +const a: number = +NaN; +const a: number = -NaN; +const a: null = null; +const a: RegExp = /a/; +const a: RegExp = RegExp("a"); +const a: RegExp = RegExp?.("a"); +const a: RegExp = new RegExp("a"); +const a: string = "str"; +const a: string = 'str'; +const a: string = `str`; +const a: string = String(1); +const a: string = String?.(1); +const a: symbol = Symbol("a"); +const a: symbol = Symbol?.("a"); +const a: undefined = undefined; +const a: undefined = void someValue; + +``` + +## Compliant Code Examples +```typescript +const a = 10n; +const a = -10n; +const a = BigInt(10); +const a = -BigInt(10); +const a = BigInt?.(10); +const a = -BigInt?.(10); +const a = false; +const a = true; +const a = Boolean(null); +const a = Boolean?.(null); +const a = !0; +const a = 10; +const a = +10; +const a = -10; +const a = Number("1"); +const a = +Number("1"); +const a = -Number("1"); +const a = Number?.("1"); +const a = +Number?.("1"); +const a = -Number?.("1"); +const a = Infinity; +const a = +Infinity; +const a = -Infinity; +const a = NaN; +const a = +NaN; +const a = -NaN; +const a = null; +const a = /a/; +const a = RegExp("a"); +const a = RegExp?.("a"); +const a = new RegExp("a"); +const a = "str"; +const a = 'str'; +const a = `str`; +const a = String(1); +const a = String?.(1); +const a = Symbol("a"); +const a = Symbol?.("a"); +const a = undefined; +const a = void someValue; +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md b/content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md new file mode 100644 index 0000000000000..c3005f45bc662 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md @@ -0,0 +1,122 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-lonely-if + language: TypeScript + severity: Notice +title: Avoid if statements as the only statement in else blocks +--- +## Metadata +**ID:** `typescript-code-style/no-lonely-if` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Prefer else if statement instead of an lonely if statement, it is considered cleaner code. + +## Non-Compliant Code Examples +```typescript +if (a) {;} else { if (b) {;} } + +if (a) { + foo(); +} else { + if (b) { + bar(); + } +} + +if (a) { + foo(); +} else /* comment */ { + if (b) { + bar(); + } +} + + +if (a) { + foo(); +} else { + /* otherwise, do the other thing */ if (b) { + bar(); + } +} + +if (a) { + foo(); +} else { + if /* this comment is ok */ (b) { + bar(); + } +} + +if (a) { + foo(); +} else { + if (b) { + bar(); + } /* this comment will prevent this test case from being autofixed. */ +} +if (foo) {} else { if (bar) baz(); } + +// Not fixed; removing the braces would cause a SyntaxError. +if (foo) {} else { if (bar) baz() } qux(); + +// This is fixed because there is a semicolon after baz(). +if (foo) {} else { if (bar) baz(); } qux(); + +// Not fixed; removing the braces would change the semantics due to ASI. +if (foo) { +} else { + if (bar) baz() +} +[1, 2, 3].forEach(foo); + +// Not fixed; removing the braces would change the semantics due to ASI. +if (foo) { +} else { + if (bar) baz++ +} +foo; + +// This is fixed because there is a semicolon after baz++ +if (foo) { +} else { + if (bar) baz++; +} +foo; + +// Not fixed; bar() would be interpreted as a template literal tag +if (a) { + foo(); +} else { + if (b) bar() +} +`template literal`; + +if (a) { + foo(); +} else { + if (b) { + bar(); + } else if (c) { + baz(); + } else { + qux(); + } +} +``` + +## Compliant Code Examples +```typescript +if (a) {;} else if (b) {;} +if (a) {;} else { if (b) {;} ; } +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md b/content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md new file mode 100644 index 0000000000000..ae4ea76772076 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md @@ -0,0 +1,72 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-multi-assign + language: TypeScript + severity: Notice +title: Avoid the use of chained assignment expressions +--- +## Metadata +**ID:** `typescript-code-style/no-multi-assign` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Assigning multiple variables at once can be hard to understand. Make one expression per assignment instead. + +## Non-Compliant Code Examples +```typescript +var a = b = c; +var a = b = c = d; +let foo = bar = cee = 100; +a=b=c=d=e; +a=b=c; +a +=b +=c; +var a = (b) = (((c))); +var a = ((b)) = (c); +var a = b = ( (c * 12) + 2); +var a = +((b)) + = (c); +a = b = '=' + c + 'foo'; +a = b = 7 * 12 + 5; +const x = {}; +const y = x.one = 1; +let a, b;a = b = 1; +let x, y;x = y = 'baz'; +const a = b = 1; +class C { field = foo = 0 } +class C { field = foo = 0 } +``` + +## Compliant Code Examples +```typescript +var a, b, c, +d = 0; +var a = 1; var b = 2; var c = 3; +var d = 0; +var a = 1 + (b === 10 ? 5 : 4); +const a = 1, b = 2, c = 3; +const a = 1; +const b = 2; +const c = 3; +for(var a = 0, b = 0;;){} +for(let a = 0, b = 0;;){} +for(const a = 0, b = 0;;){} +export let a, b; +export let a, + b = 0; +// ignore non declaration option not supported +// const x = {};const y = {};x.one = y.one = 1; +// let a, b;a = b = 1 +class C { [foo = 0] = 0 } +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-new-func.md b/content/en/static_analysis/rules/typescript-code-style/no-new-func.md new file mode 100644 index 0000000000000..056ca6a37f560 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-new-func.md @@ -0,0 +1,54 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-new-func + language: TypeScript + severity: Warning +title: Avoid new operators with the Function object +--- +## Metadata +**ID:** `typescript-code-style/no-new-func` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Best Practices + +## Description +The Function constructor can lead to code similar to `eval` executions. Use function declarations instead of the Function constructor. + +## Non-Compliant Code Examples +```typescript +var a = new Function("b", "c", "return b+c"); +var a = Function("b", "c", "return b+c"); +var a = Function.call(null, "b", "c", "return b+c"); +var a = Function.apply(null, ["b", "c", "return b+c"]); +var a = Function.bind(null, "b", "c", "return b+c")(); +var a = Function.bind(null, "b", "c", "return b+c"); +var a = Function["call"](null, "b", "c", "return b+c"); +var a = (Function?.call)(null, "b", "c", "return b+c"); +const fn = () => { class Function {} }; new Function('', ''); +var fn = function () { function Function() {} }; Function('', ''); +``` + +## Compliant Code Examples +```typescript +var a = new _function("b", "c", "return b+c"); +var a = _function("b", "c", "return b+c"); +// Scoped re assign not supported +// class Function {}; new Function() +// const fn = () => { class Function {}; new Function() } +// function Function() {}; Function() +// var fn = function () { function Function() {}; Function() } +// var x = function Function() { Function(); } +call(Function) +new Class(Function) +foo[Function]() +foo(Function.bind) +Function.toString() +Function[call]() +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-new-object.md b/content/en/static_analysis/rules/typescript-code-style/no-new-object.md new file mode 100644 index 0000000000000..e01ae38876eaf --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-new-object.md @@ -0,0 +1,60 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-new-object + language: TypeScript + severity: Notice +title: Avoid Object constructors +--- +## Metadata +**ID:** `typescript-code-style/no-new-object` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +For consistency, always use the shorter object literal notation `{}`. + +## Non-Compliant Code Examples +```typescript +var foo = new Object() +new Object(); +const a = new Object() +``` + +## Compliant Code Examples +```typescript +// Scoped re declare not supported +var myObject = {}; +var myObject = new CustomObject(); +var foo = new foo.Object() +// var Object = function Object() {}; +// new Object(); +var x = something ? MyClass : Object; +var y = new x(); + +// class Object { +// constructor(){ + +// } +// } +// new Object(); + +// import { Object } from './' +// new Object(); + +const init = (canvas, context, t) => + drawDoughnutChart( + canvas, + t('Chats'), + context, + labels.map((l) => t(l)), + Object.values(initialData), + ); +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-new.md b/content/en/static_analysis/rules/typescript-code-style/no-new.md new file mode 100644 index 0000000000000..ee1bb5953d24b --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-new.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-new + language: TypeScript + severity: Notice +title: Avoid new operators outside of assignments or comparisons +--- +## Metadata +**ID:** `typescript-code-style/no-new` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +A lonely instance is almost always useless. Do not create objects without assigning them to a variable that you will use later. + +## Non-Compliant Code Examples +```typescript +new Date() +``` + +## Compliant Code Examples +```typescript +var a = new Date() +var a; if (a === new Date()) { a = false; } +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-return-assign.md b/content/en/static_analysis/rules/typescript-code-style/no-return-assign.md new file mode 100644 index 0000000000000..72e9b42aa5af8 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-return-assign.md @@ -0,0 +1,84 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-code-style/no-return-assign + language: TypeScript + severity: Notice +title: Avoid assignment operators in return statements +--- +## Metadata +**ID:** `typescript-code-style/no-return-assign` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Error Prone + +## Description +JavaScript allows return statements to do assignment operations. Because it is hard to differentiate between an assignment and a comparison when written as part of the return statement, avoid using return statements. + +## Non-Compliant Code Examples +```typescript +function x() { return result = a * b; }; +function x() { return (result) = (a * b); }; +function x() { return result = a * b; }; +function x() { return (result) = (a * b); }; +() => { return result = a * b; }; +() => result = a * b; +function x() { return result = a * b; }; +// Allow parens option not supported +// function x() { return (result = a * b); }; +// function x() { return result || (result = a * b); }; +function foo(){ + return a = b +} +function doSomething() { + return foo = bar && foo > 0; +} +function doSomething() { + return foo = function(){ + return (bar = bar1) + } +} +function doSomething() { + return foo = () => a +} +function doSomething() { + return () => a = () => b +} +function foo(a){ + return function bar(b){ + return a = b + } +} +const foo = (a) => (b) => a = b; + +``` + +## Compliant Code Examples +```typescript +module.exports = {'a': 1}; +var result = a * b; +function x() { var result = a * b; return result; } +function x() { return (result = a * b); } +function x() { var result = a * b; return result; } +function x() { return (result = a * b); } +function x() { var result = a * b; return result; } +function x() { return function y() { result = a * b }; } +() => { return (result = a * b); } +() => (result = a * b) +const foo = (a,b,c) => ((a = b), c) +function foo(){ + return (a = b) +} +function bar(){ + return function foo(){ + return (a = b) && c + } +} +const foo = (a) => (b) => (a = b) +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-self-compare.md b/content/en/static_analysis/rules/typescript-code-style/no-self-compare.md new file mode 100644 index 0000000000000..ad871eff4e6d3 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-self-compare.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-code-style/no-self-compare + language: TypeScript + severity: Warning +title: Avoid comparisons where both sides are exactly the same +--- +## Metadata +**ID:** `typescript-code-style/no-self-compare` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +Comparing a variable to itself is most likely a mistake. + +## Non-Compliant Code Examples +```typescript +if (x === x) { } +if (x !== x) { } +if (x > x) { } +if ('x' > 'x') { } +do {} while (x === x) +x === x +x !== x +x == x +x != x +x > x +x < x +x >= x +x <= x +foo.bar().baz.qux >= foo.bar().baz.qux +class C { #field; foo() { this.#field === this.#field; } } +``` + +## Compliant Code Examples +```typescript +if (x === y) { } +if (1 === 2) { } +y=x*x +foo.bar.baz === foo.bar.qux +class C { #field; foo() { this.#field === this['#field']; } } +class C { #field; foo() { this['#field'] === this.#field; } } +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md b/content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md new file mode 100644 index 0000000000000..f2ec1c8a7d6d9 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md @@ -0,0 +1,49 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-useless-empty-export + language: TypeScript + severity: Notice +title: Avoid empty exports that don't change anything +--- +## Metadata +**ID:** `typescript-code-style/no-useless-empty-export` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Do not use empty exports. + +## Non-Compliant Code Examples +```typescript +export const value = 'Hello, world!'; +export {}; + +import 'some-other-module'; +export {}; + +``` + +## Compliant Code Examples +```typescript +declare module '_'; +import {} from '_'; +import * as _ from '_'; +export = {}; +export = 3; +export const _ = {}; + +const _ = {}; +export default _; + +export * from '_'; +export = {}; + +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-var.md b/content/en/static_analysis/rules/typescript-code-style/no-var.md new file mode 100644 index 0000000000000..64480c358e5d8 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/no-var.md @@ -0,0 +1,62 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/no-var + language: TypeScript + severity: Notice +title: Require let or const instead of var +--- +## Metadata +**ID:** `typescript-code-style/no-var` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +Block scoped lexical declarations like `let` and `const` are preferred over `var`. Block scope is common in many other programming languages and helps programmers avoid mistakes. + +## Non-Compliant Code Examples +```typescript +var foo = bar; +var foo = bar, toast = most; +var foo = bar; let toast = most; +for (var a of b) { console.log(a); } +for (var a in b) { console.log(a); } +for (let a of b) { var c = 1; console.log(c); } +for (var i = 0; i < list.length; ++i) { foo(i) } +for (var i = 0; i < 10; ++i) {}; +for (var a of b) { arr.push(() => a); } +for (let a of b) { var c; console.log(c); c = 'hello'; } +var a = a; +var {a = a} = {}; +var {a = b, b} = {}; +let {a, b = a} = {}; +var a = b, b = 1; +let a = b; var b = 1; +function foo() { a } var a = 1; foo(); +if (foo) var bar = 1; +var foo = 1; +{ var foo = 1 } +if (true) { var foo = 1 } +var foo = 1; +declare var foo = 2; +function foo() { var let; } +function foo() { var { let } = {}; } +function foo() { a } +var a = 1; foo(); + +``` + +## Compliant Code Examples +```typescript +const JOE = 'schmoe'; +let moo = 'car'; +const JOE = 'schmoe'; +let moo = 'car'; +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/parameter-name.md b/content/en/static_analysis/rules/typescript-code-style/parameter-name.md new file mode 100644 index 0000000000000..38c969946b3a6 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/parameter-name.md @@ -0,0 +1,37 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-code-style/parameter-name + language: TypeScript + severity: Notice +title: Parameter name should use camelCase +--- +## Metadata +**ID:** `typescript-code-style/parameter-name` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that parameter names use `camelCase` and not `snake_case` or `PascalCase`. + +## Non-Compliant Code Examples +```typescript +const a = { setValue(NewValue, event_info?) {} } +class A { setValue(NewValue, event_info) {} } +function setValue(NewValue, event_info) {} +const a = function(NewValue, event_info) {} +``` + +## Compliant Code Examples +```typescript +const a = { getValue() {} } +class A { setValue(newValue) {} } +class B { setValue(md5, valid5String) {} } +``` diff --git a/content/en/static_analysis/rules/typescript-code-style/radix.md b/content/en/static_analysis/rules/typescript-code-style/radix.md new file mode 100644 index 0000000000000..4c5108e87a945 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-code-style/radix.md @@ -0,0 +1,84 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Best Practices + id: typescript-code-style/radix + language: TypeScript + severity: Notice +title: Consistent use of the radix argument using parseInt +--- +## Metadata +**ID:** `typescript-code-style/radix` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Best Practices + +## Description +When utilizing the `parseInt()` function, many often skip the second parameter (the radix), allowing the function to deduce the number type based on the initial argument. By default, `parseInt()` can recognize both decimal and hexadecimal numbers, the latter through the `0x` prefix. However, before ECMAScript 5, the function also mistakenly recognized octal numbers, leading to issues as many developers presumed a starting `0` would be disregarded. + +## Non-Compliant Code Examples +```typescript +parseInt(); +parseInt(); +parseInt("10"); +parseInt("10",); +parseInt((0, "10")); +parseInt((0, "10"),); +parseInt("10", null); +parseInt("10", undefined); +parseInt("10", true); +parseInt("10", "foo"); +parseInt("10", "123"); +parseInt("10", 1); +parseInt("10", 37); +parseInt("10", 10.5); +Number.parseInt(); +Number.parseInt(); +Number.parseInt("10"); +Number.parseInt("10", 1); +Number.parseInt("10", 37); +Number.parseInt("10", 10.5); +parseInt?.("10"); +Number.parseInt?.("10"); +Number?.parseInt("10"); +(Number?.parseInt)("10"); + +``` + +## Compliant Code Examples +```typescript +parseInt("10", 10); +parseInt("10", 2); +parseInt("10", 36); +parseInt("10", 0x10); +parseInt("10", 1.6e1); +parseInt("10", 10.0); +parseInt("10", foo); +Number.parseInt("10", foo); +parseInt("10", 10); +parseInt("10", 8); +parseInt("10", foo); +parseInt +Number.foo(); +Number[parseInt](); +class C { #parseInt; foo() { Number.#parseInt(); } } +class C { #parseInt; foo() { Number.#parseInt(foo); } } +class C { #parseInt; foo() { Number.#parseInt(foo, 'bar'); } } +class C { #parseInt; foo() { Number.#parseInt(foo, 10); } } + +// shadowed not supported +// Ignores if it's shadowed or disabled. +// var parseInt; parseInt(); +// var parseInt; parseInt(foo); +// var parseInt; parseInt(foo, 10); +// var Number; Number.parseInt(); +// var Number; Number.parseInt(foo); +// var Number; Number.parseInt(foo, 10); +// /* globals parseInt:off */ parseInt(foo); +// Number.parseInt(foo, 10); +``` diff --git a/content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md b/content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md new file mode 100644 index 0000000000000..4cdf8e3c24db8 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-common-security/axios-avoid-insecure-http + language: TypeScript + severity: Warning +title: Avoid insecure HTTP requests with Axios +--- +## Metadata +**ID:** `typescript-common-security/axios-avoid-insecure-http` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Avoid connecting to `http` services. Use `https` services for security reasons. + +## Non-Compliant Code Examples +```typescript +const dataFromBackend = axios.get('http://backend.my.app') + +``` + +## Compliant Code Examples +```typescript +const dataFromBackend = axios.get('https://backend.my.app') + +``` diff --git a/content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md b/content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md new file mode 100644 index 0000000000000..0f56b932ba7c2 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-common-security/unique-function-arguments + language: TypeScript + severity: Warning +title: Function argument names should be unique +--- +## Metadata +**ID:** `typescript-common-security/unique-function-arguments` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +A function's parameter names should all be unique. Otherwise, a latter parameter will overwrite the former parameter. This behavior can lead to unintended bugs and it difficult to debug in the future. + +## Non-Compliant Code Examples +```typescript +function addition(foo: number, bar: number, foo: number) { + console.log(foo + bar + foo); +} + +addition(1, 2, 3); // outputs 8 +``` + +## Compliant Code Examples +```typescript +function addition(foo: number, bar: number, baz: number) { + console.log(foo + bar + baz); +} + +addition(1, 2, 3); // outputs 6 +``` diff --git a/content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md b/content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md new file mode 100644 index 0000000000000..1397cae017c5d --- /dev/null +++ b/content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md @@ -0,0 +1,43 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-common-security/xml-no-external-entities + language: TypeScript + severity: Warning +title: Do not use external XML entities +--- +## Metadata +**ID:** `typescript-common-security/xml-no-external-entities` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Process external entities in XML files may lead to XXE attack. Do not load external entities unless they have been explicitly checked. + +## Non-Compliant Code Examples +```typescript +import libxmljs from 'libxmljs'; +import fs from 'fs'; + +const xml = fs.readFileSync('file.xml', 'utf8'); +libxmljs.parseXmlString(xml, { + noent: true, +}); +``` + +## Compliant Code Examples +```typescript +import libxmljs from 'libxmljs'; +import fs from 'fs'; + +const xml = fs.readFileSync('file.xml', 'utf8'); +libxmljs.parseXmlString(xml); + +``` diff --git a/content/en/static_analysis/rules/typescript-express/access-restriction.md b/content/en/static_analysis/rules/typescript-express/access-restriction.md new file mode 100644 index 0000000000000..d3b3b7150e5b6 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/access-restriction.md @@ -0,0 +1,46 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/access-restriction + language: TypeScript + severity: Warning +title: Limit exposure to sensitive directories and files +--- +## Metadata +**ID:** `typescript-express/access-restriction` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Exposing a directory listing could present an attacker an opportunity to access source code or other sensitive data through a file structure exploit. Restricting access to non-sensitive directories and files is strongly suggested. + +#### Learn More +- [Express Serve index middleware](https://expressjs.com/en/resources/middleware/serve-index.html) + + +## Non-Compliant Code Examples +```typescript +import express, { Express } from 'express'; +import serveIndex from "serve-index"; + +const app: Express = express(); + +app.use(serveIndex()) +``` + +## Compliant Code Examples +```typescript +import express, { Express } from 'express'; +import serveIndex from "serve-index"; + +const app: Express = express(); + +app.use(serveIndex("/public")) +``` diff --git a/content/en/static_analysis/rules/typescript-express/default-session-config.md b/content/en/static_analysis/rules/typescript-express/default-session-config.md new file mode 100644 index 0000000000000..6fc6e29b8221a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/default-session-config.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/default-session-config + language: TypeScript + severity: Warning +title: Enforce overriding default config +--- +## Metadata +**ID:** `typescript-express/default-session-config` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Avoid leaving your session cookies open to exploits or unauthorized access, by overriding default values. + +Setting the `name` value to something generic is better than using the default value. + +#### Learn More +- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) + +## Non-Compliant Code Examples +```typescript +import session from "express-session" + +app.use( + session({ + secret: "secret" + }) +) +``` + +## Compliant Code Examples +```typescript +import session from "express-session" + +app.use( + session({ + secret: "secret", + name: 'sessionId' + }) +) +``` diff --git a/content/en/static_analysis/rules/typescript-express/external-filename-upload.md b/content/en/static_analysis/rules/typescript-express/external-filename-upload.md new file mode 100644 index 0000000000000..b6ba024b7616d --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/external-filename-upload.md @@ -0,0 +1,53 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/external-filename-upload + language: TypeScript + severity: Warning +title: Avoid using unsanitized user input with sendFile +--- +## Metadata +**ID:** `typescript-express/external-filename-upload` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Using unsanitized user input in a `sendFile` method can allow attackers to access unintended resources. + +Set the `root` option directly in your `sendFile` options will make this rule not report a violation. + +#### Learn More +- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile) + +## Non-Compliant Code Examples +```typescript +app.post("/upload", (req: Request, res: Response) => { + res.sendFile(req.params.filename) + + res.sendFile(req.params.filename, { maxAge: 0 }) + + res.sendFile(req.params.filename, { maxAge: 0 }, (err) => console.log(err)) +}) +``` + +## Compliant Code Examples +```typescript +app.post("/upload", (req: Request, res: Response) => { + res.sendFile("foo") + + const options = { maxAge: 0, root: path.join(__dirname, "upload") } + + res.sendFile(req.params.filename, options) + res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }) + + res.sendFile(req.params.filename, options, (err) => console.log(err)) + res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }, (err) => console.log(err)) +}) +``` diff --git a/content/en/static_analysis/rules/typescript-express/external-resource.md b/content/en/static_analysis/rules/typescript-express/external-resource.md new file mode 100644 index 0000000000000..af9e85e82ce63 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/external-resource.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/external-resource + language: TypeScript + severity: Warning +title: Avoid rendering resource based on unsanitized user input +--- +## Metadata +**ID:** `typescript-express/external-resource` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Rendering resources based on unsanitized user input should be avoided. At a minimum, one should use a safelist to restrict the potential resources that are exposed. + +## Non-Compliant Code Examples +```typescript +app.get("/", (req: Request, res: Response) => { + res.render(req.body.path) + res.render(req.cookies.path) + res.render(req.headers.path) + res.render(req.params.path) + res.render(req.query.path) +}) +``` + +## Compliant Code Examples +```typescript +app.get("/", (req: Request, res: Response) => { + const path = req.body.path + if (["posts", "pages"].includes(path)) { + return res.render(`${path}/success`) + } + res.render("error-page") +}) +``` diff --git a/content/en/static_analysis/rules/typescript-express/hardcoded-secret.md b/content/en/static_analysis/rules/typescript-express/hardcoded-secret.md new file mode 100644 index 0000000000000..c41ad3df24eb7 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/hardcoded-secret.md @@ -0,0 +1,69 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/hardcoded-secret + language: TypeScript + severity: Warning +title: Avoid using a hard-coded secret +--- +## Metadata +**ID:** `typescript-express/hardcoded-secret` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not store secrets in plaintext where they are used. Instead use environment variables (`process.env.`) or better yet, use a key management service (KMS) linked below that includes encryption. + +#### Learn More +- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password) +- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs) +- [AWS Key Management Service](https://aws.amazon.com/kms/) + +## Non-Compliant Code Examples +```typescript +import session from "express-session" +import { expressjwt } from "express-jwt" + +app.use( + session({ + name: "session-name", + secret: "not-secret-secret", + secret: `${isProd ? "prod-secret" : "dev-secret"}`, + }) +) + +app.use( + expressjwt({ + name: "session-name", + secret: "not-secret-secret", + secret: `${isProd ? "prod-secret" : "dev-secret"}`, + }) +) +``` + +## Compliant Code Examples +```typescript +import session from "express-session" +import { expressjwt } from "express-jwt" + +app.use( + session({ + name: "session-name", + secret: process.env.SECRET + }) +) + +app.use( + expressjwt({ + name: "session-name", + secret: process.env.SECRET + }) +) +``` diff --git a/content/en/static_analysis/rules/typescript-express/https-protocol-missing.md b/content/en/static_analysis/rules/typescript-express/https-protocol-missing.md new file mode 100644 index 0000000000000..a7e00bae78b69 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/https-protocol-missing.md @@ -0,0 +1,48 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/https-protocol-missing + language: TypeScript + severity: Warning +title: Use `https` protocol over `http` +--- +## Metadata +**ID:** `typescript-express/https-protocol-missing` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-tls): + +> If your app deals with or transmits sensitive data, use [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS) to secure the connection and the data. This technology encrypts data before it is sent from the client to the server, thus preventing some common (and easy) hacks. + +This rule will detect the usage of non `https.createServer()` usage. + +## Non-Compliant Code Examples +```typescript +import https from 'https'; +import express, { Express } from 'express'; + +const app: Express = express(); + +var httpServer = http.createServer(app) +httpServer.listen(8080); +``` + +## Compliant Code Examples +```typescript +import https from 'https'; +import express, { Express } from 'express'; + +const app: Express = express(); + +var httpsServer = https.createServer(app) +httpsServer.listen(8080); +``` diff --git a/content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md b/content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md new file mode 100644 index 0000000000000..3570bb1f019d4 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md @@ -0,0 +1,51 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/insecure-allow-origin + language: TypeScript + severity: Warning +title: Avoid using an insecure Access-Control-Allow-Origin header +--- +## Metadata +**ID:** `typescript-express/insecure-allow-origin` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Setting an Access-Control-Allow-Origin header with an unverified user-defined input can lead to sharing sensitive data with an unintended user. + +If this is unavoidable, consider comparing the input against a safe-list. + +#### Learn More + +- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing) + + +## Non-Compliant Code Examples +```typescript +app.get('/', function (req: Request, res: Response) { + res.set('Access-Control-Allow-Origin', req.headers.foo) + res.set({ "foo": "bar", 'Access-Control-Allow-Origin': req.query.foo }) + res.header('Access-Control-Allow-Origin', req.params.foo) + res.setHeader('Access-Control-Allow-Origin', req.body.foo); + res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': req.cookies.foo }) +}); +``` + +## Compliant Code Examples +```typescript +app.get('/', function (req: Request, res: Response) { + res.set('Access-Control-Allow-Origin', "foo_url") + res.set({ "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) + res.header('Access-Control-Allow-Origin', "foo_url") + res.setHeader('Access-Control-Allow-Origin', "foo_url"); + res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) +}); +``` diff --git a/content/en/static_analysis/rules/typescript-express/insecure-cookie.md b/content/en/static_analysis/rules/typescript-express/insecure-cookie.md new file mode 100644 index 0000000000000..027d964464c43 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/insecure-cookie.md @@ -0,0 +1,61 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/insecure-cookie + language: TypeScript + severity: Warning +title: Avoid setting insecure cookie settings +--- +## Metadata +**ID:** `typescript-express/insecure-cookie` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +When using cookies in your application, one should ensure appropriate security options are set to lessen the risk of exploits and unauthorized users. + +This rule will detect when `secure` and `httpOnly` are set to `false` in a multitude of ways. + +#### Learn More +- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) + +## Non-Compliant Code Examples +```typescript +const cookie = { + secure: false, + httpOnly: false, +} + +const options = { + cookie: { + secure: false, + httpOnly: false, + } +} + +cookieSession({ secure: false }) +``` + +## Compliant Code Examples +```typescript +const cookie = { + secure: true, + httpOnly: true, +} + +const options = { + cookie: { + secure: true, + httpOnly: true, + } +} + +cookieSession({ secure: true }) +``` diff --git a/content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md b/content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md new file mode 100644 index 0000000000000..ff3ef9e0f8db0 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md @@ -0,0 +1,60 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/jwt-not-revoked + language: TypeScript + severity: Warning +title: Ensure an isRevoked method is used for tokens +--- +## Metadata +**ID:** `typescript-express/jwt-not-revoked` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Consider a method to revoke JWTs, especially when they contain sensitive information, to ensure they remain short-lived. + +#### Learn More +- [ExpressJWT revoking documentation](https://github.com/auth0/express-jwt#revoked-tokens) + +## Non-Compliant Code Examples +```typescript +import { expressjwt } from "express-jwt"; + +app.get( + "/protected", + expressjwt({ + secret: "shhhhhhared-secret", + algorithms: ["HS256"], + }), + function (req, res) { + if (!req.auth.admin) return res.sendStatus(401); + res.sendStatus(200); + } +); +``` + +## Compliant Code Examples +```typescript +import { expressjwt as jwt } from "express-jwt"; + +app.get( + "/protected", + jwt({ + secret: "shhhhhhared-secret", + algorithms: ["HS256"], + isRevoked: isRevokedCallback, + }), + function (req, res) { + if (!req.auth.admin) return res.sendStatus(401); + res.sendStatus(200); + } +); +``` diff --git a/content/en/static_analysis/rules/typescript-express/missing-helmet.md b/content/en/static_analysis/rules/typescript-express/missing-helmet.md new file mode 100644 index 0000000000000..f0fc5a12e1913 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/missing-helmet.md @@ -0,0 +1,53 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/missing-helmet + language: TypeScript + severity: Warning +title: Express application should use Helmet +--- +## Metadata +**ID:** `typescript-express/missing-helmet` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-helmet): + +> [Helmet](https://helmetjs.github.io/) can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately. + +This rule will check whether you've set `app.use(helmet())` within the file that you've called `express()` + +## Non-Compliant Code Examples +```typescript +import express, { Express, Request, Response } from 'express'; + +const app: Express = express(); + +// no `app.use(helmet())` helmet detected in the file + +app.get("/foo", (req: Request, res: Response) => res.send("foo")); + +app.listen(8000); +``` + +## Compliant Code Examples +```typescript +import express, { Express, Request, Response } from 'express'; +import helmet from "helmet"; + +const app: Express = express(); + +app.use(helmet()); // helmet detected + +app.get("/foo", (req: Request, res: Response) => res.send("foo")); + +app.listen(8000); +``` diff --git a/content/en/static_analysis/rules/typescript-express/path-traversal.md b/content/en/static_analysis/rules/typescript-express/path-traversal.md new file mode 100644 index 0000000000000..dd0e7a69cb57e --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/path-traversal.md @@ -0,0 +1,57 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/path-traversal + language: TypeScript + severity: Warning +title: Avoid allowing access to unintended directories or files +--- +## Metadata +**ID:** `typescript-express/path-traversal` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +By not sanitizing user input prior to using it in path resolution methods you open your application's access to unintended directories and files. + +> If you're using `replace` on a user input, this rule will assume you've done so correctly and will not report a violation + +#### Learn More +- [OWASP path traversal](https://owasp.org/www-community/attacks/Path_Traversal) + +## Non-Compliant Code Examples +```typescript +import path from "path"; + +app.get("/", (req: Request, res: Response) => { + path.join("/user/", req.params.path) + + const pathname = path.join("/public/", req.body.foo) + path.resolve(pathname) + + path.resolve(__dirname, req.body.foo) + path.resolve(__dirname, `${req.body.foo}`) +}) +``` + +## Compliant Code Examples +```typescript +import path from "path"; + +app.get("/", (req: Request, res: Response) => { + path.join("/user/", req.params.path.replace(/^(\.\.(\/|\\|$))+/, '')) + + const pathname = path.join("/public/", req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) + path.resolve(pathname) + + path.resolve(__dirname, req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) + path.resolve(__dirname, `${req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')}`) +}) +``` diff --git a/content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md b/content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md new file mode 100644 index 0000000000000..32e230e84d84a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md @@ -0,0 +1,66 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/reduce-server-fingerprinting + language: TypeScript + severity: Warning +title: Server fingerprinting misconfiguration +--- +## Metadata +**ID:** `typescript-express/reduce-server-fingerprinting` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Improve your overall server security by taking the step to reduce the likelihood of server fingerprinting the software being used on the server. + +By default, Express.js sends the `X-Powered-By` response header banner which can be disabled with `app.disable('X-Powered-By')`. + +If you're using `helmet`, you can use either of these methods too: +- `app.use(hidePoweredBy())` +- `app.use(helmet.hidePoweredBy())` + +#### Learn More +- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html) + +## Non-Compliant Code Examples +```typescript +const app: Express = express(); + +// express() is called but none of the following were detected afterwards +// app.disable('x-powered-by') +// app.use(hidePoweredBy()) +// app.use(helmet.hidePoweredBy()) +``` + +## Compliant Code Examples +```typescript +const app: Express = express(); + +app.use(helmet.hidePoweredBy()); + +// rest of your config +``` + +```typescript +const app: Express = express(); + +app.use(hidePoweredBy()) + +// rest of your config +``` + +```typescript +const app: Express = express(); + +app.disable('x-powered-by') + +// rest of your config +``` diff --git a/content/en/static_analysis/rules/typescript-express/xss-vulnerability.md b/content/en/static_analysis/rules/typescript-express/xss-vulnerability.md new file mode 100644 index 0000000000000..d2eeeade51167 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-express/xss-vulnerability.md @@ -0,0 +1,45 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-express/xss-vulnerability + language: TypeScript + severity: Warning +title: Avoid sending unsanitized user input in response +--- +## Metadata +**ID:** `typescript-express/xss-vulnerability` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Returning unsanitized user input in a `send` or `write` method can increase your application's risk of cross-site scripting attacks. + +#### Learn More +- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) + +## Non-Compliant Code Examples +```typescript +app.get("/", (req: Request, res: Response) => { + res.send(req.body.foo); + res.send({ title: "foo", message: req.body.foo }); + res.write(req.body.foo); + res.write({ title: "foo", message: req.body.foo }); +}) +``` + +## Compliant Code Examples +```typescript +app.get("/", (req: Request, res: Response) => { + res.send("foo"); + res.send({ title: "foo", message: 'foo' }); + res.write("foo"); + res.write({ title: "foo", message: 'foo' }); +}) +``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/comments.md b/content/en/static_analysis/rules/typescript-inclusive/comments.md new file mode 100644 index 0000000000000..2346a8bb24ead --- /dev/null +++ b/content/en/static_analysis/rules/typescript-inclusive/comments.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-inclusive/comments + language: TypeScript + severity: Notice +title: Check comments for wording issues +--- +## Metadata +**ID:** `typescript-inclusive/comments` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Check the variable names and suggest better names. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```typescript +/** + * whitelist names to prevent unauthorized usage + */ + +// she SHE should check her code + +// he should check his +``` + +## Compliant Code Examples +```typescript +// allowlist names to prevent unauthorized usage + +/* the comments do not have a history of issues */ +``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/declarations.md b/content/en/static_analysis/rules/typescript-inclusive/declarations.md new file mode 100644 index 0000000000000..a735ba5f7a303 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-inclusive/declarations.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-inclusive/declarations + language: TypeScript + severity: Notice +title: Check declaration names for wording issues +--- +## Metadata +**ID:** `typescript-inclusive/declarations` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that some words are not used in the codebase and suggest a replacement when appropriate. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```typescript +function foo_blacklist() {} +a(function *blackList() {}); +function *whItEList() {} +function blacklist_names() {} +function whiteList() {} +class WhiteList {} +const slave = 0; +let master = ""; +var slave = b; +``` + +## Compliant Code Examples +```typescript +function foo_denyList() {} +a(function *allowedList() {}); +class primary {} +const secondary = 0; +``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md b/content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md new file mode 100644 index 0000000000000..6bc99bd00f3f5 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-inclusive/formal-parameters + language: TypeScript + severity: Notice +title: Check parameter names for wording issues +--- +## Metadata +**ID:** `typescript-inclusive/formal-parameters` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that some words are not used in the codebase and suggest a replacement when appropriate. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```typescript +function a(master, slave) {} +function a(blacklist, whitelist?: boolean) {} +class A { foo(master: string, slave = 1) {} } + +``` + +## Compliant Code Examples +```typescript +function denyList(primary, secondary) {} +``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/identifiers.md b/content/en/static_analysis/rules/typescript-inclusive/identifiers.md new file mode 100644 index 0000000000000..311cc56bf5049 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-inclusive/identifiers.md @@ -0,0 +1,50 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Code Style + id: typescript-inclusive/identifiers + language: TypeScript + severity: Notice +title: Check identifier names for wording issues +--- +## Metadata +**ID:** `typescript-inclusive/identifiers` + +**Language:** TypeScript + +**Severity:** Notice + +**Category:** Code Style + +## Description +Ensure that some words are not used in the codebase and suggest a replacement when appropriate. + +Examples of replacement suggestions: + +- `blacklist` with `denylist` +- `whitelist` with `allowlist` +- `master` with `primary` +- `slave` with `secondary` + +## Non-Compliant Code Examples +```typescript +{ slave: false } +const a = { 'master': false, }; +const a = { ['master']: false, }; +const a = { c, ...blacklist } = b; +const { whitelist } = b; +const a = { whitelist }; +const { whitelist: slave } = b; +[slave, ...master] = blacklist; +``` + +## Compliant Code Examples +```typescript +{ secondary: false } +const a = { 'primary': false, }; +const a = { c, ...denylist } = b; +const { AllowedList } = b; +[primary, ...secondary] = b; +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/argon2.md b/content/en/static_analysis/rules/typescript-node-security/argon2.md new file mode 100644 index 0000000000000..76880feeeed1b --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/argon2.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/argon2 + language: TypeScript + severity: Error +title: Use strong security mechanisms with argon2 +--- +## Metadata +**ID:** `typescript-node-security/argon2` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Security + +## Description +Use secure and fast security mechanisms when using `argon2`. + +#### Learn More + + - [argon2 types](https://github.com/ranisalt/node-argon2/wiki/Options#type) + +## Non-Compliant Code Examples +```typescript +await argon2.hash('password', {type: argon2.argon2d}) +await argon2.hash('password', {type: argon2.argon2i}) +``` + +## Compliant Code Examples +```typescript +await argon2.hash('password', {type: argon2.argon2id}) +await argon2.hash('password', {}) +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md b/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md new file mode 100644 index 0000000000000..6d2d71d3d87c7 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/avoid-crypto-rc4 + language: TypeScript + severity: Warning +title: Avoid RC4 +--- +## Metadata +**ID:** `typescript-node-security/avoid-crypto-rc4` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of the RC4 security protocol exposes your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library, RC4](https://cryptojs.gitbook.io/docs/#ciphers) + +## Non-Compliant Code Examples +```typescript +const encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase"); +const decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase"); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md b/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md new file mode 100644 index 0000000000000..62410f011887a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md @@ -0,0 +1,32 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/avoid-crypto-sha1 + language: TypeScript + severity: Warning +title: Avoid SHA1 security protocol +--- +## Metadata +**ID:** `typescript-node-security/avoid-crypto-sha1` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of insecure encryption or hashing protocols expose your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hmac) + +## Non-Compliant Code Examples +```typescript +const hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase"); +const hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase", anotherargument); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/avoid-des.md b/content/en/static_analysis/rules/typescript-node-security/avoid-des.md new file mode 100644 index 0000000000000..e5f84ce4bc194 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/avoid-des.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/avoid-des + language: TypeScript + severity: Warning +title: Avoid DES and 3DES +--- +## Metadata +**ID:** `typescript-node-security/avoid-des` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of insecure encryption or hashing protocols expose your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library, DES and TripleDES](https://cryptojs.gitbook.io/docs/#ciphers) + +## Non-Compliant Code Examples +```typescript +const encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase"); +const decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase"); +const encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase"); +const decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase"); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md b/content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md new file mode 100644 index 0000000000000..ed8e633b8fcbd --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/chmod-permissions + language: TypeScript + severity: Warning +title: Do not give 777 permissions to a file +--- +## Metadata +**ID:** `typescript-node-security/chmod-permissions` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Always make sure you restrict the permissions of your application files. Applications should not allow write and execution for other users, as it may leak data and information. Always restrict the number of users and applications that can access your application data. + +## Non-Compliant Code Examples +```typescript +const fs = require('fs'); +const fsPromises = fs.promises; + +fs.chmodSync("/tmp/myfile", 0o777); +fsPromises.chmod("/tmp/fsPromises", 0o777); + +``` + +## Compliant Code Examples +```typescript +const fs = require('fs'); +const fsPromises = fs.promises; + +fs.chmodSync(myPath, 0o770); +fsPromises.chmod("/tmp/fsPromises", 0o770); + +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/command-injection.md b/content/en/static_analysis/rules/typescript-node-security/command-injection.md new file mode 100644 index 0000000000000..3a5b8b51cf554 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/command-injection.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/command-injection + language: TypeScript + severity: Warning +title: Avoid command injection +--- +## Metadata +**ID:** `typescript-node-security/command-injection` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +When executing a command, never use unchecked variables. Make sure that each variable of the command has been checked. + +## Non-Compliant Code Examples +```typescript +childprocess.exec(`mv ${src} ${dst}`, (error, stdout, stderr) => {}); +childprocess.exec('mv ' + src + " " + dst, (error, stdout, stderr) => {}); +``` + +## Compliant Code Examples +```typescript +childprocess.exec('mv /tmp/src /tmp/dst', (error, stdout, stderr) => {}); + +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md b/content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md new file mode 100644 index 0000000000000..42b26dd6f3fd7 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md @@ -0,0 +1,33 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/crypto-avoid-weak-hash + language: TypeScript + severity: Warning +title: Avoid weak hash algorithm from CryptoJS +--- +## Metadata +**ID:** `typescript-node-security/crypto-avoid-weak-hash` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Use of insecure hash functions like MD5 or SHA1 can expose your application to vulnerabilities. + +#### Learn More + + - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hashing) + +## Non-Compliant Code Examples +```typescript +const hash = CryptoJS.MD5("Message", "Secret Passphrase"); +const hash = CryptoJS.SHA1("Message", "Secret Passphrase"); +const hash = CryptoJS.HmacMD5("Message", "Secret Passphrase"); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md b/content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md new file mode 100644 index 0000000000000..630154ecfbf00 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md @@ -0,0 +1,115 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/detect-buffer-noassert + language: TypeScript + severity: Error +title: Avoid calls to 'buffer' with 'noAssert' flag set +--- +## Metadata +**ID:** `typescript-node-security/detect-buffer-noassert` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Security + +## Description +Avoid calls to [`buffer`](https://nodejs.org/api/buffer.html) with `noAssert`. If you skip the `offset` validation it can go beyond the end of the `Buffer`. + +## Non-Compliant Code Examples +```typescript +a.readUInt8(0, true) +a.readUInt16LE(0, true) +a.readUInt16BE(0, true) +a.readUInt32LE(0, true) +a.readUInt32BE(0, true) +a.readInt8(0, true) +a.readInt16LE(0, true) +a.readInt16BE(0, true) +a.readInt32LE(0, true) +a.readInt32BE(0, true) +a.readFloatLE(0, true) +a.readFloatBE(0, true) +a.readDoubleLE(0, true) +a.readDoubleBE(0, true) +a.writeUInt8(0, 0, true) +a.writeUInt16LE(0, 0, true) +a.writeUInt16BE(0, 0, true) +a.writeUInt32LE(0, 0, true) +a.writeUInt32BE(0, 0, true) +a.writeInt8(0, 0, true) +a.writeInt16LE(0, 0, true) +a.writeInt16BE(0, 0, true) +a.writeInt32LE(0, 0, true) +a.writeInt32BE(0, 0, true) +a.writeFloatLE(0, 0, true) +a.writeFloatBE(0, 0, true) +a.writeDoubleLE(0, 0, true) +a.writeDoubleBE(0, 0, true) + +``` + +## Compliant Code Examples +```typescript +a.readUInt8(0) +a.readUInt16LE(0) +a.readUInt16BE(0) +a.readUInt32LE(0) +a.readUInt32BE(0) +a.readInt8(0) +a.readInt16LE(0) +a.readInt16BE(0) +a.readInt32LE(0) +a.readInt32BE(0) +a.readFloatLE(0) +a.readFloatBE(0) +a.readDoubleLE(0) +a.readDoubleBE(0) +a.writeUInt8(0) +a.writeUInt16LE(0) +a.writeUInt16BE(0) +a.writeUInt32LE(0) +a.writeUInt32BE(0) +a.writeInt8(0) +a.writeInt16LE(0) +a.writeInt16BE(0) +a.writeInt32LE(0) +a.writeInt32BE(0) +a.writeFloatLE(0) +a.writeFloatBE(0) +a.writeDoubleLE(0) +a.writeDoubleBE(0) +a.readUInt8(0, false) +a.readUInt16LE(0, false) +a.readUInt16BE(0, false) +a.readUInt32LE(0, false) +a.readUInt32BE(0, false) +a.readInt8(0, false) +a.readInt16LE(0, false) +a.readInt16BE(0, false) +a.readInt32LE(0, false) +a.readInt32BE(0, false) +a.readFloatLE(0, false) +a.readFloatBE(0, false) +a.readDoubleLE(0, false) +a.readDoubleBE(0, false) +a.writeUInt8(0, false) +a.writeUInt16LE(0, false) +a.writeUInt16BE(0, false) +a.writeUInt32LE(0, false) +a.writeUInt32BE(0, false) +a.writeInt8(0, false) +a.writeInt16LE(0, false) +a.writeInt16BE(0, false) +a.writeInt32LE(0, false) +a.writeInt32BE(0, false) +a.writeFloatLE(0, false) +a.writeFloatBE(0, false) +a.writeDoubleLE(0, false) +a.writeDoubleBE(0, false) +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-child-process.md b/content/en/static_analysis/rules/typescript-node-security/detect-child-process.md new file mode 100644 index 0000000000000..15ffb3ed5771a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detect-child-process.md @@ -0,0 +1,119 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Error Prone + id: typescript-node-security/detect-child-process + language: TypeScript + severity: Warning +title: Avoid instances of 'child_process' and non-literal 'exec()' +--- +## Metadata +**ID:** `typescript-node-security/detect-child-process` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Error Prone + +## Description +In Node.js, the "child_process" module provides capabilities to execute shell commands directly. While this might seem beneficial, it comes with significant security risks. If the input to this module isn't properly sanitized, it can pave the way for command injection attacks. In such attacks, malicious actors could introduce harmful commands, which, when executed, could compromise system integrity or lead to data breaches. + +Additionally, using non-literal arguments with "exec()" presents another challenge. When arguments to "exec()" are dynamic or derived from untrusted sources, there's a risk that attackers could manipulate this input. This makes the system vulnerable to unauthorized actions, potentially causing significant damage. Therefore, for a more secure Node.js application, it's advised to tread cautiously with these features, employing rigorous input validation and considering safer alternatives. + +## Non-Compliant Code Examples +```typescript +require('child_process') +require('node:child_process') +var child = require('child_process'); child.exec(com) +var nodeChild = require('node:child_process'); nodeChild.exec(com) +import childImport from 'child_process'; childImport.exec(com) +import nodeChildImport from 'node:child_process'; nodeChildImport.exec(com) + +// not supported +// var child = sinon.stub(require('child_process')); child.exec.returns({}); +// var child = sinon.stub(require('node:child_process')); child.exec.returns({}); + +function fn () { + var result = child.exec(str); +} + +function fn () { + var result = childImport.exec(str); +} + +function fn () { + var result = nodeChildImport.exec(str); +} + +require('child_process').exec(str) + +function fn () { + require('child_process').exec(str) +} + +const {exec} = require('child_process'); +exec(str) + +const {exec: nodeExec} = require('node:child_process'); +nodeExec(str) + +import {exec as foo} from 'child_process'; +foo(com); +``` + +## Compliant Code Examples +```typescript +child_process.exec('ls') + +var {} = require('child_process'); +var result = /hello/.exec(str); + +var {} = require('node:child_process'); +var result = /hello/.exec(str); + +import {} from 'child_process'; +var result = /hello/.exec(str); + +import {} from 'node:child_process'; +var result = /hello/.exec(str); + +var { spawn } = require('child_process'); spawn(str); +var { spawn } = require('node:child_process'); spawn(str); +import { spawn } from 'child_process'; spawn(str); +import { spawn } from 'node:child_process'; spawn(str); + +// import redeclare not covered +// var foo = require('child_process'); +// function fn () { +// var foo = /hello/; +// var result = foo.exec(str); +// } + +var child = require('child_process'); child.spawn(str) +var child = require('node:child_process'); child.spawn(str) +import child from 'child_process'; child.spawn(str) +import child from 'node:child_process'; child.spawn(str) + +var foo = require('child_process'); +function fn () { + var result = foo.spawn(str); +} + +require('child_process').spawn(str) + +function fn () { + require('child_process').spawn(str) +} + +// constant assigment static analysis not covered +// var child_process = require('child_process'); +// var FOO = 'ls'; +// child_process.exec(FOO); + +// import child_process from 'child_process'; +// const FOO = 'ls'; +// child_process.exec(FOO); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md b/content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md new file mode 100644 index 0000000000000..81ba250e36e5c --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/detect-eval-with-expression + language: TypeScript + severity: Warning +title: Avoid `eval` with expressions +--- +## Metadata +**ID:** `typescript-node-security/detect-eval-with-expression` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +The `eval` function could execute malicious code if used with non-literal values. The argument provided to the `eval` method could be use to execute malicious code, if an attacker manage to control the `eval` argument they can execute arbitrary code. + +In JavaScript, the `eval()` function evaluates or executes an argument if it's a string of JavaScript code. If this argument is influenced by user input or other external sources, it can lead to security vulnerabilities. Specifically, if an attacker can control or manipulate the value of the `variable` in `eval(variable)`, they can execute arbitrary code. + +It is recommended to avoid `eval` at all cost, but if you face an advance use case make sure to use literal values that are under you control or take actions to sanitize the input, even then it is still recommended to avoid the use of `eval` as it has lead to security breaches before. + +## Non-Compliant Code Examples +```typescript +eval(a); +global.eval(a); +globalThis.eval(a); + +const answer = eval(expression) +``` + +## Compliant Code Examples +```typescript +eval('alert()') +global.eval('a'); +globalThis.eval('a'); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md b/content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md new file mode 100644 index 0000000000000..1034acfb0da2a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md @@ -0,0 +1,34 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/detect-new-buffer + language: TypeScript + severity: Warning +title: Avoid Buffer(argument) with non-literal values +--- +## Metadata +**ID:** `typescript-node-security/detect-new-buffer` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Dealing with binary data can achieved with Node.js Buffer class, however if used with non literal params it could lead to an attack as the attacker might control the value of the provided parameter. + +For example a large number could allocate a large amount of memory leading to a denial of service attack. It is recommended to use literal values you can control to prevent attacks. + +## Non-Compliant Code Examples +```typescript +var a = new Buffer(c) +``` + +## Compliant Code Examples +```typescript +var a = new Buffer('test') +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md new file mode 100644 index 0000000000000..b72b970e79d10 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md @@ -0,0 +1,149 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/detect-non-literal-fs-filename + language: TypeScript + severity: Warning +title: Avoid variables in 'fs' calls filename argument +--- +## Metadata +**ID:** `typescript-node-security/detect-non-literal-fs-filename` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +An attacker could manipulate the file system call argument leading to a path traversal attack where the attacker get access to files and directories within your server file system. + +## Non-Compliant Code Examples +```typescript +/// requires +var something = require('fs'); +var a = something.open(c); + +var one = require('fs').readFile; +one(filename); + +var one = require('node:fs').readFile; +one(filename); + +var one = require('fs/promises').readFile; +one(filename); + +var something = require('fs/promises'); +something.readFile(filename); + +var something = require('node:fs/promises'); +something.readFile(filename); + +var something = require('fs-extra'); +something.readFile(filename); + +var { readFile: something } = require('fs'); +something(filename) + +//// imports +import { readFile as something } from 'fs'; +something(filename); + +import { readFile as something } from 'node:fs'; +something(filename); + +import { readFile as something } from 'fs-extra'; +something(filename); + +import { readFile as something } from 'fs/promises' +something(filename) + +import { readFile as something } from 'node:fs/promises' +something(filename) + +import { readFile } from 'node:fs/promises' +something(readFile) + +import * as something from 'fs'; +something.readFile(filename); +import * as something from 'node:fs'; +something.readFile(filename); + +/// promises +var something = require('fs').promises; +something.readFile(filename) + +var something = require('node:fs').promises; +something.readFile(filename) + +var something = require('fs'); +something.promises.readFile(filename) + +var something = require('node:fs'); +something.promises.readFile(filename) + +var fs = require('fs'); +fs.readFile(`template with ${filename}`); + +// inline +function foo () { + var fs = require('fs'); + fs.readFile(filename); +} + +function foo () { + var { readFile: something } = require('fs'); + something(filename); +} + +var fs = require('fs'); +function foo () { + var { readFile: something } = fs.promises; + something(filename); +} + +import fs from 'fs'; +import path from 'path'; +const key = fs.readFileSync(path.resolve(__dirname, foo)); +``` + +## Compliant Code Examples +```typescript +var fs = require('fs'); +var a = fs.open('test') + +var something = require('some'); +var a = something.readFile(c); + +var something = require('fs').readFile, readFile = require('foo').readFile; +readFile(c); + + +// TODO: allow path with constant arguments +import { promises as fsp } from 'fs'; +import fs from 'fs'; +import path from 'path'; +// const index = await fsp.readFile(path.resolve(__dirname, './index.html'), 'utf-8'); +// const key = fs.readFileSync(path.join(__dirname, './ssl.key')); +await fsp.writeFile(path.resolve(__dirname, './sitemap.xml'), sitemap); + +import fs from 'fs'; +import path from 'path'; +const dirname = path.dirname(__filename) +// const key = fs.readFileSync(path.resolve(dirname, './index.html')); + +import fs from 'fs'; +// const key = fs.readFileSync(`${process.cwd()}/path/to/foo.json`); + +import fs from 'fs'; +import path from 'path'; +import url from 'url'; +// const dirname = path.dirname(url.fileURLToPath(import.meta.url)); +// const html = fs.readFileSync(path.resolve(dirname, './index.html'), 'utf-8'); + +import fs from 'fs'; +// const pkg = fs.readFileSync(require.resolve('eslint/package.json'), 'utf-8'); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md new file mode 100644 index 0000000000000..60affbdb0b185 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md @@ -0,0 +1,36 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/detect-non-literal-regexp + language: TypeScript + severity: Warning +title: Detects non-literal values in regular expressions +--- +## Metadata +**ID:** `typescript-node-security/detect-non-literal-regexp` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Creating a regular expression with user input is a security vulnerability as it could lead to a Regular Expression Denial of Service attack. In this type of attack a user could submit a very complex regular expression that takes too long to execute. + +If you have an advanced use case that requires regex evaluation with user input always make sure to sanitize the data and provide a safe timeout environment. + +## Non-Compliant Code Examples +```typescript +var a = new RegExp(c, 'i'); + +``` + +## Compliant Code Examples +```typescript +var a = new RegExp('ab+c', 'i'); + +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md new file mode 100644 index 0000000000000..ac328cb2a7b6f --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md @@ -0,0 +1,42 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/detect-non-literal-require + language: TypeScript + severity: Warning +title: Avoid require with non-literal values +--- +## Metadata +**ID:** `typescript-node-security/detect-non-literal-require` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Importing packages from dynamic paths can be a security vulnerability. An attacker might provide an undesired path that leads to running arbitrary code or reading sensitive information from your file system. + +In Node.js, the `require()` function is a built-in function that allows modules to be loaded. You can use it to include various types of files (like .js, .json, .node, etc) in your project. + +If the argument to `require()` is a variable instead of a static string, and if that variable's value can be influenced by user input, then an attacker might be able to exploit this to run arbitrary code or read sensitive files from your server's disk. This is a serious security issue often referred to as arbitrary code execution. + +Dynamic imports are a common source of arbitrary file read and code execution vulnerabilities. Avoid using variables with `require` or `import` statements. If you have an advanced use case that requires the use of dynamic imports, make sure to sanitize the input and have an allowed list of paths you can import code from. Always set the proper access control to your file system. + +## Non-Compliant Code Examples +```typescript +const a = require(c); +const a = require(`${c}`); + +``` + +## Compliant Code Examples +```typescript +var a = require('b'); +var a = require(`b`); + +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md b/content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md new file mode 100644 index 0000000000000..4a5d3fcb90e60 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/detected-jwt-token + language: TypeScript + severity: Error +title: Detects hardcoded JWT tokens within the codebase +--- +## Metadata +**ID:** `typescript-node-security/detected-jwt-token` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Security + +## Description +JSON Web Tokens (JWT) are commonly used for authentication and information exchange in web applications. While they are a powerful tool, they must be handled with care. + +## Non-Compliant Code Examples +```typescript +"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" +"eyJ0eXAiOiJKV1QiLA0KImFsZyI6IkhTMjU2In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" +"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9lIiwKInN0YXR1cyI6ImVtcGxveWVlIgp9" +'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IsWww6HFkcOtIMOWxZHDqcOoIiwiaWF0IjoxNTE2MjM5MDIyfQ.k5HibI_uLn_RTuPcaCNkaVaQH2y5q6GvJg8GPpGMRwQ' +`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ` +``` + +## Compliant Code Examples +```typescript +"eyfoo" +`eybaz` +'eybla' +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md b/content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md new file mode 100644 index 0000000000000..d86ae0cc81458 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md @@ -0,0 +1,47 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/hardcoded-hmac-key + language: TypeScript + severity: Warning +title: Detects hardcoded HMAC keys +--- +## Metadata +**ID:** `typescript-node-security/hardcoded-hmac-key` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Hardcoding cryptographic keys, secrets, or other sensitive information within the code is a common but dangerous practice. This rule aims to detect and prevent this kind of code pattern. + +## Non-Compliant Code Examples +```typescript +import crypto from "crypto"; + +crypto.createHmac('sha256', 'pa4qacea4VK9t9nGv7yZtwmj').update(data).digest('hex'); + +const rsa_key = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' +const hmac = crypto.createHmac('sha256', rsa_key) + +const key = 'private'; +const secret = key; +const fail = crypto.createHmac('sha256', secret); +``` + +## Compliant Code Examples +```typescript +import crypto from "crypto"; +import config from "./config"; + +const safely_stored_key = config.get('AWS_KEY') +const safe_hmac = crypto.createHmac('sha256', safely_stored_key) + +crypto.createHmac('sha256', process.env.KEY); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/insecure-hash.md b/content/en/static_analysis/rules/typescript-node-security/insecure-hash.md new file mode 100644 index 0000000000000..c162b720a3720 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/insecure-hash.md @@ -0,0 +1,38 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/insecure-hash + language: TypeScript + severity: Warning +title: Do not use weah hash functions +--- +## Metadata +**ID:** `typescript-node-security/insecure-hash` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not use weak hash algorithms such as MD5 or SHA1. + +#### Learn More + + - [CWE-328: Use of Weak Hash](https://cwe.mitre.org/data/definitions/328.html) + +## Non-Compliant Code Examples +```typescript +crypto.createHash("md5") +crypto.createHash("sha1") +``` + +## Compliant Code Examples +```typescript +crypto.createHash("sha256") + +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md b/content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md new file mode 100644 index 0000000000000..1a349344e999e --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md @@ -0,0 +1,54 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/insecure-jwt-secret-usage + language: TypeScript + severity: Error +title: Insecure Usage of a Static Secret in JWT Signing +--- +## Metadata +**ID:** `typescript-node-security/insecure-jwt-secret-usage` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Security + +## Description +Using a static secret for signing JSON Web Tokens (JWT) poses several security risks: + +1. **Static Secrets**: Static secrets embedded in the code can be easily discovered by attackers. This is particularly dangerous if the code becomes publicly available or is leaked. +2. **Weak Secrets**: A simple, static secret might be weak and easily guessable, rendering the security controls it supports ineffective. +3. **Lack of Key Rotation**: A static secret doesn't allow for key rotation, a recommended practice to mitigate the risk if a secret is compromised. + +## Non-Compliant Code Examples +```typescript +import jwt from 'jsonwebtoken'; + +const privateKey = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' +export const authorize = (user = {}) => jwt.sign(user, privateKey, { expiresIn: '6h', algorithm: 'RS256' }); + +jwt.sign({ user: 'foo' }, 'secret'); + +const key = 'shhh'; +const secret = key; +jwt.sign({ user: 'foo' }, secret); +``` + +## Compliant Code Examples +```typescript +import jwt from "jsonwebtoken"; +import config from './config'; + +const payload = {foo: 'bar'}; +const secret3 = process.env.SECRET +const token5 = jwt.sign(payload, secret3) + +jwt.sign(payload, process.env.KEY); +jwt.sign(payload, config.secret); + +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md b/content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md new file mode 100644 index 0000000000000..99f3642ab53fa --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/jwt-hardcoded-secret + language: TypeScript + severity: Error +title: Do not use hardcoded secret with a JWT +--- +## Metadata +**ID:** `typescript-node-security/jwt-hardcoded-secret` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Security + +## Description +Never hardcode secrets. Instead, use secrets from environment variables or a secret vault. + +## Non-Compliant Code Examples +```typescript +import jwt from "jsonwebtoken"; + +const token = jwt.sign({ foo: "bar" }, "secret"); + +const token = jwt.sign({ foo: "bar" }, 'secret'); + +const token = jwt.sign({ foo: "bar" }, `secret`); +``` + +## Compliant Code Examples +```typescript +import jwt from "jsonwebtoken"; + +const token = jwt.sign({ foo: "bar" }, process.env.JWT_SECRET); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md b/content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md new file mode 100644 index 0000000000000..2b87b2add2635 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md @@ -0,0 +1,40 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/jwt-sensitive-data + language: TypeScript + severity: Warning +title: Do not put sensitive data in objects +--- +## Metadata +**ID:** `typescript-node-security/jwt-sensitive-data` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Never include sensitive information in a JWT. Instead, only use non-personal information to identify the end-user. + +## Non-Compliant Code Examples +```typescript +jwt.sign( + { user: { email: 'foo@bar.com' }} +) + +jwt.sign( + { user: { lastname: 'babar' }} +) +``` + +## Compliant Code Examples +```typescript +jwt.sign( + {user: { id: 42 }} +) +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md b/content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md new file mode 100644 index 0000000000000..66f6ab586a364 --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md @@ -0,0 +1,35 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/jwt-weak-encryption + language: TypeScript + severity: Warning +title: Use default encryption from the JWT library +--- +## Metadata +**ID:** `typescript-node-security/jwt-weak-encryption` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not use `none` as a validation algorithm for a JWT token. The none algorithm assumes that the token has been verified, which would allow attacker to create a token that would be automatically validated. + +Never use the `none` algorithm, always use a valid algorithm as directed by [the documentation](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback). + +## Non-Compliant Code Examples +```typescript +jwt.verify(token, secret, { algorithms: ['RS256', 'none'] }, func); +jwt.verify(token, secret, { algorithms: ['none', 'RS256'] }, func); +``` + +## Compliant Code Examples +```typescript +jwt.verify(token, secret, { algorithms: ['RS256', 'HS256'] }, func); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md b/content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md new file mode 100644 index 0000000000000..2f521d7c13ddc --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md @@ -0,0 +1,44 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/log-sensitive-data + language: TypeScript + severity: Warning +title: Avoid logging sensitive data +--- +## Metadata +**ID:** `typescript-node-security/log-sensitive-data` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not log sensitive data such as user id, email or other personal data (first name, last name, etc). + +## Non-Compliant Code Examples +```typescript +console.log("email from user" + user.email); +console.log(`email from user ${user.email}`); +logger.info(`email from user ${user.email}`); +logger.info(`email from user ${user.name}: ${user.email}`); +logger.info(`email from user ${username}: ${user.email}`); +logger.warn(email); +logger.error(`email from user ${email}`); + +foobar.error(`email from user ${email}`); + +logger.foobar(`email from user ${email}`); + +``` + +## Compliant Code Examples +```typescript +console.log("email from user" + user.id); +console.log(`email from user ${user.uuid}`); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md b/content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md new file mode 100644 index 0000000000000..e3e3d640dc4be --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md @@ -0,0 +1,56 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/oauth2-hardcoded-secret + language: TypeScript + severity: Warning +title: Do not use hardcoded secret for OAuth2 providers +--- +## Metadata +**ID:** `typescript-node-security/oauth2-hardcoded-secret` + +**Language:** TypeScript + +**Severity:** Warning + +**Category:** Security + +## Description +Do not put hardcoded credentials in code. Instead, put secrets in environment variables or a vault. + +## Non-Compliant Code Examples +```typescript +passport.use(new OAuth2Strategy({ + authorizationURL: 'https://www.example.com/oauth2/authorize', + tokenURL: 'https://www.example.com/oauth2/token', + clientID: `client_id`, + clientSecret: 'secret_id', + callbackURL: "http://localhost:3000/auth/example/callback" + }, + function(accessToken, refreshToken, profile, cb) { + User.findOrCreate({ exampleId: profile.id }, function (err, user) { + return cb(err, user); + }); + } +)); +``` + +## Compliant Code Examples +```typescript +passport.use(new OAuth2Strategy({ + authorizationURL: 'https://www.example.com/oauth2/authorize', + tokenURL: 'https://www.example.com/oauth2/token', + clientID: process.env.EXAMPLE_CLIENT_ID, + clientSecret: process.env.EXAMPLE_CLIENT_SECRET, + callbackURL: "http://localhost:3000/auth/example/callback" + }, + function(accessToken, refreshToken, profile, cb) { + User.findOrCreate({ exampleId: profile.id }, function (err, user) { + return cb(err, user); + }); + } +)); +``` diff --git a/content/en/static_analysis/rules/typescript-node-security/sql-injection.md b/content/en/static_analysis/rules/typescript-node-security/sql-injection.md new file mode 100644 index 0000000000000..d6a64e610055a --- /dev/null +++ b/content/en/static_analysis/rules/typescript-node-security/sql-injection.md @@ -0,0 +1,276 @@ +--- +dependencies: [] +disable_edit: true +kind: documentation +meta: + category: Security + id: typescript-node-security/sql-injection + language: TypeScript + severity: Error +title: Avoid SQL injection +--- +## Metadata +**ID:** `typescript-node-security/sql-injection` + +**Language:** TypeScript + +**Severity:** Error + +**Category:** Security + +## Description +Check for variable declarations in a SQL statement where there is potential for SQL injections. + +#### Learn More + + - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) + +## Non-Compliant Code Examples +```typescript +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + // only allow apple or orange related searches + if (!criteria.startsWith("apple") || !criteria.startsWith("orange")) { + res.status(400).send() + return + } + models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```typescript +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + criteria.replace(/"|'|;|and|or/i, "") + models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```typescript +const injectionChars = /"|'|;|and|or|;|#/i; + +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + if (criteria.match(injectionChars)) { + res.status(400).send() + return + } + models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```typescript +module.exports = function searchProducts () { + return (req: Request, res: Response, next: NextFunction) => { + let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' + criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) + models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name") + .then(([products]: any) => { + const dataString = JSON.stringify(products) + for (let i = 0; i < products.length; i++) { + products[i].name = req.__(products[i].name) + products[i].description = req.__(products[i].description) + } + res.json(utils.queryResultToJson(products)) + }).catch((error: ErrorWithParent) => { + next(error.parent) + }) + } +} +``` + +```typescript +var express = require('express') + +var app = express() +const Sequelize = require('sequelize'); +const sequelize = new Sequelize('database', 'username', 'password', { + dialect: 'sqlite', + storage: 'data/juiceshop.sqlite' +}); + +app.post('/login', function (req, res) { + sequelize.query('SELECT * FROM Products WHERE name LIKE ' + req.body.username); + }) + + +app.post('/update', function (req, res) { + sequelize.query('UPDATE products SET bla=bli WHERE name LIKE ' + req.body.username); + }) + + + +app.post('/remove', function (req, res) { + sequelize.query('DELETE FROM product WHERE name LIKE ' + req.body.username); + }) +``` + +```typescript +const express = require('express'); +const router = express.Router() + +const config = require('../../config') +const mysql = require('mysql'); +const connection = mysql.createConnection({ + host : config.MYSQL_HOST, + port : config.MYSQL_PORT, + user : config.MYSQL_USER, + password : config.MYSQL_PASSWORD, + database : config.MYSQL_DB_NAME, +}); + +connection.connect(); + +router.get('/example1/user/:id', (req,res) => { + let userId = req.params.id; + let query = { + sql : "SELECT * FROM users WHERE id=" + userId + } + connection.query(query,(err, result) => { + res.json(result); + }); +}) + +router.get('/example2/user/:id', (req,res) => { + let userId = req.params.id; + connection.query("SELECT * FROM users WHERE id=" + userId,(err, result) => { + res.json(result); + }); +}) + +router.get('/example3/user/:id', (req,res) => { + let userId = req.params.id; + connection.query({ + sql : "SELECT * FROM users WHERE id=" +userId + },(err, result) => { + res.json(result); + }); +}) + + +module.exports = router +``` + +## Compliant Code Examples +```typescript +import {BasketModel} from "../../../models/basket"; + +module.exports = function login () { + function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { + BasketModel.findOrCreate({ where: { UserId: user.data.id } }) + .then(([basket]: [BasketModel, boolean]) => { + const token = security.authorize(user) + user.bid = basket.id // keep track of original basket + security.authenticatedUsers.put(token, user) + res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) + }).catch((error: Error) => { + next(error) + }) + } + + return (req: Request, res: Response, next: NextFunction) => { + models.sequelize.query(`SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL`, + { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) + .then((authenticatedUser: { data: User }) => { + const user = utils.queryResultToJson(authenticatedUser) + if (user.data?.id && user.data.totpSecret !== '') { + res.status(401).json({ + status: 'totp_token_required', + data: { + tmpToken: security.authorize({ + userId: user.data.id, + type: 'password_valid_needs_second_factor_token' + }) + } + }) + } else if (user.data?.id) { + afterLogin(user, res, next) + } else { + res.status(401).send(res.__('Invalid email or password.')) + } + }).catch((error: Error) => { + next(error) + }) + } +``` + +```typescript +import {BasketModel} from "../../../models/basket"; + +module.exports = function login () { + function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { + BasketModel.findOrCreate({ where: { UserId: user.data.id } }) + .then(([basket]: [BasketModel, boolean]) => { + const token = security.authorize(user) + user.bid = basket.id // keep track of original basket + security.authenticatedUsers.put(token, user) + res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) + }).catch((error: Error) => { + next(error) + }) + } + + return (req: Request, res: Response, next: NextFunction) => { + models.sequelize.query('SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL', + { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) + .then((authenticatedUser: { data: User }) => { + const user = utils.queryResultToJson(authenticatedUser) + if (user.data?.id && user.data.totpSecret !== '') { + res.status(401).json({ + status: 'totp_token_required', + data: { + tmpToken: security.authorize({ + userId: user.data.id, + type: 'password_valid_needs_second_factor_token' + }) + } + }) + } else if (user.data?.id) { + afterLogin(user, res, next) + } else { + res.status(401).send(res.__('Invalid email or password.')) + } + }).catch((error: Error) => { + next(error) + }) + } +``` diff --git a/local/bin/py/build/configurations/pull_config.yaml b/local/bin/py/build/configurations/pull_config.yaml index 006e138e8b4ad..51cba83ee0ad4 100644 --- a/local/bin/py/build/configurations/pull_config.yaml +++ b/local/bin/py/build/configurations/pull_config.yaml @@ -343,13 +343,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'circleci_orbs.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md"] title: Static Analysis and CircleCI Orbs kind: documentation description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/circleci_orbs - repo_name: datadog-static-analyzer-github-action contents: @@ -358,13 +360,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'github_actions.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md"] title: Static Analysis and GitHub Actions kind: documentation description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/github_actions - repo_name: datadog-static-analyzer-rule-docs contents: @@ -373,7 +377,7 @@ globs: - rulesets/**/*.md options: - dest_dir: '/continuous_integration/static_analysis/rules/' + dest_dir: '/static_analysis/rules/' path_to_remove: 'rulesets/' front_matters: disable_edit: true diff --git a/local/bin/py/build/configurations/pull_config_preview.yaml b/local/bin/py/build/configurations/pull_config_preview.yaml index 4e01a7f401c27..90d444307c516 100644 --- a/local/bin/py/build/configurations/pull_config_preview.yaml +++ b/local/bin/py/build/configurations/pull_config_preview.yaml @@ -1,6 +1,6 @@ --- - config: - cache_enabled: true + cache_enabled: false - data: - org_name: jenkinsci @@ -344,13 +344,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'circleci_orbs.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md"] title: Static Analysis and CircleCI Orbs kind: documentation description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/circleci_orbs - repo_name: datadog-static-analyzer-github-action contents: @@ -359,13 +361,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'github_actions.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md"] title: Static Analysis and GitHub Actions kind: documentation description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/github_actions - repo_name: datadog-static-analyzer-rule-docs contents: @@ -374,7 +378,7 @@ globs: - rulesets/**/*.md options: - dest_dir: '/continuous_integration/static_analysis/rules/' + dest_dir: '/static_analysis/rules/' path_to_remove: 'rulesets/' front_matters: disable_edit: true From 750a6dc3c77bcef11a9aa2dcece2496012acda4e Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:28:02 -0800 Subject: [PATCH 05/12] Update .gitignore --- .gitignore | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 0225eda8b1fd4..7e9a0716d0c46 100644 --- a/.gitignore +++ b/.gitignore @@ -101,10 +101,10 @@ content/en/continuous_testing/cicd_integrations/circleci_orb.md content/en/continuous_testing/cicd_integrations/azure_devops_extension.md # Static Analysis -content/en/continuous_integration/static_analysis/github_actions.md -content/en/continuous_integration/static_analysis/circleci_orbs.md -content/en/continuous_integration/static_analysis/rules/ -!content/en/continuous_integration/static_analysis/rules/_index.md +content/en/static_analysis/github_actions.md +content/en/static_analysis/circleci_orbs.md +content/en/static_analysis/rules/ +!content/en/static_analysis/rules/_index.md # serverless content/en/serverless/libraries_integrations/plugin.md From 959824c75d6a3cd2ccaaac7b0d20c6faec09ebec Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:29:56 -0800 Subject: [PATCH 06/12] Revert "Update Slugs + Add Aliases" This reverts commit 6739086a5df93eaca1cb6982acb334b6e0756b4a. --- config/_default/menus/menus.en.yaml | 30 +- .../dora_metrics/_index.md | 2 - .../quality_gates/_index.md | 2 - .../static_analysis/_index.md | 2 - .../static_analysis/rules/_index.md | 2 - content/en/static_analysis/circleci_orbs.md | 102 -- content/en/static_analysis/github_actions.md | 72 -- .../docker-best-practices/absolute-workdir.md | 34 - .../alias-must-be-unique.md | 40 - .../docker-best-practices/apt-get-yes.md | 32 - .../docker-best-practices/apt-pin-version.md | 39 - .../docker-best-practices/avoid-chmod-777.md | 35 - .../avoid-commands-not-relevant.md | 35 - .../rules/docker-best-practices/avoid-http.md | 35 - .../rules/docker-best-practices/dnf-use-y.md | 32 - .../expose-admin-ports.md | 34 - .../expose-valid-port.md | 32 - .../image-avoid-digest.md | 34 - .../maintainer-deprecated.md | 32 - .../docker-best-practices/multiple-cmd.md | 35 - .../multiple-entrypoint.md | 35 - .../multiple-healthcheck.md | 33 - .../docker-best-practices/no-root-user.md | 38 - .../docker-best-practices/pip-no-cache.md | 35 - .../docker-best-practices/pip-pin-versions.md | 34 - .../tag-image-version.md | 34 - .../rules/docker-best-practices/yum-use-y.md | 32 - .../docker-best-practices/zypper-use-y.md | 34 - .../for-direction.md | 83 -- .../javascript-best-practices/new-parens.md | 85 -- .../javascript-best-practices/no-alert.md | 80 -- .../no-async-promise-executor.md | 35 - .../javascript-best-practices/no-caller.md | 36 - .../no-case-declarations.md | 60 -- .../no-compare-neg-zero.md | 69 -- .../no-cond-assign.md | 74 -- .../javascript-best-practices/no-console.md | 35 - .../javascript-best-practices/no-debugger.md | 32 - .../no-delete-var.md | 32 - .../javascript-best-practices/no-dupe-args.md | 43 - .../no-dupe-class-members.md | 92 -- .../javascript-best-practices/no-dupe-keys.md | 68 -- .../no-duplicate-case.md | 73 -- .../no-empty-character-class.md | 52 - .../no-empty-pattern.md | 45 - .../javascript-best-practices/no-empty.md | 77 -- .../javascript-best-practices/no-ex-assign.md | 38 - .../no-implied-eval.md | 180 ---- .../no-import-assign.md | 149 --- .../no-inner-declarations.md | 71 -- .../javascript-best-practices/no-iterator.md | 40 - .../no-loss-of-precision.md | 132 --- .../no-new-symbol.md | 35 - .../javascript-best-practices/no-octal.md | 47 - .../javascript-best-practices/no-proto.md | 41 - .../no-script-url.md | 40 - .../no-unsafe-negation.md | 45 - .../javascript-best-practices/no-with.md | 32 - .../require-yield.md | 45 - .../javascript-best-practices/use-isnan.md | 91 -- .../javascript-best-practices/valid-typeof.md | 87 -- .../event-check-origin.md | 44 - .../inner-outer-html.md | 81 -- .../insecure-websocket.md | 34 - .../local-storage-sensitive-data.md | 39 - .../manual-sanitization.md | 45 - .../postmessage-permissive-origin.md | 38 - .../react-dangerously-inner-html.md | 50 - .../regexp-non-literal.md | 35 - .../javascript-code-style/assignment-name.md | 95 -- .../rules/javascript-code-style/class-name.md | 33 - .../rules/javascript-code-style/eqeqeq.md | 85 -- .../func-name-matching.md | 195 ---- .../rules/javascript-code-style/func-names.md | 96 -- .../javascript-code-style/function-naming.md | 38 - .../javascript-code-style/max-class-lines.md | 258 ----- .../max-function-lines.md | 952 ------------------ .../rules/javascript-code-style/max-params.md | 46 - .../javascript-code-style/method-name.md | 38 - .../no-array-constructor.md | 45 - .../javascript-code-style/no-div-regex.md | 33 - .../no-duplicate-imports.md | 42 - .../no-floating-decimal.md | 41 - .../javascript-code-style/no-lonely-if.md | 122 --- .../javascript-code-style/no-multi-assign.md | 72 -- .../javascript-code-style/no-new-func.md | 54 - .../javascript-code-style/no-new-object.md | 61 -- .../rules/javascript-code-style/no-new.md | 33 - .../javascript-code-style/no-return-assign.md | 84 -- .../javascript-code-style/no-self-compare.md | 51 - .../rules/javascript-code-style/no-var.md | 62 -- .../javascript-code-style/parameter-name.md | 37 - .../rules/javascript-code-style/radix.md | 84 -- .../axios-avoid-insecure-http.md | 34 - .../unique-function-arguments.md | 40 - .../xml-no-external-entities.md | 43 - .../javascript-express/access-restriction.md | 46 - .../default-session-config.md | 50 - .../external-filename-upload.md | 57 -- .../javascript-express/external-resource.md | 44 - .../javascript-express/hardcoded-secret.md | 69 -- .../https-protocol-missing.md | 46 - .../insecure-allow-origin.md | 51 - .../javascript-express/insecure-cookie.md | 62 -- .../javascript-express/jwt-not-revoked.md | 93 -- .../javascript-express/missing-helmet.md | 67 -- .../javascript-express/path-traversal.md | 57 -- .../reduce-server-fingerprinting.md | 66 -- .../javascript-express/xss-vulnerability.md | 45 - .../rules/javascript-inclusive/comments.md | 47 - .../javascript-inclusive/declarations.md | 50 - .../javascript-inclusive/formal-parameters.md | 42 - .../rules/javascript-inclusive/identifiers.md | 50 - .../rules/javascript-node-security/argon2.md | 38 - .../avoid-crypto-rc4.md | 32 - .../avoid-crypto-sha1.md | 32 - .../javascript-node-security/avoid-des.md | 34 - .../chmod-permissions.md | 42 - .../command-injection.md | 34 - .../crypto-avoid-weak-hash.md | 33 - .../detect-buffer-noassert.md | 115 --- .../detect-child-process.md | 119 --- .../detect-eval-with-expression.md | 42 - .../detect-new-buffer.md | 34 - .../detect-non-literal-fs-filename.md | 149 --- .../detect-non-literal-regexp.md | 36 - .../detect-non-literal-require.md | 42 - .../detected-jwt-token.md | 38 - .../hardcoded-hmac-key.md | 47 - .../javascript-node-security/insecure-hash.md | 41 - .../insecure-jwt-secret-usage.md | 54 - .../jwt-hardcoded-secret.md | 41 - .../jwt-sensitive-data.md | 41 - .../jwt-weak-encryption.md | 35 - .../log-sensitive-data.md | 44 - .../oauth2-hardcoded-secret.md | 56 -- .../javascript-node-security/sql-injection.md | 276 ----- .../variable-sql-statement-injection.md | 35 - .../rules/jsx-react/jsx-key.md | 45 - .../jsx-react/jsx-no-comment-textnodes.md | 69 -- .../rules/jsx-react/jsx-no-duplicate-key.md | 41 - .../rules/jsx-react/jsx-no-duplicate-props.md | 34 - .../rules/jsx-react/jsx-no-target-blank.md | 49 - .../rules/jsx-react/no-children-prop.md | 44 - .../jsx-react/no-danger-with-children.md | 43 - .../rules/jsx-react/no-deprecated.md | 73 -- .../rules/jsx-react/no-render-return-value.md | 34 - .../rules/jsx-react/no-string-refs.md | 58 -- .../rules/jsx-react/require-render-return.md | 52 - .../ambiguous-class-name.md | 34 - .../ambiguous-function-name.md | 34 - .../ambiguous-variable-name.md | 33 - .../any-type-disallow.md | 45 - .../argument-same-name.md | 34 - .../assertraises-specific-exception.md | 34 - .../avoid-duplicate-keys.md | 43 - .../avoid-string-concat.md | 54 - .../class-methods-use-self.md | 46 - .../collection-while-iterating.md | 39 - .../comment-fixme-todo-ownership.md | 52 - .../comparison-constant-left.md | 47 - .../condition-similar-block.md | 48 - .../ctx-manager-enter-exit-defined.md | 48 - .../dataclass-special-methods.md | 66 -- .../equal-basic-types.md | 36 - .../exception-inherit.md | 38 - .../finally-no-break-continue-return.md | 72 -- .../function-already-exists.md | 50 - .../function-variable-argument-name.md | 39 - .../generic-exception-last.md | 57 -- .../get-set-arguments.md | 69 -- .../if-return-no-else.md | 46 - .../import-modules-twice.md | 45 - .../import-single-module.md | 35 - .../python-best-practices/init-call-parent.md | 52 - .../init-method-required.md | 106 -- .../init-no-return-value.md | 44 - .../invalid-strip-call.md | 32 - .../logging-no-format.md | 37 - .../python-best-practices/method-hidden.md | 48 - .../python-best-practices/nested-blocks.md | 78 -- .../no-assert-on-tuples.md | 34 - .../rules/python-best-practices/no-assert.md | 46 - .../python-best-practices/no-bare-except.md | 70 -- .../python-best-practices/no-bare-raise.md | 49 - .../no-base-exception.md | 55 - .../no-datetime-today.md | 38 - .../python-best-practices/no-double-not.md | 34 - .../no-double-unary-operator.md | 35 - .../no-duplicate-base-class.md | 43 - .../python-best-practices/no-equal-unary.md | 40 - .../rules/python-best-practices/no-exit.md | 38 - .../no-generic-exception.md | 46 - .../rules/python-best-practices/no-if-true.md | 34 - .../no-range-loop-with-len.md | 43 - .../no-silent-exception.md | 43 - .../python-best-practices/open-add-flag.md | 45 - .../os-environ-no-assign.md | 37 - .../raising-not-implemented.md | 42 - .../return-bytes-not-string.md | 38 - .../return-outside-function.md | 41 - .../python-best-practices/self-assignment.md | 34 - .../slots-no-single-string.md | 53 - .../special-methods-arguments.md | 54 - .../static-method-no-self.md | 38 - .../too-many-nested-if.md | 39 - .../python-best-practices/too-many-while.md | 41 - .../type-check-isinstance.md | 39 - .../python-best-practices/unreachable-code.md | 44 - .../use-callable-not-hasattr.md | 36 - .../python-code-style/assignment-names.md | 44 - .../rules/python-code-style/class-name.md | 93 -- .../python-code-style/function-naming.md | 67 -- .../python-code-style/max-class-lines.md | 138 --- .../python-code-style/max-function-lines.md | 259 ----- .../rules/python-design/function-too-long.md | 134 --- .../http-response-from-request.md | 45 - .../http-response-with-json-dumps.md | 47 - .../jsonresponse-no-content-type.md | 46 - .../model-charfield-max-length.md | 36 - .../rules/python-django/model-help-text.md | 39 - .../rules/python-django/no-null-boolean.md | 35 - .../python-django/no-unicode-on-models.md | 38 - .../open-filename-from-request.md | 77 -- .../python-django/os-system-from-request.md | 51 - .../python-django/subprocess-from-request.md | 59 -- .../python-django/use-convenience-imports.md | 32 - .../python-flask/disable-sqlalchemy-text.md | 67 -- .../html-format-from-user-input.md | 91 -- .../python-flask/listen-all-interfaces.md | 47 - .../python-flask/no-render-template-string.md | 47 - .../open-file-unsanitized-data.md | 73 -- .../os-system-unsanitized-data.md | 66 -- .../rules/python-flask/secure-cookie.md | 42 - .../python-flask/sqlalchemy-injection.md | 64 -- .../rules/python-flask/ssrf-requests.md | 96 -- .../python-flask/urlopen-unsanitized-data.md | 62 -- .../rules/python-flask/use-jsonify.md | 46 - .../rules/python-inclusive/comments.md | 57 -- .../python-inclusive/function-definition.md | 62 -- .../rules/python-inclusive/variable-name.md | 47 - .../arith-operator-not-functions.md | 60 -- .../rules/python-pandas/avoid-inplace.md | 36 - .../comp-operator-not-function.md | 32 - .../rules/python-pandas/import-as-pd.md | 53 - .../python-pandas/isna-instead-of-isnull.md | 36 - .../rules/python-pandas/loc-not-ix.md | 40 - .../python-pandas/notna-instead-of-notnull.md | 32 - .../rules/python-pandas/pivot-table.md | 51 - .../use-read-csv-not-read-table.md | 32 - .../asyncio-subprocess-create-shell.md | 47 - .../asyncio-subprocess-exec.md | 46 - .../rules/python-security/avoid-random.md | 64 -- .../python-security/aws-boto-credentials.md | 89 -- .../deserialize-untrusted-data.md | 54 - .../python-security/file-write-others.md | 51 - .../python-security/hardcoded-tmp-file.md | 64 -- .../html-string-from-parameters.md | 76 -- .../insecure-hash-functions.md | 52 - .../rules/python-security/insecure-jwt.md | 53 - .../python-security/insecure-ssl-protocols.md | 74 -- .../rules/python-security/jinja-autoescape.md | 70 -- .../rules/python-security/mktemp.md | 49 - .../no-empty-array-as-parameter.md | 38 - .../rules/python-security/no-eval.md | 45 - .../rules/python-security/os-spawn.md | 57 -- .../rules/python-security/os-system.md | 88 -- .../rules/python-security/request-verify.md | 42 - .../rules/python-security/requests-http.md | 72 -- .../rules/python-security/requests-timeout.md | 64 -- .../python-security/ruamel-unsafe-yaml.md | 55 - .../sql-server-security-credentials.md | 86 -- .../python-security/ssl-unverified-context.md | 52 - .../python-security/subprocess-shell-true.md | 43 - .../variable-sql-statement-injection.md | 145 --- .../rules/python-security/yaml-load.md | 52 - .../tsx-react/jsx-no-comment-textnodes.md | 69 -- .../rules/tsx-react/no-children-prop.md | 44 - .../tsx-react/no-danger-with-children.md | 43 - .../rules/tsx-react/no-deprecated.md | 73 -- .../rules/tsx-react/no-render-return-value.md | 34 - .../rules/tsx-react/no-string-refs.md | 58 -- .../rules/tsx-react/require-render-return.md | 52 - .../rules/tsx-react/tsx-key.md | 45 - .../rules/tsx-react/tsx-no-duplicate-key.md | 41 - .../rules/tsx-react/tsx-no-target-blank.md | 49 - .../typescript-best-practices/ban-types.md | 62 -- .../boolean-prop-naming.md | 41 - .../for-direction.md | 83 -- .../typescript-best-practices/new-parens.md | 84 -- .../typescript-best-practices/no-alert.md | 80 -- .../no-async-promise-executor.md | 35 - .../typescript-best-practices/no-caller.md | 36 - .../no-compare-neg-zero.md | 69 -- .../no-cond-assign.md | 74 -- .../typescript-best-practices/no-console.md | 35 - .../typescript-best-practices/no-debugger.md | 32 - .../no-delete-var.md | 32 - .../typescript-best-practices/no-dupe-keys.md | 68 -- .../no-duplicate-enum-values.md | 108 -- .../no-duplicate-type-constituents.md | 112 --- .../no-empty-character-class.md | 52 - .../no-empty-pattern.md | 45 - .../typescript-best-practices/no-empty.md | 77 -- .../typescript-best-practices/no-ex-assign.md | 38 - .../no-explicit-any.md | 175 ---- .../no-extra-non-null-assertion.md | 58 -- .../no-implied-eval.md | 180 ---- .../no-inner-declarations.md | 71 -- .../typescript-best-practices/no-iterator.md | 40 - .../no-loss-of-precision.md | 131 --- .../typescript-best-practices/no-namespace.md | 73 -- .../no-non-null-optional-chain.md | 53 - .../typescript-best-practices/no-proto.md | 41 - .../no-script-url.md | 40 - .../no-unnecessary-type-constraint.md | 74 -- .../no-unsafe-assignment.md | 74 -- .../no-unsafe-declaration-merging.md | 41 - .../no-unsafe-negation.md | 45 - .../no-var-requires.md | 51 - .../require-yield.md | 45 - .../triple-slash-reference.md | 36 - .../event-check-origin.md | 44 - .../inner-outer-html.md | 81 -- .../insecure-websocket.md | 34 - .../local-storage-sensitive-data.md | 39 - .../manual-sanitization.md | 45 - .../postmessage-permissive-origin.md | 38 - .../react-dangerously-inner-html.md | 50 - .../regexp-non-literal.md | 35 - .../rules/typescript-code-style/array-type.md | 129 --- .../typescript-code-style/assignment-name.md | 94 -- .../typescript-code-style/ban-ts-comment.md | 39 - .../ban-tslint-comment.md | 40 - .../rules/typescript-code-style/class-name.md | 33 - .../rules/typescript-code-style/eqeqeq.md | 85 -- .../func-name-matching.md | 195 ---- .../rules/typescript-code-style/func-names.md | 96 -- .../typescript-code-style/function-naming.md | 38 - .../typescript-code-style/max-class-lines.md | 258 ----- .../max-function-lines.md | 952 ------------------ .../rules/typescript-code-style/max-params.md | 46 - .../typescript-code-style/method-name.md | 38 - .../no-array-constructor.md | 45 - .../no-confusing-non-null-assertion.md | 44 - .../typescript-code-style/no-div-regex.md | 33 - .../no-duplicate-imports.md | 42 - .../no-empty-interface.md | 51 - .../no-floating-decimal.md | 41 - .../no-inferrable-types.md | 111 -- .../typescript-code-style/no-lonely-if.md | 122 --- .../typescript-code-style/no-multi-assign.md | 72 -- .../typescript-code-style/no-new-func.md | 54 - .../typescript-code-style/no-new-object.md | 60 -- .../rules/typescript-code-style/no-new.md | 33 - .../typescript-code-style/no-return-assign.md | 84 -- .../typescript-code-style/no-self-compare.md | 51 - .../no-useless-empty-export.md | 49 - .../rules/typescript-code-style/no-var.md | 62 -- .../typescript-code-style/parameter-name.md | 37 - .../rules/typescript-code-style/radix.md | 84 -- .../axios-avoid-insecure-http.md | 34 - .../unique-function-arguments.md | 40 - .../xml-no-external-entities.md | 43 - .../typescript-express/access-restriction.md | 46 - .../default-session-config.md | 50 - .../external-filename-upload.md | 53 - .../typescript-express/external-resource.md | 44 - .../typescript-express/hardcoded-secret.md | 69 -- .../https-protocol-missing.md | 48 - .../insecure-allow-origin.md | 51 - .../typescript-express/insecure-cookie.md | 61 -- .../typescript-express/jwt-not-revoked.md | 60 -- .../typescript-express/missing-helmet.md | 53 - .../typescript-express/path-traversal.md | 57 -- .../reduce-server-fingerprinting.md | 66 -- .../typescript-express/xss-vulnerability.md | 45 - .../rules/typescript-inclusive/comments.md | 47 - .../typescript-inclusive/declarations.md | 50 - .../typescript-inclusive/formal-parameters.md | 42 - .../rules/typescript-inclusive/identifiers.md | 50 - .../rules/typescript-node-security/argon2.md | 38 - .../avoid-crypto-rc4.md | 32 - .../avoid-crypto-sha1.md | 32 - .../typescript-node-security/avoid-des.md | 34 - .../chmod-permissions.md | 42 - .../command-injection.md | 34 - .../crypto-avoid-weak-hash.md | 33 - .../detect-buffer-noassert.md | 115 --- .../detect-child-process.md | 119 --- .../detect-eval-with-expression.md | 42 - .../detect-new-buffer.md | 34 - .../detect-non-literal-fs-filename.md | 149 --- .../detect-non-literal-regexp.md | 36 - .../detect-non-literal-require.md | 42 - .../detected-jwt-token.md | 38 - .../hardcoded-hmac-key.md | 47 - .../typescript-node-security/insecure-hash.md | 38 - .../insecure-jwt-secret-usage.md | 54 - .../jwt-hardcoded-secret.md | 40 - .../jwt-sensitive-data.md | 40 - .../jwt-weak-encryption.md | 35 - .../log-sensitive-data.md | 44 - .../oauth2-hardcoded-secret.md | 56 -- .../typescript-node-security/sql-injection.md | 276 ----- .../py/build/configurations/pull_config.yaml | 10 +- .../configurations/pull_config_preview.yaml | 12 +- 407 files changed, 22 insertions(+), 24913 deletions(-) rename content/en/{ => continuous_integration}/dora_metrics/_index.md (99%) rename content/en/{ => continuous_integration}/quality_gates/_index.md (99%) rename content/en/{ => continuous_integration}/static_analysis/_index.md (99%) rename content/en/{ => continuous_integration}/static_analysis/rules/_index.md (99%) delete mode 100644 content/en/static_analysis/circleci_orbs.md delete mode 100644 content/en/static_analysis/github_actions.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/avoid-http.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/no-root-user.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/tag-image-version.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/yum-use-y.md delete mode 100644 content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/for-direction.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/new-parens.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-alert.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-caller.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-console.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-debugger.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-empty.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-iterator.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-octal.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-proto.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-script-url.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/no-with.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/require-yield.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/use-isnan.md delete mode 100644 content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md delete mode 100644 content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/assignment-name.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/class-name.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/eqeqeq.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/func-name-matching.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/func-names.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/function-naming.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/max-class-lines.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/max-function-lines.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/max-params.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/method-name.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-div-regex.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-new-func.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-new-object.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-new.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-return-assign.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-self-compare.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/no-var.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/parameter-name.md delete mode 100644 content/en/static_analysis/rules/javascript-code-style/radix.md delete mode 100644 content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md delete mode 100644 content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md delete mode 100644 content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md delete mode 100644 content/en/static_analysis/rules/javascript-express/access-restriction.md delete mode 100644 content/en/static_analysis/rules/javascript-express/default-session-config.md delete mode 100644 content/en/static_analysis/rules/javascript-express/external-filename-upload.md delete mode 100644 content/en/static_analysis/rules/javascript-express/external-resource.md delete mode 100644 content/en/static_analysis/rules/javascript-express/hardcoded-secret.md delete mode 100644 content/en/static_analysis/rules/javascript-express/https-protocol-missing.md delete mode 100644 content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md delete mode 100644 content/en/static_analysis/rules/javascript-express/insecure-cookie.md delete mode 100644 content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md delete mode 100644 content/en/static_analysis/rules/javascript-express/missing-helmet.md delete mode 100644 content/en/static_analysis/rules/javascript-express/path-traversal.md delete mode 100644 content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md delete mode 100644 content/en/static_analysis/rules/javascript-express/xss-vulnerability.md delete mode 100644 content/en/static_analysis/rules/javascript-inclusive/comments.md delete mode 100644 content/en/static_analysis/rules/javascript-inclusive/declarations.md delete mode 100644 content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md delete mode 100644 content/en/static_analysis/rules/javascript-inclusive/identifiers.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/argon2.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/avoid-des.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/command-injection.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-child-process.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/insecure-hash.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/sql-injection.md delete mode 100644 content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md delete mode 100644 content/en/static_analysis/rules/jsx-react/jsx-key.md delete mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md delete mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md delete mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md delete mode 100644 content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md delete mode 100644 content/en/static_analysis/rules/jsx-react/no-children-prop.md delete mode 100644 content/en/static_analysis/rules/jsx-react/no-danger-with-children.md delete mode 100644 content/en/static_analysis/rules/jsx-react/no-deprecated.md delete mode 100644 content/en/static_analysis/rules/jsx-react/no-render-return-value.md delete mode 100644 content/en/static_analysis/rules/jsx-react/no-string-refs.md delete mode 100644 content/en/static_analysis/rules/jsx-react/require-render-return.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/any-type-disallow.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/argument-same-name.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/condition-similar-block.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/equal-basic-types.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/exception-inherit.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/function-already-exists.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/generic-exception-last.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/get-set-arguments.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/if-return-no-else.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/import-modules-twice.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/import-single-module.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/init-call-parent.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/init-method-required.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/init-no-return-value.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/logging-no-format.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/method-hidden.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/nested-blocks.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-assert.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-bare-except.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-bare-raise.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-base-exception.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-datetime-today.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-double-not.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-equal-unary.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-exit.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-generic-exception.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-if-true.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/no-silent-exception.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/open-add-flag.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/return-outside-function.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/self-assignment.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/static-method-no-self.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/too-many-while.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/unreachable-code.md delete mode 100644 content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md delete mode 100644 content/en/static_analysis/rules/python-code-style/assignment-names.md delete mode 100644 content/en/static_analysis/rules/python-code-style/class-name.md delete mode 100644 content/en/static_analysis/rules/python-code-style/function-naming.md delete mode 100644 content/en/static_analysis/rules/python-code-style/max-class-lines.md delete mode 100644 content/en/static_analysis/rules/python-code-style/max-function-lines.md delete mode 100644 content/en/static_analysis/rules/python-design/function-too-long.md delete mode 100644 content/en/static_analysis/rules/python-django/http-response-from-request.md delete mode 100644 content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md delete mode 100644 content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md delete mode 100644 content/en/static_analysis/rules/python-django/model-charfield-max-length.md delete mode 100644 content/en/static_analysis/rules/python-django/model-help-text.md delete mode 100644 content/en/static_analysis/rules/python-django/no-null-boolean.md delete mode 100644 content/en/static_analysis/rules/python-django/no-unicode-on-models.md delete mode 100644 content/en/static_analysis/rules/python-django/open-filename-from-request.md delete mode 100644 content/en/static_analysis/rules/python-django/os-system-from-request.md delete mode 100644 content/en/static_analysis/rules/python-django/subprocess-from-request.md delete mode 100644 content/en/static_analysis/rules/python-django/use-convenience-imports.md delete mode 100644 content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md delete mode 100644 content/en/static_analysis/rules/python-flask/html-format-from-user-input.md delete mode 100644 content/en/static_analysis/rules/python-flask/listen-all-interfaces.md delete mode 100644 content/en/static_analysis/rules/python-flask/no-render-template-string.md delete mode 100644 content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md delete mode 100644 content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md delete mode 100644 content/en/static_analysis/rules/python-flask/secure-cookie.md delete mode 100644 content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md delete mode 100644 content/en/static_analysis/rules/python-flask/ssrf-requests.md delete mode 100644 content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md delete mode 100644 content/en/static_analysis/rules/python-flask/use-jsonify.md delete mode 100644 content/en/static_analysis/rules/python-inclusive/comments.md delete mode 100644 content/en/static_analysis/rules/python-inclusive/function-definition.md delete mode 100644 content/en/static_analysis/rules/python-inclusive/variable-name.md delete mode 100644 content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md delete mode 100644 content/en/static_analysis/rules/python-pandas/avoid-inplace.md delete mode 100644 content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md delete mode 100644 content/en/static_analysis/rules/python-pandas/import-as-pd.md delete mode 100644 content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md delete mode 100644 content/en/static_analysis/rules/python-pandas/loc-not-ix.md delete mode 100644 content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md delete mode 100644 content/en/static_analysis/rules/python-pandas/pivot-table.md delete mode 100644 content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md delete mode 100644 content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md delete mode 100644 content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md delete mode 100644 content/en/static_analysis/rules/python-security/avoid-random.md delete mode 100644 content/en/static_analysis/rules/python-security/aws-boto-credentials.md delete mode 100644 content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md delete mode 100644 content/en/static_analysis/rules/python-security/file-write-others.md delete mode 100644 content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md delete mode 100644 content/en/static_analysis/rules/python-security/html-string-from-parameters.md delete mode 100644 content/en/static_analysis/rules/python-security/insecure-hash-functions.md delete mode 100644 content/en/static_analysis/rules/python-security/insecure-jwt.md delete mode 100644 content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md delete mode 100644 content/en/static_analysis/rules/python-security/jinja-autoescape.md delete mode 100644 content/en/static_analysis/rules/python-security/mktemp.md delete mode 100644 content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md delete mode 100644 content/en/static_analysis/rules/python-security/no-eval.md delete mode 100644 content/en/static_analysis/rules/python-security/os-spawn.md delete mode 100644 content/en/static_analysis/rules/python-security/os-system.md delete mode 100644 content/en/static_analysis/rules/python-security/request-verify.md delete mode 100644 content/en/static_analysis/rules/python-security/requests-http.md delete mode 100644 content/en/static_analysis/rules/python-security/requests-timeout.md delete mode 100644 content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md delete mode 100644 content/en/static_analysis/rules/python-security/sql-server-security-credentials.md delete mode 100644 content/en/static_analysis/rules/python-security/ssl-unverified-context.md delete mode 100644 content/en/static_analysis/rules/python-security/subprocess-shell-true.md delete mode 100644 content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md delete mode 100644 content/en/static_analysis/rules/python-security/yaml-load.md delete mode 100644 content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md delete mode 100644 content/en/static_analysis/rules/tsx-react/no-children-prop.md delete mode 100644 content/en/static_analysis/rules/tsx-react/no-danger-with-children.md delete mode 100644 content/en/static_analysis/rules/tsx-react/no-deprecated.md delete mode 100644 content/en/static_analysis/rules/tsx-react/no-render-return-value.md delete mode 100644 content/en/static_analysis/rules/tsx-react/no-string-refs.md delete mode 100644 content/en/static_analysis/rules/tsx-react/require-render-return.md delete mode 100644 content/en/static_analysis/rules/tsx-react/tsx-key.md delete mode 100644 content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md delete mode 100644 content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/ban-types.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/for-direction.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/new-parens.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-alert.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-caller.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-console.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-debugger.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-empty.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-iterator.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-namespace.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-proto.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-script-url.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/require-yield.md delete mode 100644 content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md delete mode 100644 content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/array-type.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/assignment-name.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/class-name.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/eqeqeq.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/func-name-matching.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/func-names.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/function-naming.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/max-class-lines.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/max-function-lines.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/max-params.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/method-name.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-div-regex.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-new-func.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-new-object.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-new.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-return-assign.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-self-compare.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/no-var.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/parameter-name.md delete mode 100644 content/en/static_analysis/rules/typescript-code-style/radix.md delete mode 100644 content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md delete mode 100644 content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md delete mode 100644 content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md delete mode 100644 content/en/static_analysis/rules/typescript-express/access-restriction.md delete mode 100644 content/en/static_analysis/rules/typescript-express/default-session-config.md delete mode 100644 content/en/static_analysis/rules/typescript-express/external-filename-upload.md delete mode 100644 content/en/static_analysis/rules/typescript-express/external-resource.md delete mode 100644 content/en/static_analysis/rules/typescript-express/hardcoded-secret.md delete mode 100644 content/en/static_analysis/rules/typescript-express/https-protocol-missing.md delete mode 100644 content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md delete mode 100644 content/en/static_analysis/rules/typescript-express/insecure-cookie.md delete mode 100644 content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md delete mode 100644 content/en/static_analysis/rules/typescript-express/missing-helmet.md delete mode 100644 content/en/static_analysis/rules/typescript-express/path-traversal.md delete mode 100644 content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md delete mode 100644 content/en/static_analysis/rules/typescript-express/xss-vulnerability.md delete mode 100644 content/en/static_analysis/rules/typescript-inclusive/comments.md delete mode 100644 content/en/static_analysis/rules/typescript-inclusive/declarations.md delete mode 100644 content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md delete mode 100644 content/en/static_analysis/rules/typescript-inclusive/identifiers.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/argon2.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/avoid-des.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/command-injection.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-child-process.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/insecure-hash.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md delete mode 100644 content/en/static_analysis/rules/typescript-node-security/sql-injection.md diff --git a/config/_default/menus/menus.en.yaml b/config/_default/menus/menus.en.yaml index dea51276097e8..4d3311bec3fea 100644 --- a/config/_default/menus/menus.en.yaml +++ b/config/_default/menus/menus.en.yaml @@ -2617,37 +2617,37 @@ main: parent: cd_explorer weight: 303 - name: DORA Metrics - url: dora_metrics/ + url: continuous_integration/dora_metrics/ pre: ci parent: software_delivery_heading - identifier: dora_metrics + identifier: ci_explorer_dora_metrics weight: 170000 - name: Static Analysis - url: static_analysis/ + url: continuous_integration/static_analysis/ pre: ci parent: software_delivery_heading - identifier: static_analysis + identifier: ci_static_analysis weight: 180000 - name: Rules - url: static_analysis/rules - parent: static_analysis - identifier: static_analysis_rules + url: continuous_integration/static_analysis/rules + parent: ci_static_analysis + identifier: ci_static_analysis_rules weight: 101 - name: CircleCI Orbs - url: static_analysis/circleci_orbs - parent: static_analysis - identifier: static_analysis_circleci_orbs + url: continuous_integration/static_analysis/circleci_orbs + parent: ci_static_analysis + identifier: ci_static_analysis_circleci_orbs weight: 102 - name: GitHub Actions - url: static_analysis/github_actions - parent: static_analysis - identifier: static_analysis_github_actions + url: continuous_integration/static_analysis/github_actions + parent: ci_static_analysis + identifier: ci_static_analysis_github_actions weight: 103 - name: Quality Gates - url: quality_gates/ + url: continuous_integration/quality_gates/ pre: ci parent: software_delivery_heading - identifier: quality_gates + identifier: ci_quality_gates weight: 190000 - name: Database Monitoring url: database_monitoring/ diff --git a/content/en/dora_metrics/_index.md b/content/en/continuous_integration/dora_metrics/_index.md similarity index 99% rename from content/en/dora_metrics/_index.md rename to content/en/continuous_integration/dora_metrics/_index.md index 739e7ca275289..f42d07df804a8 100644 --- a/content/en/dora_metrics/_index.md +++ b/content/en/continuous_integration/dora_metrics/_index.md @@ -2,8 +2,6 @@ title: DORA Metrics kind: documentation description: Learn how to use DORA metrics to improve and measure software development. -aliases: -- /continuous_integration/dora_metrics is_beta: true further_reading: - link: "/continuous_integration/tests" diff --git a/content/en/quality_gates/_index.md b/content/en/continuous_integration/quality_gates/_index.md similarity index 99% rename from content/en/quality_gates/_index.md rename to content/en/continuous_integration/quality_gates/_index.md index 4327a46fe5f47..38565d8a82fd4 100644 --- a/content/en/quality_gates/_index.md +++ b/content/en/continuous_integration/quality_gates/_index.md @@ -3,8 +3,6 @@ title: Quality Gates kind: documentation description: Learn how to use Quality Gates in your pipeline. is_beta: true -aliases: -- /continuous_integration/quality_gates further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/static_analysis/_index.md b/content/en/continuous_integration/static_analysis/_index.md similarity index 99% rename from content/en/static_analysis/_index.md rename to content/en/continuous_integration/static_analysis/_index.md index 240ce6b186216..0450f4664144e 100644 --- a/content/en/static_analysis/_index.md +++ b/content/en/continuous_integration/static_analysis/_index.md @@ -2,8 +2,6 @@ title: Static Analysis kind: documentation description: Learn about Datadog Static Analysis to scan code for quality issues and security vulnerabilities before your code reaches production. -aliases: -- /continuous_integration/static_analysis/ is_beta: true further_reading: - link: "https://www.datadoghq.com/blog/monitor-ci-pipelines/" diff --git a/content/en/static_analysis/rules/_index.md b/content/en/continuous_integration/static_analysis/rules/_index.md similarity index 99% rename from content/en/static_analysis/rules/_index.md rename to content/en/continuous_integration/static_analysis/rules/_index.md index e9adda4145101..ccfc294a23faa 100644 --- a/content/en/static_analysis/rules/_index.md +++ b/content/en/continuous_integration/static_analysis/rules/_index.md @@ -3,8 +3,6 @@ title: Static Analysis Rules kind: documentation description: View rules for multiple languages for Static Analysis. is_beta: true -aliases: -- /continuous_integration/static_analysis/rules docker_best_practices_data: - link: "/continuous_integration/static_analysis/rules/docker-best-practices/absolute-workdir" tag: "absolute-workdir" diff --git a/content/en/static_analysis/circleci_orbs.md b/content/en/static_analysis/circleci_orbs.md deleted file mode 100644 index 007a018ac3942..0000000000000 --- a/content/en/static_analysis/circleci_orbs.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -aliases: -- /continuous_integration/static_analysis/circleci_orbs -dependencies: -- https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md -description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. -kind: documentation -title: Static Analysis and CircleCI Orbs ---- -[![CircleCI Build Status](https://circleci.com/gh/DataDog/datadog-static-analyzer-circleci-orb.svg?style=shield "CircleCI Build Status")](https://circleci.com/gh/DataDog/datadog-static-analyzer-circleci-orb) [![CircleCI Orb Version](https://badges.circleci.com/orbs/DataDog/datadog-static-analyzer-circleci-orb.svg)](https://circleci.com/developer/orbs/orb/DataDog/datadog-static-analyzer-circleci-orb) [![GitHub License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/DataDog/datadog-static-analyzer-circleci-orb/main/LICENSE) [![CircleCI Community](https://img.shields.io/badge/community-CircleCI%20Discuss-343434.svg)](https://discuss.circleci.com/c/ecosystem/orbs) - - -Run a Datadog Static Analysis in your CircleCI workflows. - -## Requirements - -To use the Datadog static analyzer, you need to add a `static-analysis.datadog.yml` file to your repositories root directory that specifies what rulesets to use. - -```yaml -rulesets: - - - - -``` - -#### Example for Python - -You can see an example for repositories based on Python: - -```yaml -rulesets: - - python-security - - python-code-style - - python-best-practices -``` - -## Workflow - -Create a file in `.circleci` to run a Datadog static analysis. - -Here's a sample workflow file. - -```yaml -version: 2.1 -orbs: - datadog-static-analysis: datadog/datadog-static-analyzer-circleci-orb@1.0.0 -jobs: - run-static-analysis-job: - docker: - - image: cimg/node:current - steps: - - checkout - - datadog-static-analysis/analyze: - service: my-service -workflows: - main: - jobs: - - run-static-analysis-job -``` - -## Environment Variables - -These environment variables should be set in the [CircleCI Project Settings](https://circleci.com/docs/set-environment-variable/#set-an-environment-variable-in-a-project) page. - -| Name | Description | Required | Default | -|--------------|----------------------------------------------------------------------------------------------------------------------------|----------|-----------------| -| `DD_API_KEY` | Your Datadog API key. This key is created by your [Datadog organization](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys) and should be stored as a secret. | True | | -| `DD_APP_KEY` | Your Datadog Application key. This key is created by your [Datadog organization](https://docs.datadoghq.com/account_management/api-app-keys/) and should be stored as a secret. | True | | - -## Inputs - -To customize your workflow, you can set the following parameters for an analysis. - -| Name | Description | Required | Default | -|--------------|----------------------------------------------------------------------------------------------------------------------------|----------|-----------------| -| `service` | The service you want your results tagged with. | True | | -| `env` | The environment you want your results tagged with. | False | `none` | -| `site` | The [Datadog site](https://docs.datadoghq.com/getting_started/site/) | False | `datadoghq.com` | - -## Resources - -[CircleCI Orb Registry Page](https://circleci.com/developer/orbs/orb/DataDog/datadog-static-analyzer-circleci-orb) - The official registry page of this orb for all versions, executors, commands, and jobs described. - -[CircleCI Orb Docs](https://circleci.com/docs/orb-intro/#section=configuration) - Docs for using, creating, and publishing CircleCI Orbs. - -### How to Contribute - -We welcome [issues](https://github.com/DataDog/datadog-static-analyzer-circleci-orb/issues) to and [pull requests](https://github.com/DataDog/datadog-static-analyzer-circleci-orb/pulls) against this repository! - -### How to Publish An Update -1. Merge pull requests with desired changes to the main branch. - - For the best experience, squash-and-merge and use [Conventional Commit Messages](https://conventionalcommits.org/). -2. Find the current version of the orb. - - You can run `circleci orb info DataDog/datadog-static-analyzer-circleci-orb | grep "Latest"` to see the current version. -3. Create a [new Release](https://github.com/DataDog/datadog-static-analyzer-circleci-orb/releases/new) on GitHub. - - Click "Choose a tag" and _create_ a new [semantically versioned](http://semver.org/) tag. (ex: v1.0.0) - - We will have an opportunity to change this before we publish if needed after the next step. -4. Click _"+ Auto-generate release notes"_. - - This will create a summary of all of the merged pull requests since the previous release. - - If you have used _[Conventional Commit Messages](https://conventionalcommits.org/)_ it will be easy to determine what types of changes were made, allowing you to ensure the correct version tag is being published. -5. Now ensure the version tag selected is semantically accurate based on the changes included. -6. Click _"Publish Release"_. - - This will push a new tag and trigger your publishing pipeline on CircleCI. diff --git a/content/en/static_analysis/github_actions.md b/content/en/static_analysis/github_actions.md deleted file mode 100644 index b1f9479e235f7..0000000000000 --- a/content/en/static_analysis/github_actions.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -aliases: -- /continuous_integration/static_analysis/github_actions -dependencies: -- https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md -description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. -kind: documentation -title: Static Analysis and GitHub Actions ---- -Run a Datadog Static Analysis in your Github Action workflows. - -## Requirements - -To use the Datadog static analyzer, you need to add a `static-analysis.datadog.yml` file to your repositories root directory that specifies what rulesets to use. - -```yaml -rulesets: - - - - -``` - -#### Example for Python - -You can see an example for repositories based on Python: - -```yaml -rulesets: - - python-security - - python-code-style - - python-best-practices -``` - -## Workflow - -Create a file in `.github/workflows` to run a Datadog static analysis. - -Here's a sample workflow file. - -```yaml -on: [push] - -jobs: - check-quality: - runs-on: ubuntu-latest - name: Datadog Static Analyzer - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Check code meets quality standards - id: datadog-static-analysis - uses: DataDog/datadog-static-analyzer-github-action@v1.0.0 - with: - dd_app_key: ${{ secrets.DD_APP_KEY }} - dd_api_key: ${{ secrets.DD_API_KEY }} - dd_service: "my-service" - dd_env: "ci" -``` - -> You **must** set your Datadog API and Application Keys as secrets in your GitHub repository. For more information, see [API and Application Keys][1] - -## Inputs - -| Name | Description | Required | Default | -|--------------|----------------------------------------------------------------------------------------------------------------------------|----------|-----------------| -| `dd_api_key` | Your Datadog API key. This key is created by your [Datadog organization][1] and should be stored as a [secret][2]. | True | | -| `dd_app_key` | Your Datadog Application key. This key is created by your [Datadog organization][1] and should be stored as a [secret][2]. | True | | -| `dd_service` | The service you want your results tagged with. | True | | -| `dd_env` | The environment you want your results tagged with. | False | `none` | -| `dd_site` | The [Datadog site](https://docs.datadoghq.com/getting_started/site/) | False | `datadoghq.com` | - -[1]: https://docs.datadoghq.com/account_management/api-app-keys/ -[2]: https://docs.github.com/en/actions/security-guides/encrypted-secrets diff --git a/content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md b/content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md deleted file mode 100644 index 8f981943e644d..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/absolute-workdir.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/absolute-workdir - language: Docker - severity: Warning -title: Use absolute workdir ---- -## Metadata -**ID:** `docker-best-practices/absolute-workdir` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Best Practices - -## Description -When using a relative `WORKDIR`, you may run into problems since you are dependent on previous `WORKDIR` instructions. Using an absolute `WORKDIR` ensures you have the right path no matter where the instruction is positioned. - -## Non-Compliant Code Examples -```docker -FROM busybox -WORKDIR usr/src/app -``` - -## Compliant Code Examples -```docker -FROM busybox -WORKDIR /usr/src/app -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md b/content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md deleted file mode 100644 index e7018d2630c49..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/alias-must-be-unique.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: docker-best-practices/alias-must-be-unique - language: Docker - severity: Warning -title: FROM aliases must be unique ---- -## Metadata -**ID:** `docker-best-practices/alias-must-be-unique` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Error Prone - -## Description -When using multiple images in a Dockerfile, aliases must be unique. - -## Non-Compliant Code Examples -```docker -FROM awesomeimage:version as build -RUN stuff -FROM otherawesomeimage:version1 as foobar -RUN plop -FROM otherawesomeimage:version2 as build -RUN more_stuff -``` - -## Compliant Code Examples -```docker -FROM awesomeimage:version as build -RUN stuff -FROM otherawesomeimage:version as another-alias -RUN more_stuff -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md b/content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md deleted file mode 100644 index e480e382d3737..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/apt-get-yes.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/apt-get-yes - language: Docker - severity: Warning -title: Always use -y with apt-get install ---- -## Metadata -**ID:** `docker-best-practices/apt-get-yes` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Best Practices - -## Description -When using `apt-get` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. - -## Non-Compliant Code Examples -```docker -RUN apt-get install gcc -``` - -## Compliant Code Examples -```docker -RUN apt-get install -y gcc -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md b/content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md deleted file mode 100644 index 81f0c7e55de5f..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/apt-pin-version.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/apt-pin-version - language: Docker - severity: Notice -title: Always pin versions in apt-get install ---- -## Metadata -**ID:** `docker-best-practices/apt-pin-version` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When using `apt-get install`, pin the version to avoid unwanted upgrades and undefined behavior. - -## Non-Compliant Code Examples -```docker -FROM busybox -RUN apt-get install python - -RUN apt-get update && \ - apt-get install -y --no-install-recommends openjdk-19-jdk && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/ /var/cache/oracle* -``` - -## Compliant Code Examples -```docker -FROM busybox -RUN apt-get install python=3.11 -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md b/content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md deleted file mode 100644 index 98c1c70e284e6..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/avoid-chmod-777.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: docker-best-practices/avoid-chmod-777 - language: Docker - severity: Warning -title: Do not give wide permissions on files ---- -## Metadata -**ID:** `docker-best-practices/avoid-chmod-777` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Security - -## Description -Make sure you do not give too many permissions with copying or adding a file. Adding write permissions to all means that any other users may modify the files. - - -## Non-Compliant Code Examples -```docker -ADD --chmod=777 src dst -COPY --chmod=777 src dst -``` - -## Compliant Code Examples -```docker -ADD --chmod=755 src dst -COPY --chmod=755 src dst -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md b/content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md deleted file mode 100644 index 25841be370916..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/avoid-commands-not-relevant - language: Docker - severity: Notice -title: Avoid commands not made for containers ---- -## Metadata -**ID:** `docker-best-practices/avoid-commands-not-relevant` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Some commands do not make sense to use when building a container. They require user inputs which cannot work when building a container. Avoid such commands in a Dockerfile. - -## Non-Compliant Code Examples -```docker -FROM busybox -RUN top -RUN vim -``` - -## Compliant Code Examples -```docker -FROM busybox -RUN mycommand foo bar -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/avoid-http.md b/content/en/static_analysis/rules/docker-best-practices/avoid-http.md deleted file mode 100644 index de00969599157..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/avoid-http.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: docker-best-practices/avoid-http - language: Docker - severity: Warning -title: Avoid fetching data from HTTP endpoint ---- -## Metadata -**ID:** `docker-best-practices/avoid-http` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Security - -## Description -Always use `https` links instead of `http`. Do not use clear-text protocols as they lack encryption and authentication. - -## Non-Compliant Code Examples -```docker -RUN cd /tmp && wget http://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml -RUN cd /tmp && curl -O http://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml -RUN foobar http://domain.tld -``` - -## Compliant Code Examples -```docker -RUN cd /tmp && wget https://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml -RUN cd /tmp && curl -O https://www.scalastyle.org/scalastyle_config.xml && mv scalastyle_config.xml /scalastyle_config.xml -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md b/content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md deleted file mode 100644 index 104adda55229b..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/dnf-use-y.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/dnf-use-y - language: Docker - severity: Warning -title: Always use -y with dnf install ---- -## Metadata -**ID:** `docker-best-practices/dnf-use-y` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Best Practices - -## Description -When using `dnf` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. - -## Non-Compliant Code Examples -```docker -RUN dnf install httpd-2.4.46 -``` - -## Compliant Code Examples -```docker -RUN dnf install -y httpd-2.4.46 -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md b/content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md deleted file mode 100644 index 94d6915897364..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/expose-admin-ports.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: docker-best-practices/expose-admin-ports - language: Docker - severity: Warning -title: Do not expose sensitive ports ---- -## Metadata -**ID:** `docker-best-practices/expose-admin-ports` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Security - -## Description -Never expose admin ports such as the SSH port `22` in your container. It increases the surface of attack of your containers. - -## Non-Compliant Code Examples -```docker -FROM debian:jessie -EXPOSE 22 -``` - -## Compliant Code Examples -```docker -FROM debian:jessie -EXPOSE 443 -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md b/content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md deleted file mode 100644 index 07a6909ebee0b..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/expose-valid-port.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/expose-valid-port - language: Docker - severity: Notice -title: Expose a valid UNIX port number ---- -## Metadata -**ID:** `docker-best-practices/expose-valid-port` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -The `EXPOSE` instruction should take a valid UNIX port range. - -## Non-Compliant Code Examples -```docker -EXPOSE 1001232323 -``` - -## Compliant Code Examples -```docker -EXPOSE 8080 -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md b/content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md deleted file mode 100644 index f6e771e2412fa..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/image-avoid-digest.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: docker-best-practices/image-avoid-digest - language: Docker - severity: Warning -title: Do not use the digest to pull an image ---- -## Metadata -**ID:** `docker-best-practices/image-avoid-digest` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Security - -## Description -Do not use a digest to pull an image. A digest is immutable and if a vulnerability is found in this image, your container is likely to be impacted. - -A tag is mutable and any security fixes are applied when you rebuild the image. - -## Non-Compliant Code Examples -```docker -FROM image@sha256:239898ab989898 -``` - -## Compliant Code Examples -```docker -FROM image:tag -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md b/content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md deleted file mode 100644 index 80c94131ae61a..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/maintainer-deprecated.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/maintainer-deprecated - language: Docker - severity: Notice -title: The maintainer entry is deprecated ---- -## Metadata -**ID:** `docker-best-practices/maintainer-deprecated` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Use `LABEL` instead of `MAINTAINER` to report the maintainer of a Dockerfile. - -## Non-Compliant Code Examples -```docker -MAINTAINER Jean Bar -``` - -## Compliant Code Examples -```docker -LABEL maintainer="Jean Bar " -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md b/content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md deleted file mode 100644 index f53ea2bdb3efe..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/multiple-cmd.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/multiple-cmd - language: Docker - severity: Notice -title: Do not use multiple CMD ---- -## Metadata -**ID:** `docker-best-practices/multiple-cmd` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not use multiple `CMD` instructions, only the last one is used. - -## Non-Compliant Code Examples -```docker -FROM awesomeimage -CMD run_server1 -CMD run_server2 -``` - -## Compliant Code Examples -```docker -FROM awesomeimage -CMD run_server -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md b/content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md deleted file mode 100644 index 665bcf0376144..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/multiple-entrypoint.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/multiple-entrypoint - language: Docker - severity: Notice -title: Do not use multiple CMD ---- -## Metadata -**ID:** `docker-best-practices/multiple-entrypoint` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not use multiple `ENTRYPOINT` instructions, only the last one is used. - -## Non-Compliant Code Examples -```docker -FROM awesomeimage -ENTRYPOINT /foo/bar -ENTRYPOINT /foo/baz -``` - -## Compliant Code Examples -```docker -FROM awesomeimage -ENTRYPOINT /foo/bar -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md b/content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md deleted file mode 100644 index 97931d0920d1c..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/multiple-healthcheck.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/multiple-healthcheck - language: Docker - severity: Notice -title: Do not use multiple HEALTHCHECK ---- -## Metadata -**ID:** `docker-best-practices/multiple-healthcheck` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -A Dockerfile with multiple `HEALTHCHECK` instructions is confusing. A container should only have one `HEALTHCHECK` instruction. - -## Non-Compliant Code Examples -```docker -HEALTHCHECK CMD foo -HEALTHCHECK CMD bar -``` - -## Compliant Code Examples -```docker -HEALTHCHECK CMD foo -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/no-root-user.md b/content/en/static_analysis/rules/docker-best-practices/no-root-user.md deleted file mode 100644 index 30db3fb8033ef..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/no-root-user.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: docker-best-practices/no-root-user - language: Docker - severity: Warning -title: Last user should not be root ---- -## Metadata -**ID:** `docker-best-practices/no-root-user` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Security - -## Description -Do not use `root` as the last user because your container runs with the `root` user. Always use a user with lower privileges. - -## Non-Compliant Code Examples -```docker -CMD foo -USER plop -CMD plip -USER root -``` - -## Compliant Code Examples -```docker -CMD foo -USER root -CMD plip -USER normaluser -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md b/content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md deleted file mode 100644 index 9bdf41e7eb8ba..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/pip-no-cache.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/pip-no-cache - language: Docker - severity: Notice -title: Do not use cache when installing packages ---- -## Metadata -**ID:** `docker-best-practices/pip-no-cache` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When installing Python packages with `pip`, always pin the version. - -## Non-Compliant Code Examples -```docker -FROM busybox -RUN pip install django -RUN pip3 install django -``` - -## Compliant Code Examples -```docker -FROM busybox -RUN pip install --no-cache-dir django -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md b/content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md deleted file mode 100644 index 5bcc0c791b869..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/pip-pin-versions.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/pip-pin-versions - language: Docker - severity: Notice -title: Always pin versions with pip ---- -## Metadata -**ID:** `docker-best-practices/pip-pin-versions` - -**Language:** Docker - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When installing Python packages with `pip`, always pin the version. - -## Non-Compliant Code Examples -```docker -FROM busybox -RUN pip install django -``` - -## Compliant Code Examples -```docker -FROM busybox -RUN pip install django==1.9 -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/tag-image-version.md b/content/en/static_analysis/rules/docker-best-practices/tag-image-version.md deleted file mode 100644 index a9226b9ac2723..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/tag-image-version.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/tag-image-version - language: Docker - severity: Warning -title: Always tag the version of an image ---- -## Metadata -**ID:** `docker-best-practices/tag-image-version` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Always tag the version of an image. You can never assume that `latest` is a specific version. - -## Non-Compliant Code Examples -```docker -FROM debian - -``` - -## Compliant Code Examples -```docker -FROM debian:unstable - -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/yum-use-y.md b/content/en/static_analysis/rules/docker-best-practices/yum-use-y.md deleted file mode 100644 index 2c18085d5f9f3..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/yum-use-y.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/yum-use-y - language: Docker - severity: Warning -title: Always use -y with yum install ---- -## Metadata -**ID:** `docker-best-practices/yum-use-y` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Best Practices - -## Description -When using `yum` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. - -## Non-Compliant Code Examples -```docker -RUN yum install gcc -``` - -## Compliant Code Examples -```docker -RUN yum install -y gcc -``` diff --git a/content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md b/content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md deleted file mode 100644 index 190ab34012f80..0000000000000 --- a/content/en/static_analysis/rules/docker-best-practices/zypper-use-y.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: docker-best-practices/zypper-use-y - language: Docker - severity: Warning -title: Always use -y with zypper install ---- -## Metadata -**ID:** `docker-best-practices/zypper-use-y` - -**Language:** Docker - -**Severity:** Warning - -**Category:** Best Practices - -## Description -When using `zypper` to install a package, make sure you use the `-y` flag to avoid your CI being blocked on a prompt. - - -## Non-Compliant Code Examples -```docker -RUN zypper install httpd-2.4.46 - -``` - -## Compliant Code Examples -```docker -RUN zypper install -y httpd-2.4.46 -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/for-direction.md b/content/en/static_analysis/rules/javascript-best-practices/for-direction.md deleted file mode 100644 index 734809e4cae1b..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/for-direction.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/for-direction - language: JavaScript - severity: Error -title: Check for loop is moving in the right direction ---- -## Metadata -**ID:** `javascript-best-practices/for-direction` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -This rule prevents you from creating conditions in which a `for` loop might end up in an infinite loop. If you need an infinite loop, use `while` statements. - -## Non-Compliant Code Examples -```javascript -// test if '++', '--' -for(var i = 0; i < 10; i--){} -for(var i = 0; i <= 10; i--){} -for(var i = 10; i > 10; i++){} -for(var i = 10; i >= 0; i++){} - -// test if '+=', '-=' -for(var i = 0; i < 10; i-=1){} -for(var i = 0; i <= 10; i-=1){} -for(var i = 10; i > 10; i+=1){} -for(var i = 10; i >= 0; i+=1){} -for(var i = 0; i < 10; i+=-1){} -for(var i = 0; i <= 10; i+=-1){} -for(var i = 10; i > 10; i-=-1){} -for(var i = 10; i >= 0; i-=-1){} -``` - -## Compliant Code Examples -```javascript -// test if '++', '--' -for(var i = 0; i < 10; i++){} -for(var i = 0; i <= 10; i++){} -for(var i = 10; i > 0; i--){} -for(var i = 10; i >= 0; i--){} - -// test if '+=', '-=', -for(var i = 0; i < 10; i+=1){} -for(var i = 0; i <= 10; i+=1){} -for(var i = 0; i < 10; i-=-1){} -for(var i = 0; i <= 10; i-=-1){} -for(var i = 10; i > 0; i-=1){} -for(var i = 10; i >= 0; i-=1){} -for(var i = 10; i > 0; i+=-1){} -for(var i = 10; i >= 0; i+=-1){} - -// test if no update. -for(var i = 10; i > 0;){} -for(var i = 10; i >= 0;){} -for(var i = 10; i < 0;){} -for(var i = 10; i <= 0;){} -for(var i = 10; i <= 0; j++){} -for(var i = 10; i <= 0; j--){} -for(var i = 10; i >= 0; j++){} -for(var i = 10; i >= 0; j--){} -for(var i = 10; i >= 0; j += 2){} -for(var i = 10; i >= 0; j -= 2){} -for(var i = 10; i >= 0; i |= 2){} -for(var i = 10; i >= 0; i %= 2){} -for(var i = 0; i < MAX; i += STEP_SIZE); -for(var i = 0; i < MAX; i -= STEP_SIZE); -for(var i = 10; i > 0; i += STEP_SIZE); - -// other cond-expressions. -for(var i = 0; i !== 10; i+=1){} -for(var i = 0; i === 10; i+=1){} -for(var i = 0; i == 10; i+=1){} -for(var i = 0; i != 10; i+=1){} -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/new-parens.md b/content/en/static_analysis/rules/javascript-best-practices/new-parens.md deleted file mode 100644 index 4303ee6366538..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/new-parens.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/new-parens - language: JavaScript - severity: Notice -title: Invoking a constructor must use parentheses ---- -## Metadata -**ID:** `javascript-best-practices/new-parens` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -This rule enforces the consistent use of parentheses in `new` statements. In JavaScript, you can omit parentheses when the constructor has no arguments, but you should always use them for consistency. - -## Non-Compliant Code Examples -```javascript -// Default (Always) -var a = new Date; -var a = new Date -var a = new (Date); -var a = new (Date) -var a = (new Date) - -// This `()` is `CallExpression`'s. This is a call of the result of `new Date`. -var a = (new Date)() -var a = new foo.Bar; -var a = (new Foo).bar; - -// Explicit always -var a = new Date; -var a = new foo.Bar; -var a = (new Foo).bar; -var a = new new Foo() - -// OPTION never not supported -// Never -// var a = new Date(); -// var a = new Date() -// var a = new (Date)(); -// var a = new (Date)() -// var a = (new Date()) -// var a = (new Date())() -// var a = new foo.Bar(); -// var a = (new Foo()).bar; -// var a = new new Foo() -``` - -## Compliant Code Examples -```javascript -// Default (Always) -var a = new Date(); -var a = new Date(function() {}); -var a = new (Date)(); -var a = new ((Date))(); -var a = (new Date()); -var a = new foo.Bar(); -var a = (new Foo()).bar; - -// Explicit Always -var a = new Date(); -var a = new foo.Bar(); -var a = (new Foo()).bar; - -// OPTION never not supported -// Never -// var a = new Date; -// var a = new Date(function() {}); -// var a = new (Date); -// var a = new ((Date)); -// var a = (new Date); -// var a = new foo.Bar; -// var a = (new Foo).bar; -// var a = new Person('Name') -// var a = new Person('Name', 12) -// var a = new ((Person))('Name'); -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-alert.md b/content/en/static_analysis/rules/javascript-best-practices/no-alert.md deleted file mode 100644 index 5b36eed55c703..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-alert.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-alert - language: JavaScript - severity: Notice -title: Avoid the use of alert, confirm, and prompt ---- -## Metadata -**ID:** `javascript-best-practices/no-alert` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -JavaScript’s `alert`, `confirm`, and `prompt` functions present obtrusive UI elements that prevent further user actions by taking control of the focus. These UI elements cannot be styled. - -## Non-Compliant Code Examples -```javascript -alert(foo) -window.alert(foo) -window['alert'](foo) -confirm(foo) -window.confirm(foo) -window['confirm'](foo) -prompt(foo) -window.prompt(foo) -window['prompt'](foo) -function alert() {} window.alert(foo) -var alert = function() {}; -window.alert(foo) -function foo(alert) { window.alert(); } -function foo() { alert(); } -function foo() { var alert = function() {}; } -alert(); -this.alert(foo) -this['alert'](foo) -function foo() { var window = bar; window.alert(); } -window.alert(); -globalThis['alert'](foo) -globalThis.alert(); -function foo() { var globalThis = bar; globalThis.alert(); } -globalThis.alert(); - -// Optional chaining -window?.alert(foo); -(window?.alert)(foo); -``` - -## Compliant Code Examples -```javascript -a[o.k](1) -foo.alert(foo) -foo.confirm(foo) -foo.prompt(foo) -// global overrides are not recommened -// and wont be supported by this rule -// function alert() {} alert(); -// var alert = function() {}; alert(); -// function foo() { var alert = bar; alert(); } -// function foo(alert) { alert(); } -// var alert = function() {}; function test() { alert(); } -// function foo() { var alert = function() {}; function test() { alert(); } } -// function confirm() {} confirm(); -// function prompt() {} prompt(); -window[alert](); -// function foo() { this.alert(); } -// function foo() { var window = bar; window.alert(); } -// globalThis.alert(); -// globalThis['alert'](); -// globalThis.alert(); -// var globalThis = foo; globalThis.alert(); -// function foo() { var globalThis = foo; globalThis.alert(); } -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md b/content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md deleted file mode 100644 index bdf1841a288da..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-async-promise-executor.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-async-promise-executor - language: JavaScript - severity: Error -title: Promise executor cannot be an async function ---- -## Metadata -**ID:** `javascript-best-practices/no-async-promise-executor` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -An async Promise executor won't surface exceptions if it fails. If you are already awaiting results in the executor, the Promise itself might not be required; please review your implementation. - -## Non-Compliant Code Examples -```javascript -new Promise(async function foo(resolve, reject) {}) -new Promise(async (resolve, reject) => {}) -``` - -## Compliant Code Examples -```javascript -new Promise((resolve, reject) => {}) -new Promise((resolve, reject) => {}, async function unrelated() {}) -new Foo(async (resolve, reject) => {}) -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-caller.md b/content/en/static_analysis/rules/javascript-best-practices/no-caller.md deleted file mode 100644 index c7b9ba4426da9..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-caller.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-best-practices/no-caller - language: JavaScript - severity: Warning -title: Avoid the use of arguments.caller or arguments.callee ---- -## Metadata -**ID:** `javascript-best-practices/no-caller` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -`arguments.caller` and `arguments.callee` has been deprecated and forbidden in ECMAScript 5 strict mode. - -## Non-Compliant Code Examples -```javascript -var x = arguments.callee; -var x = arguments.caller; -``` - -## Compliant Code Examples -```javascript -var x = arguments.length -var x = arguments -var x = arguments[0] -var x = arguments[caller] -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md b/content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md deleted file mode 100644 index 688c2c6423002..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-case-declarations.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-case-declarations - language: JavaScript - severity: Warning -title: Avoid lexical declarations in case clauses ---- -## Metadata -**ID:** `javascript-best-practices/no-case-declarations` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Lexical declaration in switch cases are leaked throughout all other cases, which is undesired behavior. Scope your lexical declarations using `{}`. - -## Non-Compliant Code Examples -```javascript -switch (a) { - case 1: - {} - function f() {} - break; -} -switch (a) { - case 1: - case 2: - let x; -} -switch (a) { case 1: let x = 1; break; } -switch (a) { default: let x = 2; break; } -switch (a) { case 1: const x = 1; break; } -switch (a) { default: const x = 2; break; } -switch (a) { case 1: function f() {} break; } -switch (a) { default: function f() {} break; } -switch (a) { case 1: class C {} break; } -switch (a) { default: class C {} break; } -``` - -## Compliant Code Examples -```javascript -switch (a) { case 1: { let x = 1; break; } default: { let x = 2; break; } } -switch (a) { case 1: { const x = 1; break; } default: { const x = 2; break; } } -switch (a) { case 1: { function f() {} break; } default: { function f() {} break; } } -switch (a) { case 1: { class C {} break; } default: { class C {} break; } } -switch (a) { - case 1: - case 2: {} -} -switch (a) { - case 1: var x; -} -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md b/content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md deleted file mode 100644 index 5db0ee0786c26..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-compare-neg-zero.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-compare-neg-zero - language: JavaScript - severity: Error -title: Direct comparison with -0 detected ---- -## Metadata -**ID:** `javascript-best-practices/no-compare-neg-zero` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -In JavaScript, `-0` and `+0` are considered to be equal (`(-0 === +0) // true`). However, they behave differently in some operations. For instance, `1/-0` results in `-Infinity`, while `1/+0` results in `+Infinity`. Directly comparing with `-0` can produce results that are hard to understand, and may lead to bugs. - -## Non-Compliant Code Examples -```javascript -x === -0; --0 === x; -x == -0; --0 == x; -x > -0; --0 > x; -x >= -0; --0 >= x; -x < -0; --0 < x; -x <= -0; --0 <= x; -``` - -## Compliant Code Examples -```javascript -x === 0 -0 === x -x == 0 -0 == x -x === '0' -'0' === x -x == '0' -'0' == x -x === '-0' -'-0' === x -x == '-0' -'-0' == x -x === -1 --1 === x -x < 0 -0 < x -x <= 0 -0 <= x -x > 0 -0 > x -x >= 0 -0 >= x -x != 0 -0 != x -x !== 0 -0 !== x -Object.is(x, -0) -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md b/content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md deleted file mode 100644 index d1908d2e3421f..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-cond-assign.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-cond-assign - language: JavaScript - severity: Error -title: Avoid assignment operators in conditional expressions ---- -## Metadata -**ID:** `javascript-best-practices/no-cond-assign` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -While there might be valid reasons to use an assignment operation in a condition, it is very easy to mistake `=` with the more usual intended `==`. This rule prevents such mistakes, as it is easier to intentionally disable the rule than identify the error. - -## Non-Compliant Code Examples -```javascript -var x; if (x = 0) { var b = 1; } -var x; while (x = 0) { var b = 1; } -var x = 0, y; do { y = x; } while (x = x + 1); -var x; for(; x+=1 ;){}; -var x; if ((x) = (0)); -if (someNode || (someNode = parentNode)) { } -if (someNode || (someNode = parentNode)) { } -while (someNode || (someNode = parentNode)) { } -do { } while (someNode || (someNode = parentNode)); -for (; typeof l === 'undefined' ? (l = 0) : l; i++) { } -if (x = 0) { } -while (x = 0) { } -do { } while (x = x + 1); -for(; x = y; ) { } -var x; var b = (x = 0) ? 1 : 0; -var x; var b = x && (y = 0) ? 1 : 0; -(((3496.29)).bkufyydt = 2e308) ? foo : bar; - - -if ((someNode = someNode.parentNode) !== null) { } -if ((someNode = someNode.parentNode) !== null) { } -if (someNode || (someNode = parentNode)) { } -while (someNode || (someNode = parentNode)) { } -do { } while (someNode || (someNode = parentNode)); -for (;someNode || (someNode = parentNode);); -``` - -## Compliant Code Examples -```javascript -var x = 0; if (x == 0) { var b = 1; } -var x = 0; if (x == 0) { var b = 1; } -var x = 5; while (x < 5) { x = x + 1; } -if ((a = b)); -while ((a = b)); -do {} while ((a = b)); -for (;(a = b);); -for (;;) {} -if ((function(node) { return node = parentNode; })(someNode)) { } -if ((function(node) { return node = parentNode; })(someNode)) { } -if ((node => node = parentNode)(someNode)) { } -if ((node => node = parentNode)(someNode)) { } -if (function(node) { return node = parentNode; }) { } -if (function(node) { return node = parentNode; }) { } -x = 0; -var x; var b = (x === 0) ? 1 : 0; -switch (foo) { case a = b: bar(); } -switch (foo) { case a = b: bar(); } -switch (foo) { case baz + (a = b): bar(); } -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-console.md b/content/en/static_analysis/rules/javascript-best-practices/no-console.md deleted file mode 100644 index 944a7d8e7981e..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-console.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-console - language: JavaScript - severity: Warning -title: Avoid leaving console debug statements ---- -## Metadata -**ID:** `javascript-best-practices/no-console` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Debugging with `console` is not considered a bad practice, but it's easy to forget about `console` statements and leave them in production code. There is no need to pollute production builds with debugging statements. - -## Non-Compliant Code Examples -```javascript -console.log(foo) -console.error(foo) -console.info(foo) -console.warn(foo) -``` - -## Compliant Code Examples -```javascript -Console.info(foo) -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-debugger.md b/content/en/static_analysis/rules/javascript-best-practices/no-debugger.md deleted file mode 100644 index 0b4a81ef104c6..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-debugger.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-debugger - language: JavaScript - severity: Error -title: Disallow the use of debugger ---- -## Metadata -**ID:** `javascript-best-practices/no-debugger` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -The `debugger` statement is used to intentionally stop execution and start debugging at the point where the statement appears in the code. While it can be valuable during development and debugging, it can cause unwanted behaviors if it's present in production code. - -## Non-Compliant Code Examples -```javascript -if (foo) debugger -``` - -## Compliant Code Examples -```javascript -var test = { debugger: 1 }; test.debugger; -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md b/content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md deleted file mode 100644 index c3286a917ed1f..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-delete-var.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-delete-var - language: JavaScript - severity: Error -title: Avoid using delete on variables directly ---- -## Metadata -**ID:** `javascript-best-practices/no-delete-var` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -The `delete` operator is designed to remove properties from objects in JavaScript. When used correctly, it can help manage object properties. However, using the `delete` operator on anything other than object properties can lead to unpredictable behavior. - -## Non-Compliant Code Examples -```javascript -delete x -``` - -## Compliant Code Examples -```javascript -delete x.prop; -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md deleted file mode 100644 index 0b83288170b2c..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-args.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-dupe-args - language: JavaScript - severity: Error -title: Function parameters redeclared ---- -## Metadata -**ID:** `javascript-best-practices/no-dupe-args` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -In JavaScript, it's syntactically valid to define multiple parameters with the same name in a function definition. However, doing so is considered bad practice as the last argument value will override the preceding argument value which can lead to issues that are hard to debug. - -## Non-Compliant Code Examples -```javascript -function a(a, b, b) {} -function a(a, a, a) {} -function a(a, b, a) {} -function a(a, b, a, b) {} -var a = function(a, b, b) {} -var a = function(a, a, a) {} -var a = function(a, b, a) {} -var a = function(a, b, a, b) {} -``` - -## Compliant Code Examples -```javascript -function a(a, b, c){} -var a = function(a, b, c){} -function a({a, b}, {c, d}){} -function a([ , a]) {} -function foo([[a, b], [c, d]]) {} -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md deleted file mode 100644 index 916091da2846e..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-class-members.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-dupe-class-members - language: JavaScript - severity: Error -title: Avoid duplicate class members ---- -## Metadata -**ID:** `javascript-best-practices/no-dupe-class-members` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -JavaScript allows multiple class members with the same identifier, and the last duplicate class member takes precedence over previous declarations, which is undesired behavior. Disallow duplicate class members. - -## Non-Compliant Code Examples -```javascript -class A { foo() {} foo() {} } -!class A { foo() {} foo() {} }; -class A { 'foo'() {} 'foo'() {} } -class A { 10() {} 1e1() {} } -class A { ['foo']() {} ['foo']() {} } -class A { static ['foo']() {} static foo() {} } -class A { set 'foo'(value) {} set ['foo'](val) {} } -class A { ''() {} ['']() {} } -class A { [`foo`]() {} [`foo`]() {} } -class A { static get [`foo`]() {} static get ['foo']() {} } -class A { foo() {} [`foo`]() {} } -class A { get [`foo`]() {} 'foo'() {} } -class A { static 'foo'() {} static [`foo`]() {} } -class A { ['constructor']() {} ['constructor']() {} } -class A { static [`constructor`]() {} static constructor() {} } -class A { static constructor() {} static 'constructor'() {} } -class A { [123]() {} [123]() {} } -class A { [0x10]() {} 16() {} } -class A { [100]() {} [1e2]() {} } -class A { [123.00]() {} [`123`]() {} } -class A { static '65'() {} static [0o101]() {} } -class A { [123n]() {} 123() {} } -class A { [null]() {} 'null'() {} } -class A { foo() {} foo() {} foo() {} } -class A { static foo() {} static foo() {} } -class A { foo() {} get foo() {} } -class A { set foo(value) {} foo() {} } -class A { foo; foo; } -``` - -## Compliant Code Examples -```javascript -class A { foo() {} bar() {} } -class A { static foo() {} foo() {} } -class A { get foo() {} set foo(value) {} } -class A { static foo() {} get foo() {} set foo(value) {} } -class A { foo() { } } class B { foo() { } } -class A { [foo]() {} foo() {} } -class A { 'foo'() {} 'bar'() {} baz() {} } -class A { *'foo'() {} *'bar'() {} *baz() {} } -class A { get 'foo'() {} get 'bar'() {} get baz() {} } -class A { 1() {} 2() {} } -class A { ['foo']() {} ['bar']() {} } -class A { [`foo`]() {} [`bar`]() {} } -class A { [12]() {} [123]() {} } -class A { [1.0]() {} ['1.0']() {} } -class A { [0x1]() {} [`0x1`]() {} } -class A { [null]() {} ['']() {} } -class A { get ['foo']() {} set ['foo'](value) {} } -class A { ['foo']() {} static ['foo']() {} } - -// computed "constructor" key doesn't create constructor -class A { ['constructor']() {} constructor() {} } -class A { 'constructor'() {} [`constructor`]() {} } -class A { constructor() {} get [`constructor`]() {} } -class A { 'constructor'() {} set ['constructor'](value) {} } - -// not assumed to be statically-known values -class A { ['foo' + '']() {} ['foo']() {} } -class A { [`foo${''}`]() {} [`foo`]() {} } -class A { [-1]() {} ['-1']() {} } - -// private and public -class A { foo; static foo; } -class A { foo; #foo; } -class A { '#foo'; #foo; } -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md b/content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md deleted file mode 100644 index c3465ed5fbda2..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-dupe-keys.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-best-practices/no-dupe-keys - language: JavaScript - severity: Error -title: Avoid duplicate keys in object literals ---- -## Metadata -**ID:** `javascript-best-practices/no-dupe-keys` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -Object literals should not have duplicate keys. If you define an object with duplicate keys, the last one will overwrite any preceding ones. - -## Non-Compliant Code Examples -```javascript -var x = { a: b, ['a']: b }; -var x = { y: 1, y: 2 }; -var x = { '': 1, '': 2 }; -var x = { '': 1, [``]: 2 }; -var foo = { 0x1: 1, 1: 2}; -// should be captured by no-octal -// var x = { 012: 1, 10: 2 }; -var x = { 0b1: 1, 1: 2 }; -var x = { 0o1: 1, 1: 2 }; -var x = { 1n: 1, 1: 2 }; -var x = { 1_0: 1, 10: 2 }; -var x = { "z": 1, z: 2 }; -var foo = { - bar: 1, - bar: 1, - bar() {} -} -var x = { a: 1, get ['a']() {} }; -var x = { a: 1, set a(value) {} }; -var x = { a: 1, b: { a: 2 }, get b() {} }; -var x = ({ '/(?0)/': 1, [/(?0)/]: 2 }) -``` - -## Compliant Code Examples -```javascript -var foo = { __proto__: 1, two: 2}; -var x = { foo: 1, bar: 2 }; -var x = { '': 1, bar: 2 }; -var x = { '': 1, ' ': 2 }; -var x = { '': 1, [null]: 2 }; -var x = { '': 1, [a]: 2 }; -var x = { [a]: 1, [a]: 2 }; -+{ get a() { }, set a(b) { } }; -var x = { a: b, [a]: b }; -var x = { a: b, ...c } -var x = { get a() {}, set a (value) {} }; -var x = { a: 1, b: { a: 2 } }; -var x = ({ null: 1, [/(?0)/]: 2 }) -var {a, a} = obj -// should be captured by no-octal -// var x = { 012: 1, 12: 2 }; -var x = { 1_0: 1, 1: 2 }; -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md b/content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md deleted file mode 100644 index 2e16df7c4c046..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-duplicate-case.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-duplicate-case - language: JavaScript - severity: Error -title: Avoid duplicate case labels ---- -## Metadata -**ID:** `javascript-best-practices/no-duplicate-case` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -It is easy to copy and paste a switch statement case, and leave behind duplicated test cases. - -## Non-Compliant Code Examples -```javascript -var a = 1; switch (a) {case 1: break; case 1: break; case 2: break; default: break;} -var a = '1'; switch (a) {case '1': break; case '1': break; case '2': break; default: break;} -var a = 1, one = 1; switch (a) {case one: break; case one: break; case 2: break; default: break;} -var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p.p.p1: break; case p.p.p1: break; default: break;} -var a = 1, f = function(b) { return b ? { p1: 1 } : { p1: 2 }; }; switch (a) {case f(true).p1: break; case f(true).p1: break; default: break;} -var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a + 1).p1: break; default: break;} -var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a === 1 ? 2 : 3).p1: break; case f(a === 1 ? 2 : 3).p1: break; default: break;} -var a = 1, f1 = function() { return { p1: 1 } }; switch (a) {case f1().p1: break; case f1().p1: break; default: break;} -var a = [1, 2]; switch(a.toString()){case ([1, 2]).toString():break; case ([1, 2]).toString():break; default:break;} -switch (a) { case a: case a: } -switch (a) { case a: break; case b: break; case a: break; case c: break; case a: break; } -var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a+1).p1: break; default: break;} -// limitations -var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p.p.p1: break; case p. p // comment - .p1: break; default: break;} -var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p .p - /* comment */ - .p1: break; case p.p.p1: break; default: break;} -var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p .p - /* comment */ - .p1: break; case p. p // comment - .p1: break; default: break;} -var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) { - case p.p.p1: break; case p. p // comment - .p1: break; case p .p - /* comment */ - .p1: break; default: break;} -var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f( - a + 1 // comment - ).p1: break; case f(a+1) - .p1: break; default: break;} -``` - -## Compliant Code Examples -```javascript -var a = 1; switch (a) {case 1: break; case 2: break; default: break;} -var a = 1; switch (a) {case 1: break; case '1': break; default: break;} -var a = 1; switch (a) {case 1: break; case true: break; default: break;} -var a = 1; switch (a) {default: break;} -var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p.p.p1: break; case p.p.p2: break; default: break;} -var a = 1, f = function(b) { return b ? { p1: 1 } : { p1: 2 }; }; switch (a) {case f(true).p1: break; case f(true, false).p1: break; default: break;} -var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a + 2).p1: break; default: break;} -var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a == 1 ? 2 : 3).p1: break; case f(a === 1 ? 2 : 3).p1: break; default: break;} -var a = 1, f1 = function() { return { p1: 1 } }, f2 = function() { return { p1: 2 } }; switch (a) {case f1().p1: break; case f2().p1: break; default: break;} -var a = [1,2]; switch(a.toString()){case ([1,2]).toString():break; case ([1]).toString():break; default:break;} -switch(a) { case a: break; } switch(a) { case a: break; } -switch(a) { case toString: break; -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md b/content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md deleted file mode 100644 index b0d42b4f8f5ef..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-empty-character-class.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-empty-character-class - language: JavaScript - severity: Error -title: Avoid empty character classes in regular expressions ---- -## Metadata -**ID:** `javascript-best-practices/no-empty-character-class` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -In regular expressions, empty character classes do not match anything, and were likely used in error. - -## Non-Compliant Code Examples -```javascript -var foo = /^abc[]/; -var foo = /foo[]bar/; -if (foo.match(/^abc[]/)) {} -if (/^abc[]/.test(foo)) {} -var foo = /[]]/; -var foo = /\[[]/; -var foo = /\\[\\[\\]a-z[]/; -var foo = /[]]/d; -``` - -## Compliant Code Examples -```javascript -var foo = /^abc[a-zA-Z]/; -var regExp = new RegExp("^abc[]"); -var foo = /^abc/; -var foo = /[\\[]/; -var foo = /[\\]]/; -var foo = /[a-zA-Z\\[]/; -var foo = /[[]/; -var foo = /[\\[a-z[]]/; -var foo = /[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\^\\$\\|]/g; -var foo = /\\s*:\\s*/gim; -var foo = /[\\]]/uy; -var foo = /[\\]]/s; -var foo = /[\\]]/d; -var foo = /\[]/ -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md b/content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md deleted file mode 100644 index c7d5f31c8449d..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-empty-pattern.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-empty-pattern - language: JavaScript - severity: Error -title: Avoid empty destructuring patterns ---- -## Metadata -**ID:** `javascript-best-practices/no-empty-pattern` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -An empty destructuring pattern doesn't provide any value and might be confusing, as it looks similar to the default assignment. - -## Non-Compliant Code Examples -```javascript -var {} = foo -var [] = foo -var {a: {}} = foo -var {a, b: {}} = foo -var {a: []} = foo -function foo({}) {} -function foo([]) {} -function foo({a: {}}) {} -function foo({a: []}) {} -``` - -## Compliant Code Examples -```javascript -var {a = {}} = foo; -var {a, b = {}} = foo; -var {a = []} = foo; -function foo({a = {}}) {} -function foo({a = []}) {} -var [a] = foo -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-empty.md b/content/en/static_analysis/rules/javascript-best-practices/no-empty.md deleted file mode 100644 index cadfdec0c64d6..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-empty.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-empty - language: JavaScript - severity: Error -title: Avoid empty block statements ---- -## Metadata -**ID:** `javascript-best-practices/no-empty` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -Empty or non-functional blocks in the code can be misleading and lead to maintenance difficulties. They can also lead to a false sense of security or functionality. While they may not directly introduce security issues, their presence can suggest that some logic or error handling is implemented when it is not. - -## Non-Compliant Code Examples -```javascript -try {} catch (ex) {throw ex} -try { foo() } catch (ex) {} -try { foo() } catch (ex) {throw ex} finally {} -if (foo) {} -while (foo) {} -for (;foo;) {} -switch(foo) {} -switch (foo) { /* empty */ } -try {} catch (ex) {} -try { foo(); } catch (ex) {} finally {} -try {} catch (ex) {} finally {} -try { foo(); } catch (ex) {} finally {} -(function() { }()) -var foo = () => {} -function foo() { } -function foo() { - -} -``` - -## Compliant Code Examples -```javascript -if (foo) { bar() } -while (foo) { bar() } -for (;foo;) { bar() } -try { foo() } catch (ex) { foo() } -switch(foo) {case 'foo': break;} -if (foo) {/* empty */} -while (foo) {/* empty */} -for (;foo;) {/* empty */} -try { foo() } catch (ex) {/* empty */} -try { foo() } catch (ex) {// empty -} -try { foo() } finally {// empty -} -try { foo() } finally {// test -} -try { foo() } finally { - - // hi i am off no use -} -try { foo() } catch (ex) {/* test111 */} -if (foo) { bar() } else { // nothing in me -} -if (foo) { bar() } else { /**/ -} -if (foo) { bar() } else { // -} -function foo() { - const test = {}; -} -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md b/content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md deleted file mode 100644 index 665f740be514c..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-ex-assign.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-ex-assign - language: JavaScript - severity: Error -title: Avoid reassigning exceptions in catch clauses ---- -## Metadata -**ID:** `javascript-best-practices/no-ex-assign` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -Catching an exception and assigning a different value to the error parameter will overwrite the reference to the original error data, which will be lost since there is no `arguments` object in a catch clause. - -## Non-Compliant Code Examples -```javascript -try { } catch (e) { e = 10; } -try { } catch (ex) { ex = 10; } -try { } catch (ex) { [ex] = []; } -try { } catch (ex) { ({x: ex = 0} = {}); } -try { } catch ({message}) { message = 10; } -``` - -## Compliant Code Examples -```javascript -try { } catch (e) { three = 2 + 1; } -try { } catch ({e}) { this.something = 2; } -function foo() { try { } catch (e) { return false; } } -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md b/content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md deleted file mode 100644 index d48c4a9887afb..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-implied-eval.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-best-practices/no-implied-eval - language: JavaScript - severity: Warning -title: Prevent the use methods similar to eval() ---- -## Metadata -**ID:** `javascript-best-practices/no-implied-eval` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -JavaScript methods like `setTimeout()`, `setInterval()`, or `execScript()` can accept a string of code as their first argument. This code will be executed at runtime, opening a vector for potential attacks. - -It is generally considered a bad practice to execute code at runtime. This rule considers these methods as implied evaluations when their parameter is a piece of code. - -## Non-Compliant Code Examples -```javascript -setTimeout("x = 1;"); -setTimeout("x = 1;", 100); -setInterval("x = 1;"); -execScript("x = 1;"); -// const s = 'x=1'; setTimeout(s, 100); -setTimeout(String('x=1'), 100); - -// member expressions -window.setTimeout('foo'); -window.setInterval('foo'); -window['setTimeout']('foo'); -window['setInterval']('foo'); -window[`setInterval`]('foo'); -window.window['setInterval']('foo'); -global.setTimeout('foo'); -global.setInterval('foo'); -global['setTimeout']('foo'); -global['setInterval']('foo'); -global[`setInterval`]('foo'); -global.global['setInterval']('foo'); -globalThis.setTimeout('foo'); -globalThis.setInterval('foo'); - -// template literals -setTimeout(`foo${bar}`); -window.setTimeout(`foo${bar}`); -window.window.setTimeout(`foo${bar}`); -global.global.setTimeout(`foo${bar}`); - -// string concatenation -setTimeout('foo' + bar); -setTimeout(foo + 'bar'); -setTimeout(`foo` + bar); -setTimeout(1 + ';' + 1); -window.setTimeout('foo' + bar); -window.setTimeout(foo + 'bar'); -window.setTimeout(`foo` + bar); -window.setTimeout(1 + ';' + 1); -window.window.setTimeout(1 + ';' + 1); -global.setTimeout('foo' + bar); -global.setTimeout(foo + 'bar'); -global.setTimeout(`foo` + bar); -global.setTimeout(1 + ';' + 1); -global.global.setTimeout(1 + ';' + 1); -globalThis.setTimeout('foo' + bar); - -// gives the correct node when dealing with nesting -setTimeout('foo' + (function() { - setTimeout(helper); - execScript('str'); - return 'bar'; -})()); - -window.setTimeout('foo' + (function() { - setTimeout(helper); - window.execScript('str'); - return 'bar'; -})()); - -global.setTimeout('foo' + (function() { - setTimeout(helper); - global.execScript('str'); - return 'bar'; -})()); - -// Optional chaining -window?.setTimeout('code', 0); -(window?.setTimeout)('code', 0); -``` - -## Compliant Code Examples -```javascript -setTimeout(); - -setTimeout; -setTimeout = foo; -window.setTimeout; -window.setTimeout = foo; -window['setTimeout']; -window['setTimeout'] = foo; -global.setTimeout; -global.setTimeout = foo; -global['setTimeout']; -global['setTimeout'] = foo; -globalThis['setTimeout'] = foo; - -window[`SetTimeOut`]('foo', 100); -global[`SetTimeOut`]('foo', 100); -global[`setTimeout${foo}`]('foo', 100); -global[`setTimeout${foo}`]('foo', 100); -globalThis[`setTimeout${foo}`]('foo', 100); - -// normal usage -setTimeout(function() { x = 1; }, 100); -setInterval(function() { x = 1; }, 100) -execScript(function() { x = 1; }, 100) -window.setTimeout(function() { x = 1; }, 100); -window.setInterval(function() { x = 1; }, 100); -window.execScript(function() { x = 1; }, 100); -window.setTimeout(foo, 100); -window.setInterval(foo, 100); -window.execScript(foo, 100); -global.setTimeout(function() { x = 1; }, 100); -global.setInterval(function() { x = 1; }, 100); -global.execScript(function() { x = 1; }, 100); -global.setTimeout(foo, 100); -global.setInterval(foo, 100); -global.execScript(foo, 100); -globalThis.setTimeout(foo, 100); - -// only checks on top-level statements or window.* -foo.setTimeout('hi') - -// identifiers are fine -setTimeout(foo, 10) -setInterval(1, 10) -execScript(2) - -// as are function expressions -setTimeout(function() {}, 10) - -// setInterval -foo.setInterval('hi') -setInterval(foo, 10) -setInterval(function() {}, 10) - -// execScript -foo.execScript('hi') -execScript(foo) -execScript(function() {}) - -// a binary plus on non-strings doesn't guarantee a string -// setTimeout(foo + bar, 10) - -// doesn't check anything but the first argument -setTimeout(foobar, 'buzz') -setTimeout(foobar, foo + 'bar') - -// only checks immediate subtrees of the argument -setTimeout(function() { return 'foobar'; }, 10) - -// https://github.com/eslint/eslint/issues/7821 -setTimeoutFooBar('Foo Bar') - -foo.window.setTimeout('foo', 100); -foo.global.setTimeout('foo', 100); -// var window; window.setTimeout('foo', 100); -// var global; global.setTimeout('foo', 100); -// function foo(window) { window.setTimeout('foo', 100); } -// function foo(global) { global.setTimeout('foo', 100); } -foo('', window.setTimeout); -foo('', global.setTimeout); -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md b/content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md deleted file mode 100644 index b101b96c00c7f..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-import-assign.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-best-practices/no-import-assign - language: JavaScript - severity: Error -title: Prevent assigning to imported bindings ---- -## Metadata -**ID:** `javascript-best-practices/no-import-assign` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -Imported modules must be immutable. Assignments to the imported bindings are forbidden. - -## Non-Compliant Code Examples -```javascript -import mod1 from 'mod'; mod1 = 0 -import mod2 from 'mod'; mod2 += 0 -import mod3 from 'mod'; mod3++ -import mod4 from 'mod'; for (mod4 in foo); -import mod5 from 'mod'; for (mod5 of foo); -import mod6 from 'mod'; [mod6] = foo -import mod7 from 'mod'; [mod7 = 0] = foo -import mod8 from 'mod'; [...mod8] = foo -import mod9 from 'mod'; ({ bar: mod9 } = foo) -import mod10 from 'mod'; ({ bar: mod10 = 0 } = foo) -import mod11 from 'mod'; ({ ...mod11 } = foo) -import {named1} from 'mod'; named1 = 0 -import {named2} from 'mod'; named2 += 0 -import {named3} from 'mod'; named3++ -import {named4} from 'mod'; for (named4 in foo); -import {named5} from 'mod'; for (named5 of foo); -import {named6} from 'mod'; [named6] = foo -import {named7} from 'mod'; [named7 = 0] = foo -import {named8} from 'mod'; [...named8] = foo -import {named9} from 'mod'; ({ bar: named9 } = foo) -import {named10} from 'mod'; ({ bar: named10 = 0 } = foo) -import {named11} from 'mod'; ({ ...named11 } = foo) -import {named12 as foo} from 'mod'; foo = 0; named12 = 0 -import * as mod1 from 'mod'; mod1 = 0 -import * as mod2 from 'mod'; mod2 += 0 -import * as mod3 from 'mod'; mod3++ -import * as mod4 from 'mod'; for (mod4 in foo); -import * as mod5 from 'mod'; for (mod5 of foo); -import * as mod6 from 'mod'; [mod6] = foo -import * as mod7 from 'mod'; [mod7 = 0] = foo -import * as mod8 from 'mod'; [...mod8] = foo -import * as mod9 from 'mod'; ({ bar: mod9 } = foo) -import * as mod10 from 'mod'; ({ bar: mod10 = 0 } = foo) -import * as mod11 from 'mod'; ({ ...mod11 } = foo) -import * as mod1 from 'mod'; mod1.named = 0 -import * as mod2 from 'mod'; mod2.named += 0 -import * as mod3 from 'mod'; mod3.named++ -import * as mod4 from 'mod'; for (mod4.named in foo); -import * as mod5 from 'mod'; for (mod5.named of foo); -import * as mod6 from 'mod'; [mod6.named] = foo -import * as mod7 from 'mod'; [mod7.named = 0] = foo -import * as mod8 from 'mod'; [...mod8.named] = foo -import * as mod9 from 'mod'; ({ bar: mod9.named } = foo) -import * as mod10 from 'mod'; ({ bar: mod10.named = 0 } = foo) -import * as mod11 from 'mod'; ({ ...mod11.named } = foo) -import * as mod12 from 'mod'; delete mod12.named -import * as mod from 'mod'; Object.assign(mod, obj) -import * as mod from 'mod'; Object.defineProperty(mod, key, d) -import * as mod from 'mod'; Object.defineProperties(mod, d) -import * as mod from 'mod'; Object.setPrototypeOf(mod, proto) -import * as mod from 'mod'; Object.freeze(mod) -import * as mod from 'mod'; Reflect.defineProperty(mod, key, d) -import * as mod from 'mod'; Reflect.deleteProperty(mod, key) -import * as mod from 'mod'; Reflect.set(mod, key, value) -import * as mod from 'mod'; Reflect.setPrototypeOf(mod, proto) -import mod, * as mod_ns from 'mod'; mod.prop = 0; mod_ns.prop = 0 -// Optional chaining -import * as mod from 'mod'; Object?.defineProperty(mod, key, d) -import * as mod from 'mod'; (Object?.defineProperty)(mod, key, d) -import * as mod from 'mod'; delete mod?.prop -``` - -## Compliant Code Examples -```javascript -import mod from 'mod'; mod.prop = 0 -import mod from 'mod'; mod.prop += 0 -import mod from 'mod'; mod.prop++ -import mod from 'mod'; delete mod.prop -import mod from 'mod'; for (mod.prop in foo); -import mod from 'mod'; for (mod.prop of foo); -import mod from 'mod'; [mod.prop] = foo; -import mod from 'mod'; [...mod.prop] = foo; -import mod from 'mod'; ({ bar: mod.prop } = foo); -import mod from 'mod'; ({ ...mod.prop } = foo); -import {named} from 'mod'; named.prop = 0 -import {named} from 'mod'; named.prop += 0 -import {named} from 'mod'; named.prop++ -import {named} from 'mod'; delete named.prop -import {named} from 'mod'; for (named.prop in foo); -import {named} from 'mod'; for (named.prop of foo); -import {named} from 'mod'; [named.prop] = foo; -import {named} from 'mod'; [...named.prop] = foo; -import {named} from 'mod'; ({ bar: named.prop } = foo); -import {named} from 'mod'; ({ ...named.prop } = foo); -import * as mod from 'mod'; mod.named.prop = 0 -import * as mod from 'mod'; mod.named.prop += 0 -import * as mod from 'mod'; mod.named.prop++ -import * as mod from 'mod'; delete mod.named.prop -import * as mod from 'mod'; for (mod.named.prop in foo); -import * as mod from 'mod'; for (mod.named.prop of foo); -import * as mod from 'mod'; [mod.named.prop] = foo; -import * as mod from 'mod'; [...mod.named.prop] = foo; -import * as mod from 'mod'; ({ bar: mod.named.prop } = foo); -import * as mod from 'mod'; ({ ...mod.named.prop } = foo); -import * as mod from 'mod'; obj[mod] = 0 -import * as mod from 'mod'; obj[mod.named] = 0 -import * as mod from 'mod'; for (var foo in mod.named); -import * as mod from 'mod'; for (var foo of mod.named); -import * as mod from 'mod'; [bar = mod.named] = foo; -import * as mod from 'mod'; ({ bar = mod.named } = foo); -import * as mod from 'mod'; ({ bar: baz = mod.named } = foo); -import * as mod from 'mod'; ({ [mod.named]: bar } = foo); -import * as mod from 'mod'; var obj = { ...mod.named }; -import * as mod from 'mod'; var obj = { foo: mod.named }; -// scoped import name re-use not covered -// import mod from 'mod'; { let mod = 0; mod = 1 } -// import * as mod from 'mod'; { let mod = 0; mod = 1 } -// import * as mod from 'mod'; { let mod = 0; mod.named = 1 } -import {} from 'mod' -import 'mod' -import mod from 'mod'; Object.assign(mod, obj); -import {named} from 'mod'; Object.assign(named, obj); -import * as mod from 'mod'; Object.assign(mod.prop, obj); -import * as mod from 'mod'; Object.assign(obj, mod, other); -import * as mod from 'mod'; Object[assign](mod, obj); -import * as mod from 'mod'; Object.getPrototypeOf(mod); -import * as mod from 'mod'; Reflect.set(obj, key, mod); -// Object redeclare not analyzed -// import * as mod from 'mod'; { var Object; Object.assign(mod, obj); } -// import * as mod from 'mod'; var Object; Object.assign(mod, obj); -import * as mod from 'mod'; Object.seal(mod, obj) -import * as mod from 'mod'; Object.preventExtensions(mod) -import * as mod from 'mod'; Reflect.preventExtensions(mod) -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md b/content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md deleted file mode 100644 index d677fc08f542c..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-inner-declarations.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-best-practices/no-inner-declarations - language: JavaScript - severity: Warning -title: Avoid variable or function declaration in nested blocks ---- -## Metadata -**ID:** `javascript-best-practices/no-inner-declarations` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Function declarations in JavaScript are generally not block scoped. This rule prevents function declarations inside nested blocks like `if` statements. Move your declarations to the root of your program, body, or class. - -## Non-Compliant Code Examples -```javascript -if (test) { function doSomething() { } } -if (foo) var a; -if (foo) /* some comments */ var a; -if (foo){ function f(){ if(bar){ var a; } } } -if (foo) function f(){ if(bar) var a; } -if (foo) { var fn = function(){} } -if (foo) function f(){} -function bar() { if (foo) var a; } -if (foo){ var a; } -class C { method() { if(test) { var foo; } } } -class C { static { if (test) { function foo() {} } } } -class C { static { if (test) { var foo; } } } -class C { static { if (test) { if (anotherTest) { var foo; } } } } -``` - -## Compliant Code Examples -```javascript -function doSomething() { } -function doSomething() { function somethingElse() { } } -(function() { function doSomething() { } }()); -function decl() { var fn = function expr() { }; } -function decl(arg) { var fn; if (arg) { fn = function() { }; } } -var x = {doSomething() {function doSomethingElse() {}}} -function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } -function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } -if (test) { let x = 1; } -if (test) { const x = 1; } -function doSomething() { while (test) { var foo; } } -var foo; -var foo = 42; -function doSomething() { var foo; } -(function() { var foo; }()); -foo(() => { function bar() { } }); -var fn = () => {var foo;} -var x = {doSomething() {var foo;}} -export var foo; -export function bar() {} -export default function baz() {} -exports.foo = () => {} -exports.foo = function(){} -module.exports = function foo(){} -class C { method() { function foo() {} } } -class C { method() { var x; } } -class C { static { function foo() {} } } -class C { static { var x; } } -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-iterator.md b/content/en/static_analysis/rules/javascript-best-practices/no-iterator.md deleted file mode 100644 index 8540584e3969d..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-iterator.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-best-practices/no-iterator - language: JavaScript - severity: Warning -title: Avoid the use of the __iterator__ property ---- -## Metadata -**ID:** `javascript-best-practices/no-iterator` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -The `__iterator__` property was exclusive to the SpiderMonkey engine. Avoid using it as other JavaScript engines do not implement it. - -## Non-Compliant Code Examples -```javascript -var a = test.__iterator__; -Foo.prototype.__iterator__ = function() {}; -var a = test['__iterator__']; -var a = test[`__iterator__`]; -test[`__iterator__`] = function () {}; -``` - -## Compliant Code Examples -```javascript -var a = test[__iterator__]; -var __iterator__ = null; -foo[`__iterator`] = null; -foo[`__iterator__ -`] = null; -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md b/content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md deleted file mode 100644 index 951aaa8d803c1..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-loss-of-precision.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-loss-of-precision - language: JavaScript - severity: Error -title: Avoid numbers that lose precision ---- -## Metadata -**ID:** `javascript-best-practices/no-loss-of-precision` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -JavaScript uses double-precision, floating-point numbers in accordance with the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754). This means numbers are only accurate until a certain amount of digits. Adding more digits will make the number lose precision, as the added digits will be lost in the conversion to the `Number` type, causing unexpected behavior. - -## Non-Compliant Code Examples -```javascript - -var x = 9007199254740993 -var x = 9007199254740.993e3 -var x = 9.007199254740993e15 -var x = -9007199254740993 -var x = 900719.9254740994 -var x = -900719.9254740994 -var x = 900719925474099_3 -var x = 90_0719925_4740.9_93e3 -var x = 9.0_0719925_474099_3e15 -var x = -9_00719_9254_740993 -var x = 900_719.92_54740_994 -var x = -900_719.92_5474_0994 -var x = 5123000000000000000000000000001 -var x = -5123000000000000000000000000001 -var x = 1230000000000000000000000.0 -var x = 1.0000000000000000000000123var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 -var x = 2e999 -var x = .1230000000000000000000000 -var x = 0b100000000000000000000000000000000000000000000000000001 -var x = 0B100000000000000000000000000000000000000000000000000001 -var x = 0o400000000000000001 -var x = 0O400000000000000001 -var x = 0400000000000000001 -var x = 0x20000000000001 -var x = 0X20000000000001 -var x = 5123_00000000000000000000000000_1 -var x = -5_12300000000000000000000_0000001 -var x = 123_00000000000000000000_00.0_0 -var x = 1.0_00000000000000000_0000123 -var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 -var x = 2e9_99 -var x = .1_23000000000000_00000_0000_0 -var x = 0b1_0000000000000000000000000000000000000000000000000000_1 -var x = 0B10000000000_0000000000000000000000000000_000000000000001 -var x = 0o4_00000000000000_001 -var x = 0O4_0000000000000000_1 -var x = 0x2_0000000000001 -var x = 0X200000_0000000_1 -``` - -## Compliant Code Examples -```javascript -var x = 12345 -var x = 123.456 -var x = -123.456 -var x = -123456 -var x = 123e34 -var x = 123.0e34 -var x = 123e-34 -var x = -123e34 -var x = -123e-34 -var x = 12.3e34 -var x = 12.3e-34 -var x = -12.3e34 -var x = -12.3e-34 -var x = 12300000000000000000000000 -var x = -12300000000000000000000000 -var x = 0.00000000000000000000000123 -var x = -0.00000000000000000000000123 -var x = 9007199254740991 -var x = 0 -var x = 0.0 -var x = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000 -var x = -0 -var x = 123.0000000000000000000000 -var x = 0e5 -var x = 12_34_56 -var x = 12_3.4_56 -var x = -12_3.4_56 -var x = -12_34_56 -var x = 12_3e3_4 -var x = 123.0e3_4 -var x = 12_3e-3_4 -var x = 12_3.0e-3_4 -var x = -1_23e-3_4 -var x = -1_23.8e-3_4 -var x = 1_230000000_00000000_00000_000 -var x = -1_230000000_00000000_00000_000 -var x = 0.0_00_000000000_000000000_00123 -var x = -0.0_00_000000000_000000000_00123 -var x = 0e5_3 - -var x = 0b11111111111111111111111111111111111111111111111111111 -var x = 0b111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 -var x = 0B11111111111111111111111111111111111111111111111111111 -var x = 0B111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 -var x = 0o377777777777777777 -var x = 0o3_77_777_777_777_777_777 -var x = 0O377777777777777777 - -var x = 0377777777777777777 -var x = 0x1FFFFFFFFFFFFF -var x = 0X1FFFFFFFFFFFFF -var x = true -var x = 'abc' -var x = '' -var x = null -var x = undefined -var x = {} -var x = ['a', 'b'] -var x = new Date() -var x = '9007199254740993' - -var x = 0x1FFF_FFFF_FFF_FFF -var x = 0X1_FFF_FFFF_FFF_FFF -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md b/content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md deleted file mode 100644 index dbe622c33d93c..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-new-symbol.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-new-symbol - language: JavaScript - severity: Error -title: Avoid new statements with the Symbol object ---- -## Metadata -**ID:** `javascript-best-practices/no-new-symbol` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -Symbol is intended to be called as a function. Do not instantiate with new statements. - -## Non-Compliant Code Examples -```javascript -var foo = new Symbol('foo'); -function bar() { return function Symbol() {}; } var baz = new Symbol('baz'); -``` - -## Compliant Code Examples -```javascript -var foo = Symbol('foo'); -new foo(Symbol); -new foo(bar, Symbol) -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-octal.md b/content/en/static_analysis/rules/javascript-best-practices/no-octal.md deleted file mode 100644 index 5620267cd6914..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-octal.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-octal - language: JavaScript - severity: Error -title: Avoid using octal literals to prevent unexpected behavior ---- -## Metadata -**ID:** `javascript-best-practices/no-octal` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -In JavaScript, numbers that start with a leading zero (`0`) are considered octal (base-8) literals. However, octal literals can lead to unintended and unexpected behavior, especially for developers who are not familiar with this notation or when used accidentally. - -## Non-Compliant Code Examples -```javascript -var a = 01234; -a = 1 + 01234; -00; -08; -09.1; -09e1; -09.1e1; -018; -019.1; -019e1; -019.1e1; -``` - -## Compliant Code Examples -```javascript -var a = 'hello world'; -0x1234 -0X5; -a = 0; -0.1 -0.5e1 -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-proto.md b/content/en/static_analysis/rules/javascript-best-practices/no-proto.md deleted file mode 100644 index f32be8a06a8c1..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-proto.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-best-practices/no-proto - language: JavaScript - severity: Warning -title: Avoid the use of the __proto__ property ---- -## Metadata -**ID:** `javascript-best-practices/no-proto` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -The `__proto__` property has been deprecated as of ECMAScript 3.1. - -Use a suitable alternative to `__proto__` like `Object.getPrototypeOf` and `Object.setPrototypeOf` instead. - -## Non-Compliant Code Examples -```javascript -var a = test.__proto__; -var a = test['__proto__']; -var a = test[`__proto__`]; -test[`__proto__`] = function () {}; -``` - -## Compliant Code Examples -```javascript -var a = test[__proto__]; -var __proto__ = null; -foo[`__proto`] = null; -foo[`__proto__\n`] = null; -class C { #__proto__; foo() { this.#__proto__; } } -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-script-url.md b/content/en/static_analysis/rules/javascript-best-practices/no-script-url.md deleted file mode 100644 index 9d1ebe2748950..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-script-url.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-script-url - language: JavaScript - severity: Notice -title: Avoid using JavaScript in URLs ---- -## Metadata -**ID:** `javascript-best-practices/no-script-url` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -JavaScript URLs are evaluated the same way `eval` is executed. This can lead to arbitrary code execution. - -## Non-Compliant Code Examples -```javascript -var a = 'javascript:void(0);'; -var a = 'javascript:'; -var a = `javascript:`; -var a = `JavaScript:`; -``` - -## Compliant Code Examples -```javascript -var a = 'Hello World!'; -var a = 10; -var url = 'xjavascript:' -var url = `xjavascript:` -var url = `${foo}javascript:` -var a = foo`javaScript:`; -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md b/content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md deleted file mode 100644 index 5aba62c85b514..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-unsafe-negation.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-unsafe-negation - language: JavaScript - severity: Warning -title: Avoid negating the left operand of relational operators ---- -## Metadata -**ID:** `javascript-best-practices/no-unsafe-negation` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Negation of the left-hand side of an expression is often unintended. - -## Non-Compliant Code Examples -```javascript -!a in b -(!a in b) -!(a) in b -!a instanceof b -(!a instanceof b) -!(a) instanceof b -``` - -## Compliant Code Examples -```javascript -a in b -a in b === false -!(a in b); -(!a) in b -a instanceof b -a instanceof b === false; -!(a instanceof b); -(!a) instanceof b; - -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/no-with.md b/content/en/static_analysis/rules/javascript-best-practices/no-with.md deleted file mode 100644 index d7279282e4986..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/no-with.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/no-with - language: JavaScript - severity: Error -title: The with statement can lead to ambiguous code ---- -## Metadata -**ID:** `javascript-best-practices/no-with` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -The `with` statement in JavaScript is used to add a given object's properties as variables in a specific block of code. While it may seem convenient, the `with` statement has several pitfalls and can lead to hard-to-diagnose problems. - -## Non-Compliant Code Examples -```javascript -with(foo) { bar() } -``` - -## Compliant Code Examples -```javascript -foo.bar() -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/require-yield.md b/content/en/static_analysis/rules/javascript-best-practices/require-yield.md deleted file mode 100644 index bb704297c8fd8..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/require-yield.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/require-yield - language: JavaScript - severity: Error -title: Require yield in generator functions ---- -## Metadata -**ID:** `javascript-best-practices/require-yield` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -Generator functions must yield at some point. Otherwise, use a normal function. - -## Non-Compliant Code Examples -```javascript -function* foo() { return 0; } -(function* foo() { return 0; })(); -var obj = { *foo() { return 0; } } -class A { *foo() { return 0; } } -function* foo() { function* bar() { yield 0; } } -function* foo() { function* bar() { return 0; } yield 0; } -``` - -## Compliant Code Examples -```javascript -function foo() { return 0; } -function* foo() { yield 0; } -function* foo() { } -(function* foo() { yield 0; })(); -(function* foo() { })(); -var obj = { *foo() { yield 0; } }; -var obj = { *foo() { } }; -class A { *foo() { yield 0; } }; -class A { *foo() { } } -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/use-isnan.md b/content/en/static_analysis/rules/javascript-best-practices/use-isnan.md deleted file mode 100644 index 15f5a3ea6e2f6..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/use-isnan.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-best-practices/use-isnan - language: JavaScript - severity: Error -title: Avoid direct comparison with NaN ---- -## Metadata -**ID:** `javascript-best-practices/use-isnan` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -In JavaScript, `NaN` (Not-a-Number) is a unique value that is not equal to anything, including itself. This means any direct comparison with `NaN` using equality (`==`, `===`) or inequality (`!=`, `!==`) operators will always return `false`. - -## Non-Compliant Code Examples -```javascript -123 == NaN; -123 === NaN; -NaN === "abc"; -NaN =="abc"; -123 != NaN; -123 !== NaN; -NaN !== "abc"; -NaN != "abc"; -NaN < "abc"; -"abc" < NaN; -NaN > "abc"; -"abc" > NaN; -NaN <= "abc"; -"abc" <= NaN; -NaN >= "abc"; -"abc" >= NaN; -123 == Number.NaN; -123 === Number.NaN; -Number.NaN === "abc"; -Number.NaN == "abc"; -123 != Number.NaN; -123 !== Number.NaN; -Number.NaN !== "abc"; -Number.NaN != "abc"; -Number.NaN < "abc"; -"abc" < Number.NaN; -Number.NaN > "abc"; -"abc" > Number.NaN; -Number.NaN <= "abc"; -"abc" <= Number.NaN; -Number.NaN >= "abc"; -"abc" >= Number.NaN; -x === Number?.NaN; -x === Number['NaN']; -``` - -## Compliant Code Examples -```javascript -var x = NaN; -isNaN(NaN) === true; -isNaN(123) !== true; -Number.isNaN(NaN) === true; -Number.isNaN(123) !== true; -foo(NaN + 1); -foo(1 + NaN); -foo(NaN - 1) -foo(1 - NaN) -foo(NaN * 2) -foo(2 * NaN) -foo(NaN / 2) -foo(2 / NaN) -var x; if (x = NaN) { } -var x = Number.NaN; -isNaN(Number.NaN) === true; -Number.isNaN(Number.NaN) === true; -foo(Number.NaN + 1); -foo(1 + Number.NaN); -foo(Number.NaN - 1) -foo(1 - Number.NaN) -foo(Number.NaN * 2) -foo(2 * Number.NaN) -foo(Number.NaN / 2) -foo(2 / Number.NaN) -var x; if (x = Number.NaN) { } -x === Number[NaN]; -``` diff --git a/content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md b/content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md deleted file mode 100644 index 5c6294c946507..0000000000000 --- a/content/en/static_analysis/rules/javascript-best-practices/valid-typeof.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-best-practices/valid-typeof - language: JavaScript - severity: Warning -title: Compare typeof expressions against valid strings ---- -## Metadata -**ID:** `javascript-best-practices/valid-typeof` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Always compare typeof expressions against strings and make sure they are the correct values. - -## Non-Compliant Code Examples -```javascript -typeof foo === 'strnig'; -'strnig' === typeof foo; -if (typeof bar === 'umdefined') {}; -typeof foo !== 'strnig'; -'strnig' !== typeof foo; -if (typeof bar !== 'umdefined') {}; -typeof foo != 'strnig'; -'strnig' != typeof foo; -if (typeof bar != 'umdefined') {}; -typeof foo == 'strnig'; -'strnig' == typeof foo; -if (typeof bar == 'umdefined') {}; -if (typeof bar === `umdefined`) {}; -typeof foo == 'invalid string'; -if (typeof bar !== undefined) {}; -typeof foo == Object; -typeof foo == {}; -typeof foo === undefined; -undefined === typeof foo; -undefined == typeof foo; -typeof foo === `undefined${foo}`; -typeof foo === `${string}`; -``` - -## Compliant Code Examples -```javascript -typeof foo === 'string'; -typeof foo === 'object'; -typeof foo === 'function'; -typeof foo === 'undefined'; -typeof foo === 'boolean'; -typeof foo === 'number'; -typeof foo === 'bigint'; -'string' === typeof foo; -'object' === typeof foo; -'function' === typeof foo; -'undefined' === typeof foo; -'boolean' === typeof foo; -'number' === typeof foo; -typeof foo === typeof bar; -typeof foo === baz; -typeof foo !== someType; -typeof bar != someType; -someType === typeof bar; -someType == typeof bar; -typeof foo == 'string'; -typeof(foo) === 'string'; -typeof(foo) !== 'string'; -typeof(foo) == 'string'; -typeof(foo) != 'string'; -var oddUse = typeof foo + 'thing'; -// since we don't have optios we are enforcing to always compare agaisnt strings -// function f(undefined) { typeof x === undefined }; -typeof foo === 'number'; -typeof foo === "number"; -var baz = typeof foo + 'thing'; -typeof foo === typeof bar; -typeof foo === `string`; -`object` === typeof foo; -// not supported by this rule, we cannot pretend that somethingElse will complete 'string' -// typeof foo === `str${somethingElse}`; -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md b/content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md deleted file mode 100644 index ff558ab857aea..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/event-check-origin.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/event-check-origin - language: JavaScript - severity: Warning -title: Check origin of events ---- -## Metadata -**ID:** `javascript-browser-security/event-check-origin` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Not checking the rule origin can lead to XSS attacks. Always check the event origin. - -#### Learn More - - - [XSS and CSS Cheat Sheet from OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) - -## Non-Compliant Code Examples -```javascript -window.addEventListener('message', (event) => { - processing(); -}) -``` - -## Compliant Code Examples -```javascript -window.addEventListener('message', (event) => { - if (event.origin != 'https://app.domain.tld') { - throw new Error('invalid origin') - } - - processing(); -}) -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md b/content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md deleted file mode 100644 index 5959b63447f71..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/inner-outer-html.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/inner-outer-html - language: JavaScript - severity: Warning -title: Do not modify innerHTML or outerHTML ---- -## Metadata -**ID:** `javascript-browser-security/inner-outer-html` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Properties like `innerHTML` and `outerHTML` should not be modified directly unless such modifications are clearly reviewed. Modifying `innerHTML` or `outerHTML` using user inputs that has not been validated can lead to XSS injection. - -#### Learn More - - - [Why InnerHTML Is a Bad Idea and How to Avoid It?](https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/) - - [CWE-79 - Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) - - -## Non-Compliant Code Examples -```javascript -function nonCompliant(argument) { - const content = '
' + argument + '
'; - document.write(content); -} -``` - -```javascript -function nonCompliant(myArgument) { - document.body.outerHTML = myArgument; -} -``` - -```javascript -if (typeof(SERVER_DOMAIN) === 'undefined') { - window.location.replace("/unconfigured.html"); -} - -const RECEIVE_URL = SERVER_DOMAIN + "/challenge_scoreboard.html" + "?origin=" + get_domain(); - -var window_ref = null; - -document.getElementById("username").focus(); - -function store_username() { - var username; - var username_obj; - - username_obj = document.getElementById("username"); - username = username_obj.value - - var welcome; - welcome = document.getElementById("welcome"); - welcome.innerHTML = "Welcome " + html_encode (username); - - var set_username; - set_username = document.getElementById("set_username"); - set_username.style.display="none"; - - var game; - game = document.getElementById("game"); - game.style.display="inline"; - - start_game(); - // have to do time out so the window can open - setTimeout (function () {send_username(username);}, 1000); - - return false; -} - -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md b/content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md deleted file mode 100644 index 36d4f3e1ceaa2..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/insecure-websocket.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/insecure-websocket - language: JavaScript - severity: Warning -title: Websockets must use SSL connections ---- -## Metadata -**ID:** `javascript-browser-security/insecure-websocket` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always use secure websocket communication. When using websocket, use addresses that are SSL-enabled. - - - -## Non-Compliant Code Examples -```javascript -const client = new WebSocket('ws://app.domain.tld') -``` - -## Compliant Code Examples -```javascript -const client = new WebSocket('wss://app.domain.tld') -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md b/content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md deleted file mode 100644 index a3a2dc2bcf012..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/local-storage-sensitive-data - language: JavaScript - severity: Warning -title: Do not store sensitive data to local storage ---- -## Metadata -**ID:** `javascript-browser-security/local-storage-sensitive-data` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not store sensitive data in `localStorage` and keep the data safe from any malicious software that could read this data. - -#### Learn More - - [CWE-312 - Cleartext Storage of Sensitive Information](https://cwe.mitre.org/data/definitions/312.html) - -## Non-Compliant Code Examples -```javascript -localStorage.setItem('user', email) - -localStorage.setItem('user', user.email) -``` - -## Compliant Code Examples -```javascript -localStorage.setItem('user', uuid) - -localStorage.setItem('user', user.id) -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md b/content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md deleted file mode 100644 index 311afe79206d1..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/manual-sanitization.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/manual-sanitization - language: JavaScript - severity: Warning -title: Avoid manual sanitization of inputs ---- -## Metadata -**ID:** `javascript-browser-security/manual-sanitization` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Never sanitize HTML input manually. It can lead to vulnerabilities. Use dedicated modules such as `sanitize-html` to sanitize user inputs. - -## Non-Compliant Code Examples -```javascript -const sanitizedInput = input - .replaceAll('<', '<') - .replaceAll('>', '>'); -const html = `${sanitizedInput}`; - -const sanitizedInput2 = input - .replaceAll('bla', '<') - .replaceAll('foo', '>'); - -const sanitizedInput3 = input - .replaceAll('<', '<') - .replaceAll('>', 'gt;'); -``` - -## Compliant Code Examples -```javascript -import sanitizeHtml from 'sanitize-html'; - -const html = sanitizeHtml(`${input}`); -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md b/content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md deleted file mode 100644 index 39b24dcdc08a5..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/postmessage-permissive-origin - language: JavaScript - severity: Warning -title: Specify origin in postMessage ---- -## Metadata -**ID:** `javascript-browser-security/postmessage-permissive-origin` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always specify the origin of the message for security reasons and to avoid spoofing attacks. Always specify an exact target origin, not `*`, when you use `postMessage` to send data to other windows. - -#### Learn More - - - [window.postMessage documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) - -## Non-Compliant Code Examples -```javascript -window.postMessage(message, '*') - -``` - -## Compliant Code Examples -```javascript -window.postMessage(message, 'https://app.domain.tld') - -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md b/content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md deleted file mode 100644 index 0f96150da260f..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/react-dangerously-inner-html - language: JavaScript - severity: Warning -title: Do not inject unsanitized HTML ---- -## Metadata -**ID:** `javascript-browser-security/react-dangerously-inner-html` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always sanitize HTML data before injecting it in the DOM. Use libraries such as [DOMPurify](https://github.com/cure53/DOMPurify) before using it. - -## Non-Compliant Code Examples -```javascript -const App = () => { - const data = `lorem ipsum`; - - return ( -
-
- ); -} -``` - -## Compliant Code Examples -```javascript -const App = () => { - const data = `lorem ipsum`; - - return ( -
- ); -} -``` diff --git a/content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md b/content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md deleted file mode 100644 index f36debd7d319d..0000000000000 --- a/content/en/static_analysis/rules/javascript-browser-security/regexp-non-literal.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-browser-security/regexp-non-literal - language: JavaScript - severity: Warning -title: Do not use variable for regular expressions ---- -## Metadata -**ID:** `javascript-browser-security/regexp-non-literal` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Regular expressions should not use a variable as an argument since an attacker may inject values and cause a regular expression denial of service (ReDoS). Instead, use a library like [recheck](https://www.npmjs.com/package/recheck) to check that no ReDoS can be triggered by a regular expression. - -## Non-Compliant Code Examples -```javascript -const foo = new RegExp(req.something); -const bar = new RegExp(variable); -``` - -## Compliant Code Examples -```javascript -const foo = new RegExp(`^\\d+-${topicId}$`); -const foo = new RegExp(/something/); -const foo = new RegExp("weofiwje"); -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/assignment-name.md b/content/en/static_analysis/rules/javascript-code-style/assignment-name.md deleted file mode 100644 index d54a7156594d3..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/assignment-name.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/assignment-name - language: JavaScript - severity: Notice -title: Assigment name should use camelCase ---- -## Metadata -**ID:** `javascript-code-style/assignment-name` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that variables and properties names use `camelCase` and not `snake_case` or `PascalCase`. - -## Non-Compliant Code Examples -```javascript -var a = { - MyProp: "should be camelCase", - foo_bar: 0, - #Priv: 2, -}; -const my_var = {}; -let FooBar = {}; -const { a_b, ...Bla } = c; -const [a_b, ...Bla] = c; - -``` - -## Compliant Code Examples -```javascript -/* The BenefitsDAO must be constructed with a connected database object */ -function BenefitsDAO(db) { - - "use strict"; - - /* If this constructor is called without the "new" operator, "this" points - * to the global object. Log a warning and call it correctly. */ - if (false === (this instanceof BenefitsDAO)) { - console.log("Warning: BenefitsDAO constructor called without 'new' operator"); - return new BenefitsDAO(db); - } - - const usersCol = db.collection("users"); - const Users = db.collections("something"); - - this.getAllNonAdminUsers = callback => { - usersCol.find({ - "isAdmin": { - $ne: true - } - }).toArray((err, users) => callback(null, users)); - }; - - this.updateBenefits = (userId, startDate, callback) => { - usersCol.update({ - _id: parseInt(userId) - }, { - $set: { - benefitStartDate: startDate - } - }, - (err, result) => { - if (!err) { - console.log("Updated benefits"); - return callback(null, result); - } - - return callback(err, null); - } - ); - }; -} - -module.exports = { BenefitsDAO }; -``` - -```javascript -const a = { myProp: "", #priv: 1 }; -const myVar = {}; -const { a } = c; -const { a, ...b } = c; -const [a, ...b] = c; -process.env.PCKG_OS_NAME; -const md5 = 'foo'; -const PCKG_OS_NAME = 'foo'; -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/class-name.md b/content/en/static_analysis/rules/javascript-code-style/class-name.md deleted file mode 100644 index 8ed7ee6a7e4fe..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/class-name.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/class-name - language: JavaScript - severity: Warning -title: Class name should be PascalCase ---- -## Metadata -**ID:** `javascript-code-style/class-name` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Code Style - -## Description -Class names should be `PascalCase` and not `camelCase` or `snake_case`. - -## Non-Compliant Code Examples -```javascript -class _runtimeMetricsStatus {} -class runtimeMetricsStatus {} -``` - -## Compliant Code Examples -```javascript -class MyClass {} -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/eqeqeq.md b/content/en/static_analysis/rules/javascript-code-style/eqeqeq.md deleted file mode 100644 index c6117f669cccb..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/eqeqeq.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/eqeqeq - language: JavaScript - severity: Notice -title: Enforce the use of === and !== ---- -## Metadata -**ID:** `javascript-code-style/eqeqeq` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -In JavaScript, `==` and `!=` comparisons do type coercion, which can be confusing and may introduce potential errors. Use the type-safe equality operators `===` and `!==` instead. - -## Non-Compliant Code Examples -```javascript -a == b -a != b -typeof a == 'number' -typeof a == 'number' -'string' != typeof a -true == true -2 == 3 -2 == 3 -'hello' != 'world' -'hello' != 'world' -a == null -a == null -null != a -true == 1 -0 != '1' -'wee' == /wee/ -typeof a == 'number' -'string' != typeof a -'hello' != 'world' -2 == 3 -true == true -true == null -true != null -null == null -null != null -a -== -b -(a) == b -(a) != b -a == (b) -a != (b) -(a) == (b) -(a == b) == (c) -(a != b) != (c) -a == b; -a!=b; -(a + b) == c; -(a + b) != c; -((1) ) == (2); - -``` - -## Compliant Code Examples -```javascript -a === b -a !== b -a === b -a !== null -a === null -a !== null -null === null -null !== null - -// https://github.com/eslint/eslint/issues/8020 -foo === /abc/u - -// bigint -foo === 1n -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/func-name-matching.md b/content/en/static_analysis/rules/javascript-code-style/func-name-matching.md deleted file mode 100644 index 2220769b4197d..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/func-name-matching.md +++ /dev/null @@ -1,195 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/func-name-matching - language: JavaScript - severity: Notice -title: Function names must match the name of the assignation. ---- -## Metadata -**ID:** `javascript-code-style/func-name-matching` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Use the same name between your function declaration and the variable or property to which it is assigned. - -## Non-Compliant Code Examples -```javascript -let foo = function bar() {}; -let foo = function bar() {}; -foo = function bar() {}; -foo &&= function bar() {}; -obj.foo ||= function bar() {}; -obj['foo'] ??= function bar() {}; -obj.foo = function bar() {}; -obj.bar.foo = function bar() {}; -obj['foo'] = function bar() {}; -let obj = {foo: function bar() {}}; -let obj = {'foo': function bar() {}}; -({['foo']: function bar() {}}); -// NOT SUPPORTED -// module.exports = function foo(name) {}; -// module.exports = function foo(name) {}; -// module.exports = function exports(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function exports(name) {}; -// Object.defineProperty(foo, 'bar', { value: function baz() {} }); -// Object.defineProperties(foo, { bar: { value: function baz() {} } }); -// Object.create(proto, { bar: { value: function baz() {} } }); -// var obj = { value: function foo(name) {} }; -// Object.defineProperty(foo, 'bar', { value: function bar() {} }); -// Object.defineProperties(foo, { bar: { value: function bar() {} } }); -// Object.create(proto, { bar: { value: function bar() {} } }); -// Reflect.defineProperty(foo, 'bar', { value: function baz() {} }); -// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }); -foo({ value: function bar() {} }); -(obj?.aaa).foo = function bar() {}; -// Object?.defineProperty(foo, 'bar', { value: function baz() {} }); -// (Object?.defineProperty)(foo, 'bar', { value: function baz() {} }); -// Object?.defineProperty(foo, 'bar', { value: function bar() {} }); -// (Object?.defineProperty)(foo, 'bar', { value: function bar() {} }); -// Object?.defineProperties(foo, { bar: { value: function baz() {} } }); -// (Object?.defineProperties)(foo, { bar: { value: function baz() {} } }); -// Object?.defineProperties(foo, { bar: { value: function bar() {} } }); -// (Object?.defineProperties)(foo, { bar: { value: function bar() {} } }); -class C { x = function y() {}; } -class C { 'x' = function y() {}; } -class C { ['x'] = function y() {}; } -class C { static x = function y() {}; } -(class { x = function y() {}; }) -var obj = { '\u1885': function foo() {} }; - -``` - -## Compliant Code Examples -```javascript -var foo; -var foo = function foo() {}; -var foo = function foo() {}; -var foo = function() {} -var foo = () => {} -foo = function foo() {}; -foo = function foo() {}; -foo &&= function foo() {}; -obj.foo ||= function foo() {}; -obj['foo'] ??= function foo() {}; -obj.foo = function foo() {}; -obj.foo = function foo() {}; -obj.foo = function() {}; -obj.foo = function() {}; -obj.bar.foo = function foo() {}; -obj.bar.foo = function foo() {}; -obj['foo'] = function foo() {}; -obj['foo'] = function foo() {}; -// This are not equal not sure why eslint skips them -// obj['foo//bar'] = function foo() {}; -// obj['foo//bar'] = function foo() {}; -// obj['foo//bar'] = function foo() {}; -obj[foo] = function bar() {}; -obj[foo] = function bar() {}; -var obj = {foo: function foo() {}}; -var obj = {foo: function foo() {}}; -var obj = {'foo': function foo() {}}; -var obj = {'foo': function foo() {}}; -var obj = {foo: function() {}}; -var obj = {foo: function() {}}; -var obj = {foo: function() {}}; -var obj = {[foo]: function bar() {}} -var obj = {['x' + 2]: function bar() {}}; -obj['x' + 2] = function bar(){}; -var [ bar ] = [ function bar(){} ]; -function a(foo = function bar() {}) {} -// NOT SUPPORTED -// module.exports = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module.exports = function foo(name) {}; -// module.exports = function foo(name) {}; -// module.exports = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function foo(name) {}; -({['foo']: function foo() {}}) -({['foo']: function foo() {}}) -({[foo]: function bar() {}}) -({[null]: function foo() {}}) -({[1]: function foo() {}}) -({[true]: function foo() {}}) -({[`x`]: function foo() {}}) -({[/abc/]: function foo() {}}) -({[[1, 2, 3]]: function foo() {}}) -({[{x: 1}]: function foo() {}}) -[] = function foo() {} -({} = function foo() {}) -[a] = function foo() {} -({a} = function foo() {}) -var [] = function foo() {} -var {} = function foo() {} -var [a] = function foo() {} -var {a} = function foo() {} -({ value: function value() {} }) -obj.foo = function foo() {}; -obj.bar.foo = function foo() {}; -var obj = {foo: function foo() {}}; -var obj = {foo: function() {}}; -var obj = { value: function value() {} } -// NOT SUPPORTED -// Object.defineProperty(foo, 'bar', { value: function bar() {} }) -// Object.defineProperties(foo, { bar: { value: function bar() {} } }) -// Object.create(proto, { bar: { value: function bar() {} } }) -// Object.defineProperty(foo, 'b' + 'ar', { value: function bar() {} }) -// Object.defineProperties(foo, { ['bar']: { value: function bar() {} } }) -// Object.create(proto, { ['bar']: { value: function bar() {} } }) -// Object.defineProperty(foo, 'bar', { value() {} }) -// Object.defineProperties(foo, { bar: { value() {} } }) -// Object.create(proto, { bar: { value() {} } }) -// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }) -// Reflect.defineProperty(foo, 'b' + 'ar', { value: function baz() {} }) -// Reflect.defineProperty(foo, 'bar', { value() {} }) -foo({ value: function value() {} }) -class C { x = function () {}; } -class C { x = function () {}; } -class C { 'x' = function () {}; } -class C { #x = function () {}; } -class C { #x = function () {}; } -class C { [x] = function () {}; } -class C { [x] = function () {}; } -class C { ['x'] = function () {}; } -class C { x = function x() {}; } -class C { 'x' = function x() {}; } -class C { #x = function x() {}; } -class C { #x = function x() {}; } -class C { #x = function y() {}; } -class C { #x = function y() {}; } -class C { [x] = function x() {}; } -class C { [x] = function x() {}; } -class C { [x] = function y() {}; } -class C { [x] = function y() {}; } -class C { ['x'] = function x() {}; } -class C { 1 = function x0() {}; } -class C { 1 = function x1() {}; } -class C { [1] = function x0() {}; } -class C { [1] = function x1() {}; } -class C { [f()] = function g() {}; } -class C { [f()] = function f() {}; } -class C { static x = function x() {}; } -class C { x = (function y() {})(); } -class C { x = (function x() {})(); } -(class { x = function x() {}; }) -class C { #x; foo() { this.#x = function x() {}; } } -class C { #x; foo() { this.#x = function x() {}; } } -class C { #x; foo() { this.#x = function y() {}; } } -class C { #x; foo() { this.#x = function y() {}; } } -class C { #x; foo() { a.b.#x = function x() {}; } } -class C { #x; foo() { a.b.#x = function x() {}; } } -class C { #x; foo() { a.b.#x = function y() {}; } } -class C { #x; foo() { a.b.#x = function y() {}; } } -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/func-names.md b/content/en/static_analysis/rules/javascript-code-style/func-names.md deleted file mode 100644 index 56d7921ad23e4..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/func-names.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/func-names - language: JavaScript - severity: Notice -title: Enforce named function expressions ---- -## Metadata -**ID:** `javascript-code-style/func-names` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -It is easier to debug your application code when you avoid anonymous functions so that the stack trace can show you meaningful error messages. This rule enforces all your function to be consistently declared with a name. - -## Non-Compliant Code Examples -```javascript -Foo.prototype.bar = function() {}; -(function(){}()) -f(function(){}) -var a = new Date(function() {}); -var test = function(d, e, f) {}; -new function() {} -Foo.prototype.bar = function() {}; -(function(){}()) -f(function(){}) -var a = new Date(function() {}); -new function() {} -var {foo} = function(){}; -({ a: obj.prop = function(){} } = foo); -[obj.prop = function(){}] = foo; -var { a: [b] = function(){} } = foo; -function foo({ a } = function(){}) {}; -export default function() {} -export default function() {} -export default (function(){}); -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -(function*() {}()) -var foo = bar(function *() {}); -(function*() {}()) -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -class C { foo = function() {} } -class C { [foo] = function() {} } -class C { #foo = function() {} } -``` - -## Compliant Code Examples -```javascript -Foo.prototype.bar = function bar(){}; -Foo.prototype.bar = () => {}; -function foo(){} -function test(d, e, f) {} -new function bar(){} -exports = { get foo() { return 1; }, set bar(val) { return val; } }; -({ foo() { return 1; } }); -class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} -function foo() {} -var a = function foo() {}; -class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} -({ foo() {} }); -function foo() {} -var a = function foo() { foo(); }; -class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} -({ foo() {} }); -export default function foo() {} -export default function foo() {} -export default function foo() {} -var foo = bar(function *baz() {}); -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/function-naming.md b/content/en/static_analysis/rules/javascript-code-style/function-naming.md deleted file mode 100644 index 3393ff12736c7..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/function-naming.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/function-naming - language: JavaScript - severity: Notice -title: Function name should use camelCase or PascalCase ---- -## Metadata -**ID:** `javascript-code-style/function-naming` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that the function uses `camelCase` or `PascalCase` in case it is an `Object`. Generator functions should always be `camelCase`. - -## Non-Compliant Code Examples -```javascript -function My_Class() {} -function get_value() {} -function* GetValue() {} -function *get_value() {} -``` - -## Compliant Code Examples -```javascript -function MyClass() {} -function getValue() {} -function* getValue() {} -function *getValue() {} -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/max-class-lines.md b/content/en/static_analysis/rules/javascript-code-style/max-class-lines.md deleted file mode 100644 index ce6be6365666d..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/max-class-lines.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/max-class-lines - language: JavaScript - severity: Warning -title: Classes must be less than 100 lines ---- -## Metadata -**ID:** `javascript-code-style/max-class-lines` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Code Style - -## Description -A class must stay short (less than 100 lines) to be easy to understand. If your class or function is more than 100 lines, you should refactor your code and ensure that your class is less than 100 lines. - -## Non-Compliant Code Examples -```javascript -class DummyClass { - constructor() { - this.name = "John"; - this.age = 30; - this.email = "john@example.com"; - this.address = "123 Main St"; - this.phone = "555-1234"; - this.salary = 50000; - this.skills = ["JavaScript", "HTML", "CSS"]; - this.projects = [ - { name: "Project 1", duration: 6 }, - { name: "Project 2", duration: 4 }, - { name: "Project 3", duration: 8 } - ]; - this.status = "active"; - - // Initialize more properties... - // ... - // ... - } - - sayHello() { - console.log(`Hello, my name is ${this.name}.`); - } - - calculateSalary() { - let total = this.salary; - for (let project of this.projects) { - total += project.duration * 1000; - } - return total; - } - - updateEmail(newEmail) { - if (newEmail.includes("@")) { - this.email = newEmail; - console.log("Email updated successfully."); - } else { - console.log("Invalid email format."); - } - } - - addSkill(skill) { - this.skills.push(skill); - console.log("Skill added."); - } - - removeSkill(skill) { - const index = this.skills.indexOf(skill); - if (index !== -1) { - this.skills.splice(index, 1); - console.log("Skill removed."); - } else { - console.log("Skill not found."); - } - } - - promote() { - if (this.status === "active") { - this.salary *= 1.1; - console.log("Promoted successfully."); - } else { - console.log("Cannot promote an inactive employee."); - } - } - - resign() { - if (this.status === "active") { - this.status = "inactive"; - console.log("Resigned successfully."); - } else { - console.log("Already inactive."); - } - } - - // More methods... - // ... - // ... - - // Long method 1 - longMethod1() { - // Implementation goes here... - // ... - // ... - } - - // Long method 2 - longMethod2() { - // Implementation goes here... - // ... - // ... - } - - // Long method 3 - longMethod3() { - // Implementation goes here... - // ... - // ... - } - - // Long method 4 - longMethod4() { - // Implementation goes here... - // ... - // ... - } - - // Long method 5 - longMethod5() { - // Implementation goes here... - // ... - // ... - } - - // More long methods... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final method - finalMethod() { - // Implementation goes here... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - } -} - -``` - -## Compliant Code Examples -```javascript -class DummyClass { - constructor() { - this.name = "John"; - this.age = 30; - this.email = "john@example.com"; - this.address = "123 Main St"; - this.phone = "555-1234"; - this.salary = 50000; - this.skills = ["JavaScript", "HTML", "CSS"]; - this.projects = [ - { name: "Project 1", duration: 6 }, - { name: "Project 2", duration: 4 }, - { name: "Project 3", duration: 8 } - ]; - this.status = "active"; - } - - sayHello() { - console.log(`Hello, my name is ${this.name}.`); - } - - calculateSalary() { - let total = this.salary; - for (let project of this.projects) { - total += project.duration * 1000; - } - return total; - } -} - -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/max-function-lines.md b/content/en/static_analysis/rules/javascript-code-style/max-function-lines.md deleted file mode 100644 index bdbd3a71d5fb0..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/max-function-lines.md +++ /dev/null @@ -1,952 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/max-function-lines - language: JavaScript - severity: Warning -title: Functions must be less than 200 lines ---- -## Metadata -**ID:** `javascript-code-style/max-function-lines` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Code Style - -## Description -This rule ensures that a function is not too long. A function should be less than 200 lines, or it will be hard to understand. - -## Non-Compliant Code Examples -```javascript -function dummyFunction() { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; -} - -() => { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; -} - -const dummyFunction = function() { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; -} - -class A { - dummyFunction() { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; - } -} -``` - -## Compliant Code Examples -```javascript -function myTest() { - // less than 200 lines -} - -() => { - // less than 200 lines -} - -class A { - foo() { - // less than 200 lines - } -} -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/max-params.md b/content/en/static_analysis/rules/javascript-code-style/max-params.md deleted file mode 100644 index cb1b6eeefb1d9..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/max-params.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/max-params - language: JavaScript - severity: Notice -title: Enforce a maximum number of parameters in a function ---- -## Metadata -**ID:** `javascript-code-style/max-params` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Having too many parameters can make your code hard to read. The parameters must be used in appropriate order. Forgetting the order of parameters can cause mistakes. - -Too many parameters is a code smell. You should refactor your code in smaller reusable bits. While it may be valid to require more than four parameters, you should use object destructuring. - -## Non-Compliant Code Examples -```javascript -function test(a, b, c, d) {} -var test = function(a, b, c, d, e) {}; -var test = (a, b, c, d) => {}; -(function(a, b, c, d) {}); - -// object property options -function test(a, b, c, d) {} -``` - -## Compliant Code Examples -```javascript -function test(d, e, f) {} -var test = function(a, b, c) {}; -var test = (a, b, c) => {}; -var test = function test(a, b, c) {}; - -// object property options -var test = function(a, b, c) {}; -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/method-name.md b/content/en/static_analysis/rules/javascript-code-style/method-name.md deleted file mode 100644 index 796934c2f46a4..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/method-name.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/method-name - language: JavaScript - severity: Notice -title: Method name should use camelCase ---- -## Metadata -**ID:** `javascript-code-style/method-name` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that method names use `camelCase` and not `snake_case` or `PascalCase`. - -## Non-Compliant Code Examples -```javascript -const a = { GetValue() {} } -class A { set_value() {} } -class A { *set_value() {} } -class A { #set_value() {} } -class A { #SetValue() {} } -``` - -## Compliant Code Examples -```javascript -const a = { getValue() {} } -class A { setValue() {} } -class A { #fooBla() {} } -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md b/content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md deleted file mode 100644 index 3339c7f635a70..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-array-constructor.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-code-style/no-array-constructor - language: JavaScript - severity: Warning -title: Avoid Array constructors ---- -## Metadata -**ID:** `javascript-code-style/no-array-constructor` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Array literal notation cannot be redefined. It is preferred over the Array constructor. - -The Array constructor is a common source of errors as it might behave unexpectedly when used with a single parameter. It creates an array with of N length instead of initializing an Array with the provided param. - - -## Non-Compliant Code Examples -```javascript -new Array(); -new Array; -new Array(x, y); -new Array(0, 1, 2); -``` - -## Compliant Code Examples -```javascript -new Array(x) -Array(x) -new Array(9) -Array(9) -new foo.Array() -foo.Array() -new Array.foo -Array.foo() -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-div-regex.md b/content/en/static_analysis/rules/javascript-code-style/no-div-regex.md deleted file mode 100644 index 27a9f99f26386..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-div-regex.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-code-style/no-div-regex - language: JavaScript - severity: Notice -title: Avoid equal signs at the beginning of regular expressions ---- -## Metadata -**ID:** `javascript-code-style/no-div-regex` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Error Prone - -## Description -At the start of a regular expression literal, the characters `/=` can be mistaken for a division assignment operator. - -## Non-Compliant Code Examples -```javascript -var f = function() { return /=foo/; }; -``` - -## Compliant Code Examples -```javascript -var f = function() { return /foo/ig.test('bar'); }; -var f = function() { return /\\=foo/; }; -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md b/content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md deleted file mode 100644 index 4c85eb60df2fa..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-duplicate-imports.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/no-duplicate-imports - language: JavaScript - severity: Warning -title: Avoid duplicate module imports ---- -## Metadata -**ID:** `javascript-code-style/no-duplicate-imports` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Single imports are easier to read and maintain you can see everything being imported from a module in one line. - -## Non-Compliant Code Examples -```javascript -import { merge } from 'module'; -import something from 'another-module'; -import { find } from 'module'; - -import something from 'something'; -import { find } from 'something'; -``` - -## Compliant Code Examples -```javascript -import { merge, find } from 'module'; -import something from 'another-module'; - -// not mergeable -import { merge } from 'something'; -import * as something from 'something'; -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md b/content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md deleted file mode 100644 index fe0a41431fb7f..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-floating-decimal.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/no-floating-decimal - language: JavaScript - severity: Notice -title: Avoid leading or trailing decimal points in numbers ---- -## Metadata -**ID:** `javascript-code-style/no-floating-decimal` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -To prevent confusion between the dot operator and the decimal point, always use a leading number when writing floating point numbers. - -## Non-Compliant Code Examples -```javascript -var x = .5; -var x = -.5; -var x = 2.; -var x = -2.; -typeof.2 -for(foo of.2); -``` - -## Compliant Code Examples -```javascript -var x = 2.5; -var x = "2.5"; -var t = { - ecmaVersion: 2018, -} -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md b/content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md deleted file mode 100644 index 4c5943ae33a29..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-lonely-if.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/no-lonely-if - language: JavaScript - severity: Notice -title: Avoid if statements as the only statement in else blocks ---- -## Metadata -**ID:** `javascript-code-style/no-lonely-if` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Prefers `else if` statement instead of an lonely `if` statement. Using `else if` statements` is a cleaner code practice. - -## Non-Compliant Code Examples -```javascript -if (a) {;} else { if (b) {;} } - -if (a) { - foo(); -} else { - if (b) { - bar(); - } -} - -if (a) { - foo(); -} else /* comment */ { - if (b) { - bar(); - } -} - - -if (a) { - foo(); -} else { - /* otherwise, do the other thing */ if (b) { - bar(); - } -} - -if (a) { - foo(); -} else { - if /* this comment is ok */ (b) { - bar(); - } -} - -if (a) { - foo(); -} else { - if (b) { - bar(); - } /* this comment will prevent this test case from being autofixed. */ -} -if (foo) {} else { if (bar) baz(); } - -// Not fixed; removing the braces would cause a SyntaxError. -if (foo) {} else { if (bar) baz() } qux(); - -// This is fixed because there is a semicolon after baz(). -if (foo) {} else { if (bar) baz(); } qux(); - -// Not fixed; removing the braces would change the semantics due to ASI. -if (foo) { -} else { - if (bar) baz() -} -[1, 2, 3].forEach(foo); - -// Not fixed; removing the braces would change the semantics due to ASI. -if (foo) { -} else { - if (bar) baz++ -} -foo; - -// This is fixed because there is a semicolon after baz++ -if (foo) { -} else { - if (bar) baz++; -} -foo; - -// Not fixed; bar() would be interpreted as a template literal tag -if (a) { - foo(); -} else { - if (b) bar() -} -`template literal`; - -if (a) { - foo(); -} else { - if (b) { - bar(); - } else if (c) { - baz(); - } else { - qux(); - } -} -``` - -## Compliant Code Examples -```javascript -if (a) {;} else if (b) {;} -if (a) {;} else { if (b) {;} ; } -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md b/content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md deleted file mode 100644 index f8f2ec267bb4b..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-multi-assign.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/no-multi-assign - language: JavaScript - severity: Notice -title: Avoid the use of chained assignment expressions ---- -## Metadata -**ID:** `javascript-code-style/no-multi-assign` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Assigning multiple variables at once can be hard to understand. Make one expression per assignment instead. - -## Non-Compliant Code Examples -```javascript -var a = b = c; -var a = b = c = d; -let foo = bar = cee = 100; -a=b=c=d=e; -a=b=c; -a -=b -=c; -var a = (b) = (((c))); -var a = ((b)) = (c); -var a = b = ( (c * 12) + 2); -var a = -((b)) - = (c); -a = b = '=' + c + 'foo'; -a = b = 7 * 12 + 5; -const x = {}; -const y = x.one = 1; -let a, b;a = b = 1; -let x, y;x = y = 'baz'; -const a = b = 1; -class C { field = foo = 0 } -class C { field = foo = 0 } -``` - -## Compliant Code Examples -```javascript -var a, b, c, -d = 0; -var a = 1; var b = 2; var c = 3; -var d = 0; -var a = 1 + (b === 10 ? 5 : 4); -const a = 1, b = 2, c = 3; -const a = 1; -const b = 2; -const c = 3; -for(var a = 0, b = 0;;){} -for(let a = 0, b = 0;;){} -for(const a = 0, b = 0;;){} -export let a, b; -export let a, - b = 0; -// ignore non declaration option not supported -// const x = {};const y = {};x.one = y.one = 1; -// let a, b;a = b = 1 -class C { [foo = 0] = 0 } -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-new-func.md b/content/en/static_analysis/rules/javascript-code-style/no-new-func.md deleted file mode 100644 index 535201a134fbe..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-new-func.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/no-new-func - language: JavaScript - severity: Warning -title: Avoid new operators with the Function object ---- -## Metadata -**ID:** `javascript-code-style/no-new-func` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -The Function constructor can lead to code similar to `eval` executions. Use function declarations instead of the Function constructor. - -## Non-Compliant Code Examples -```javascript -var a = new Function("b", "c", "return b+c"); -var a = Function("b", "c", "return b+c"); -var a = Function.call(null, "b", "c", "return b+c"); -var a = Function.apply(null, ["b", "c", "return b+c"]); -var a = Function.bind(null, "b", "c", "return b+c")(); -var a = Function.bind(null, "b", "c", "return b+c"); -var a = Function["call"](null, "b", "c", "return b+c"); -var a = (Function?.call)(null, "b", "c", "return b+c"); -const fn = () => { class Function {} }; new Function('', ''); -var fn = function () { function Function() {} }; Function('', ''); -``` - -## Compliant Code Examples -```javascript -var a = new _function("b", "c", "return b+c"); -var a = _function("b", "c", "return b+c"); -// Scoped re assign not supported -// class Function {}; new Function() -// const fn = () => { class Function {}; new Function() } -// function Function() {}; Function() -// var fn = function () { function Function() {}; Function() } -// var x = function Function() { Function(); } -call(Function) -new Class(Function) -foo[Function]() -foo(Function.bind) -Function.toString() -Function[call]() -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-new-object.md b/content/en/static_analysis/rules/javascript-code-style/no-new-object.md deleted file mode 100644 index c98e95a79f29e..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-new-object.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/no-new-object - language: JavaScript - severity: Notice -title: Avoid Object constructors ---- -## Metadata -**ID:** `javascript-code-style/no-new-object` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -For consistency, always use the shorter object literal notation `{}`. - -## Non-Compliant Code Examples -```javascript -var foo = new Object() -new Object(); -const a = new Object() - -``` - -## Compliant Code Examples -```javascript -// Scoped re declare not supported -var myObject = {}; -var myObject = new CustomObject(); -var foo = new foo.Object() -// var Object = function Object() {}; -// new Object(); -var x = something ? MyClass : Object; -var y = new x(); - -// class Object { -// constructor(){ - -// } -// } -// new Object(); - -// import { Object } from './' -// new Object(); - -const init = (canvas, context, t) => - drawDoughnutChart( - canvas, - t('Chats'), - context, - labels.map((l) => t(l)), - Object.values(initialData), - ); -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-new.md b/content/en/static_analysis/rules/javascript-code-style/no-new.md deleted file mode 100644 index 3a408e1f32114..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-new.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/no-new - language: JavaScript - severity: Notice -title: Avoid new operators outside of assignments or comparisons ---- -## Metadata -**ID:** `javascript-code-style/no-new` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -A lonely instance is almost always useless. Do not create objects without assigning them to a variable that you will use later. - -## Non-Compliant Code Examples -```javascript -new Date() -``` - -## Compliant Code Examples -```javascript -var a = new Date() -var a; if (a === new Date()) { a = false; } -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-return-assign.md b/content/en/static_analysis/rules/javascript-code-style/no-return-assign.md deleted file mode 100644 index 7e08d53cbb6be..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-return-assign.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-code-style/no-return-assign - language: JavaScript - severity: Notice -title: Avoid assignment operators in return statements ---- -## Metadata -**ID:** `javascript-code-style/no-return-assign` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Error Prone - -## Description -JavaScript allows return statements to do assignment operations. Because it is hard to differentiate between an assignment and a comparison when written as part of the return statement, avoid using return statements. - -## Non-Compliant Code Examples -```javascript -function x() { return result = a * b; }; -function x() { return (result) = (a * b); }; -function x() { return result = a * b; }; -function x() { return (result) = (a * b); }; -() => { return result = a * b; }; -() => result = a * b; -function x() { return result = a * b; }; -// Allow parens option not supported -// function x() { return (result = a * b); }; -// function x() { return result || (result = a * b); }; -function foo(){ - return a = b -} -function doSomething() { - return foo = bar && foo > 0; -} -function doSomething() { - return foo = function(){ - return (bar = bar1) - } -} -function doSomething() { - return foo = () => a -} -function doSomething() { - return () => a = () => b -} -function foo(a){ - return function bar(b){ - return a = b - } -} -const foo = (a) => (b) => a = b; - -``` - -## Compliant Code Examples -```javascript -module.exports = {'a': 1}; -var result = a * b; -function x() { var result = a * b; return result; } -function x() { return (result = a * b); } -function x() { var result = a * b; return result; } -function x() { return (result = a * b); } -function x() { var result = a * b; return result; } -function x() { return function y() { result = a * b }; } -() => { return (result = a * b); } -() => (result = a * b) -const foo = (a,b,c) => ((a = b), c) -function foo(){ - return (a = b) -} -function bar(){ - return function foo(){ - return (a = b) && c - } -} -const foo = (a) => (b) => (a = b) -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-self-compare.md b/content/en/static_analysis/rules/javascript-code-style/no-self-compare.md deleted file mode 100644 index 9bd32bb1d45e9..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-self-compare.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-code-style/no-self-compare - language: JavaScript - severity: Warning -title: Avoid comparisons where both sides are exactly the same ---- -## Metadata -**ID:** `javascript-code-style/no-self-compare` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Comparing a variable to itself is most likely a mistake. - -## Non-Compliant Code Examples -```javascript -if (x === x) { } -if (x !== x) { } -if (x > x) { } -if ('x' > 'x') { } -do {} while (x === x) -x === x -x !== x -x == x -x != x -x > x -x < x -x >= x -x <= x -foo.bar().baz.qux >= foo.bar().baz.qux -class C { #field; foo() { this.#field === this.#field; } } -``` - -## Compliant Code Examples -```javascript -if (x === y) { } -if (1 === 2) { } -y=x*x -foo.bar.baz === foo.bar.qux -class C { #field; foo() { this.#field === this['#field']; } } -class C { #field; foo() { this['#field'] === this.#field; } } -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/no-var.md b/content/en/static_analysis/rules/javascript-code-style/no-var.md deleted file mode 100644 index f9f6ddbc1c025..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/no-var.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/no-var - language: JavaScript - severity: Notice -title: Require let or const instead of var ---- -## Metadata -**ID:** `javascript-code-style/no-var` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Block scoped lexical declarations like `let` and `const` are preferred over `var`. Block scope is common in many other programming languages and helps programmers avoid mistakes. - -## Non-Compliant Code Examples -```javascript -var foo = bar; -var foo = bar, toast = most; -var foo = bar; let toast = most; -for (var a of b) { console.log(a); } -for (var a in b) { console.log(a); } -for (let a of b) { var c = 1; console.log(c); } -for (var i = 0; i < list.length; ++i) { foo(i) } -for (var i = 0; i < 10; ++i) {}; -for (var a of b) { arr.push(() => a); } -for (let a of b) { var c; console.log(c); c = 'hello'; } -var a = a; -var {a = a} = {}; -var {a = b, b} = {}; -let {a, b = a} = {}; -var a = b, b = 1; -let a = b; var b = 1; -function foo() { a } var a = 1; foo(); -if (foo) var bar = 1; -var foo = 1; -{ var foo = 1 } -if (true) { var foo = 1 } -var foo = 1; -declare var foo = 2; -function foo() { var let; } -function foo() { var { let } = {}; } -function foo() { a } -var a = 1; foo(); - -``` - -## Compliant Code Examples -```javascript -const JOE = 'schmoe'; -let moo = 'car'; -const JOE = 'schmoe'; -let moo = 'car'; -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/parameter-name.md b/content/en/static_analysis/rules/javascript-code-style/parameter-name.md deleted file mode 100644 index 224a4a7d62b24..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/parameter-name.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-code-style/parameter-name - language: JavaScript - severity: Notice -title: Parameter name should use camelCase ---- -## Metadata -**ID:** `javascript-code-style/parameter-name` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that parameter names use `camelCase` and not `snake_case` or `PascalCase`. - -## Non-Compliant Code Examples -```javascript -const a = { setValue(NewValue, event_info) {} } -class A { setValue(NewValue, event_info) {} } -function setValue(NewValue, event_info) {} -const a = function(NewValue, event_info) {} -``` - -## Compliant Code Examples -```javascript -const a = { getValue() {} } -class A { setValue(newValue) {} } -class B { setValue(md5, valid5String) {} } -``` diff --git a/content/en/static_analysis/rules/javascript-code-style/radix.md b/content/en/static_analysis/rules/javascript-code-style/radix.md deleted file mode 100644 index b9659fd12d6b9..0000000000000 --- a/content/en/static_analysis/rules/javascript-code-style/radix.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: javascript-code-style/radix - language: JavaScript - severity: Notice -title: Consistent use of the radix argument using parseInt ---- -## Metadata -**ID:** `javascript-code-style/radix` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When utilizing the `parseInt()` function, many often skip the second parameter (the radix), allowing the function to deduce the number type based on the initial argument. By default, `parseInt()` can recognize both decimal and hexadecimal numbers, the latter through the `0x` prefix. However, before ECMAScript 5, the function also mistakenly recognized octal numbers, leading to issues as many developers presumed a starting `0` would be disregarded. - -## Non-Compliant Code Examples -```javascript -parseInt(); -parseInt(); -parseInt("10"); -parseInt("10",); -parseInt((0, "10")); -parseInt((0, "10"),); -parseInt("10", null); -parseInt("10", undefined); -parseInt("10", true); -parseInt("10", "foo"); -parseInt("10", "123"); -parseInt("10", 1); -parseInt("10", 37); -parseInt("10", 10.5); -Number.parseInt(); -Number.parseInt(); -Number.parseInt("10"); -Number.parseInt("10", 1); -Number.parseInt("10", 37); -Number.parseInt("10", 10.5); -parseInt?.("10"); -Number.parseInt?.("10"); -Number?.parseInt("10"); -(Number?.parseInt)("10"); - -``` - -## Compliant Code Examples -```javascript -parseInt("10", 10); -parseInt("10", 2); -parseInt("10", 36); -parseInt("10", 0x10); -parseInt("10", 1.6e1); -parseInt("10", 10.0); -parseInt("10", foo); -Number.parseInt("10", foo); -parseInt("10", 10); -parseInt("10", 8); -parseInt("10", foo); -parseInt -Number.foo(); -Number[parseInt](); -class C { #parseInt; foo() { Number.#parseInt(); } } -class C { #parseInt; foo() { Number.#parseInt(foo); } } -class C { #parseInt; foo() { Number.#parseInt(foo, 'bar'); } } -class C { #parseInt; foo() { Number.#parseInt(foo, 10); } } - -// shadowed not supported -// Ignores if it's shadowed or disabled. -// var parseInt; parseInt(); -// var parseInt; parseInt(foo); -// var parseInt; parseInt(foo, 10); -// var Number; Number.parseInt(); -// var Number; Number.parseInt(foo); -// var Number; Number.parseInt(foo, 10); -// /* globals parseInt:off */ parseInt(foo); -// Number.parseInt(foo, 10); -``` diff --git a/content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md b/content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md deleted file mode 100644 index ee02662c52725..0000000000000 --- a/content/en/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-common-security/axios-avoid-insecure-http - language: JavaScript - severity: Warning -title: Avoid insecure HTTP requests with Axios ---- -## Metadata -**ID:** `javascript-common-security/axios-avoid-insecure-http` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Avoid connecting to `http` services. Use `https` services for security reasons. - -## Non-Compliant Code Examples -```javascript -const dataFromBackend = axios.get('http://backend.my.app') - -``` - -## Compliant Code Examples -```javascript -const dataFromBackend = axios.get('https://backend.my.app') - -``` diff --git a/content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md b/content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md deleted file mode 100644 index 8cc13eab0e20e..0000000000000 --- a/content/en/static_analysis/rules/javascript-common-security/unique-function-arguments.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-common-security/unique-function-arguments - language: JavaScript - severity: Warning -title: Function argument names should be unique ---- -## Metadata -**ID:** `javascript-common-security/unique-function-arguments` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -A function's parameter names should all be unique. Otherwise, a latter parameter will overwrite the former parameter. This behavior can lead to unintended bugs and it difficult to debug in the future. - -## Non-Compliant Code Examples -```javascript -function addition(foo, bar, foo) { - console.log(foo + bar + foo); -} - -addition(1, 2, 3); // outputs 8 -``` - -## Compliant Code Examples -```javascript -function addition(foo, bar, baz) { - console.log(foo + bar + baz); -} - -addition(1, 2, 3); // outputs 6 -``` diff --git a/content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md b/content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md deleted file mode 100644 index 7d3637d95d17a..0000000000000 --- a/content/en/static_analysis/rules/javascript-common-security/xml-no-external-entities.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-common-security/xml-no-external-entities - language: JavaScript - severity: Warning -title: Do not use external XML entities ---- -## Metadata -**ID:** `javascript-common-security/xml-no-external-entities` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Process external entities in XML files may lead to XXE attack. Do not load external entities unless they have been explicitly checked. - -## Non-Compliant Code Examples -```javascript -var libxmljs = require('libxmljs'); -var fs = require('fs'); - -var xml = fs.readFileSync('file.xml', 'utf8'); -libxmljs.parseXmlString(xml, { - noent: true, -}); -``` - -## Compliant Code Examples -```javascript -var libxmljs = require('libxmljs'); -var fs = require('fs'); - -var xml = fs.readFileSync('file.xml', 'utf8'); -libxmljs.parseXmlString(xml); - -``` diff --git a/content/en/static_analysis/rules/javascript-express/access-restriction.md b/content/en/static_analysis/rules/javascript-express/access-restriction.md deleted file mode 100644 index 3d5615bb3ba53..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/access-restriction.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/access-restriction - language: JavaScript - severity: Warning -title: Limit exposure to sensitive directories and files ---- -## Metadata -**ID:** `javascript-express/access-restriction` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Exposing a directory listing could present an attacker an opportunity to access source code or other sensitive data through a file structure exploit. Restricting access to non-sensitive directories and files is strongly suggested. - -#### Learn More -- [Express Serve index middleware](https://expressjs.com/en/resources/middleware/serve-index.html) - - -## Non-Compliant Code Examples -```javascript -const express = require("express") -const serveIndex = require("serve-index") - -const app = express() - -app.use(serveIndex()) -``` - -## Compliant Code Examples -```javascript -const express = require("express") -const serveIndex = require("serve-index") - -const app = express() - -app.use(serveIndex("/public")) -``` diff --git a/content/en/static_analysis/rules/javascript-express/default-session-config.md b/content/en/static_analysis/rules/javascript-express/default-session-config.md deleted file mode 100644 index 004aa7cfe9a7b..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/default-session-config.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/default-session-config - language: JavaScript - severity: Warning -title: Enforce overriding default config ---- -## Metadata -**ID:** `javascript-express/default-session-config` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Avoid leaving your session cookies open to exploits or unauthorized access, by overriding default values. - -Setting the `name` value to something generic is better than using the default value. - -#### Learn More -- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) - -## Non-Compliant Code Examples -```javascript -const session = require('express-session') - -app.use( - session({ - secret: "secret" - }) -) -``` - -## Compliant Code Examples -```javascript -const session = require('express-session') - -app.use( - session({ - secret: "secret", - name: 'sessionId' - }) -) -``` diff --git a/content/en/static_analysis/rules/javascript-express/external-filename-upload.md b/content/en/static_analysis/rules/javascript-express/external-filename-upload.md deleted file mode 100644 index 4d9a525b5f9a0..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/external-filename-upload.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/external-filename-upload - language: JavaScript - severity: Warning -title: Avoid using unsanitized user input with sendFile ---- -## Metadata -**ID:** `javascript-express/external-filename-upload` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Using unsanitized user input in a `sendFile` method can allow attackers to access unintended resources. - -Set the `root` option directly in your `sendFile` options will make this rule not report a violation. - -#### Learn More -- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile) - -## Non-Compliant Code Examples -```javascript -app.post("/upload", (req, res) => { - res.sendFile(req.params.filename) - - // options passed, but no root set - res.sendFile(req.params.filename, { maxAge: 0 }) - - // options passed, but no root set, and a callback is set - res.sendFile(req.params.filename, { maxAge: 0 }, (err) => console.log(err)) -}) -``` - -## Compliant Code Examples -```javascript -app.post("/upload", (req, res) => { - res.sendFile("foo") - - const options = { maxAge: 0, root: path.join(__dirname, "upload") } - - // options with root set - res.sendFile(req.params.filename, options) - res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }) - - // options with root set (and a callback is set) - res.sendFile(req.params.filename, options, (err) => console.log(err)) - res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }, (err) => console.log(err)) -}) -``` diff --git a/content/en/static_analysis/rules/javascript-express/external-resource.md b/content/en/static_analysis/rules/javascript-express/external-resource.md deleted file mode 100644 index 5a1ef1e4fa466..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/external-resource.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/external-resource - language: JavaScript - severity: Warning -title: Avoid rendering resource based on unsanitized user input ---- -## Metadata -**ID:** `javascript-express/external-resource` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Rendering resources based on unsanitized user input should be avoided. At a minimum, one should use a safelist to restrict the potential resources that are exposed. - -## Non-Compliant Code Examples -```javascript -app.get("/", (req, res) => { - res.render(req.body.path) - res.render(req.cookies.path) - res.render(req.headers.path) - res.render(req.params.path) - res.render(req.query.path) -}) -``` - -## Compliant Code Examples -```javascript -app.get("/", (req, res) => { - const path = req.body.path - if (["posts", "pages"].includes(path)) { - return res.render(`${path}/success`) - } - res.render("error-page") -}) -``` diff --git a/content/en/static_analysis/rules/javascript-express/hardcoded-secret.md b/content/en/static_analysis/rules/javascript-express/hardcoded-secret.md deleted file mode 100644 index e0728d9692ce0..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/hardcoded-secret.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/hardcoded-secret - language: JavaScript - severity: Warning -title: Avoid using a hard-coded secret ---- -## Metadata -**ID:** `javascript-express/hardcoded-secret` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not store secrets in plaintext where they are used. Instead use environment variables (`process.env.`) or better yet, use a key management service (KMS) linked below that includes encryption. - -#### Learn More -- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password) -- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs) -- [AWS Key Management Service](https://aws.amazon.com/kms/) - -## Non-Compliant Code Examples -```javascript -import session from "express-session" -import { expressjwt } from "express-jwt" - -app.use( - session({ - name: "session-name", - secret: "not-secret-secret", - secret: `${isProd ? "prod-secret" : "dev-secret"}`, - }) -) - -app.use( - expressjwt({ - name: "session-name", - secret: "not-secret-secret", - secret: `${isProd ? "prod-secret" : "dev-secret"}`, - }) -) -``` - -## Compliant Code Examples -```javascript -import session from "express-session" -import { expressjwt } from "express-jwt" - -app.use( - session({ - name: "session-name", - secret: process.env.SECRET - }) -) - -app.use( - expressjwt({ - name: "session-name", - secret: process.env.SECRET - }) -) -``` diff --git a/content/en/static_analysis/rules/javascript-express/https-protocol-missing.md b/content/en/static_analysis/rules/javascript-express/https-protocol-missing.md deleted file mode 100644 index 26a5177a95114..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/https-protocol-missing.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/https-protocol-missing - language: JavaScript - severity: Warning -title: Use `https` protocol over `http` ---- -## Metadata -**ID:** `javascript-express/https-protocol-missing` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-tls): - -> If your app deals with or transmits sensitive data, use [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS) to secure the connection and the data. This technology encrypts data before it is sent from the client to the server, thus preventing some common (and easy) hacks. - -This rule will detect the usage of non `https.createServer()` usage. - -## Non-Compliant Code Examples -```javascript -var http = require('http'); -var express = require('express'); -var app = express(); - -var httpServer = http.createServer(app) -httpServer.listen(8080); -``` - -## Compliant Code Examples -```javascript -var https = require('https'); -var express = require('express'); -var app = express(); - -var httpsServer = https.createServer(app) -httpsServer.listen(8080); -``` diff --git a/content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md b/content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md deleted file mode 100644 index 22a1ec7c06bb2..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/insecure-allow-origin.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/insecure-allow-origin - language: JavaScript - severity: Warning -title: Avoid using an insecure Access-Control-Allow-Origin header ---- -## Metadata -**ID:** `javascript-express/insecure-allow-origin` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Setting an Access-Control-Allow-Origin header with an unverified user-defined input can lead to sharing sensitive data with an unintended user. - -If this is unavoidable, consider comparing the input against a safe-list. - -#### Learn More - -- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing) - - -## Non-Compliant Code Examples -```javascript -app.get('/', function (req, res) { - res.set('Access-Control-Allow-Origin', req.headers.foo) - res.set({ "foo": "bar", 'Access-Control-Allow-Origin': req.query.foo }) - res.header('Access-Control-Allow-Origin', req.params.foo) - res.setHeader('Access-Control-Allow-Origin', req.body.foo); - res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': req.cookies.foo }) -}); -``` - -## Compliant Code Examples -```javascript -app.get('/', function (req, res) { - res.set('Access-Control-Allow-Origin', "foo_url") - res.set({ "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) - res.header('Access-Control-Allow-Origin', "foo_url") - res.setHeader('Access-Control-Allow-Origin', "foo_url"); - res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) -}); -``` diff --git a/content/en/static_analysis/rules/javascript-express/insecure-cookie.md b/content/en/static_analysis/rules/javascript-express/insecure-cookie.md deleted file mode 100644 index 41437cf1512ba..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/insecure-cookie.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/insecure-cookie - language: JavaScript - severity: Warning -title: Avoid setting insecure cookie settings ---- -## Metadata -**ID:** `javascript-express/insecure-cookie` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -When using cookies in your application, one should ensure appropriate security options are set to lessen the risk of exploits and unauthorized users. - -This rule will detect when `secure` and `httpOnly` are set to `false` in a multitude of ways. - -#### Learn More - -- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) - -## Non-Compliant Code Examples -```javascript -const cookie = { - secure: false, - httpOnly: false, -} - -const options = { - cookie: { - secure: false, - httpOnly: false, - } -} - -cookieSession({ secure: false }) -``` - -## Compliant Code Examples -```javascript -const cookie = { - secure: true, - httpOnly: true, -} - -const options = { - cookie: { - secure: true, - httpOnly: true, - } -} - -cookieSession({ secure: true }) -``` diff --git a/content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md b/content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md deleted file mode 100644 index ce347e4e9df06..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/jwt-not-revoked.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/jwt-not-revoked - language: JavaScript - severity: Warning -title: Ensure an isRevoked method is used for tokens ---- -## Metadata -**ID:** `javascript-express/jwt-not-revoked` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Consider a method to revoke JWTs, especially when they contain sensitive information, to ensure they remain short-lived. - -#### Learn More -- [ExpressJWT revoking documentation](https://github.com/auth0/express-jwt#revoked-tokens) - -## Non-Compliant Code Examples -```javascript -const { expressjwt: jwt } = require("express-jwt") - -app.get( - "/protected", - jwt({ - secret: "shhhhhhared-secret", - algorithms: ["HS256"] - }), - function (req, res) { - if (!req.auth.admin) return res.sendStatus(401); - res.sendStatus(200); - } -); -``` - -```javascript -import { expressjwt } from "express-jwt"; - -app.get( - "/protected", - expressjwt({ - secret: "shhhhhhared-secret", - algorithms: ["HS256"], - }), - function (req, res) { - if (!req.auth.admin) return res.sendStatus(401); - res.sendStatus(200); - } -); -``` - -## Compliant Code Examples -```javascript -const { expressjwt } = require("express-jwt") - -app.get( - "/protected", - expressjwt({ - secret: "shhhhhhared-secret", - algorithms: ["HS256"], - isRevoked: isRevokedCallback, - }), - function (req, res) { - if (!req.auth.admin) return res.sendStatus(401); - res.sendStatus(200); - } -); -``` - -```javascript -import { expressjwt as jwt } from "express-jwt"; - -app.get( - "/protected", - jwt({ - secret: "shhhhhhared-secret", - algorithms: ["HS256"], - isRevoked: isRevokedCallback, - }), - function (req, res) { - if (!req.auth.admin) return res.sendStatus(401); - res.sendStatus(200); - } -); -``` diff --git a/content/en/static_analysis/rules/javascript-express/missing-helmet.md b/content/en/static_analysis/rules/javascript-express/missing-helmet.md deleted file mode 100644 index ad54e76c6607d..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/missing-helmet.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/missing-helmet - language: JavaScript - severity: Warning -title: Express application should use Helmet ---- -## Metadata -**ID:** `javascript-express/missing-helmet` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-helmet): - -> [Helmet](https://helmetjs.github.io/) can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately. - -This rule will check whether you've set `app.use(helmet())` within the file that you've called `express()` - -## Non-Compliant Code Examples -```javascript -const express = require("express") - -const app = express(); - -// no `app.use(helmet())` helmet detected in the file - -app.get("/foo", (req, res) => res.send("foo")); - -app.listen(8000); -``` - -## Compliant Code Examples -```javascript -const express = require("express") -const helmet = require("helmet") - -const app = express(); - -app.use(json()); // helmet detected -app.use(helmet()); // helmet detected - -app.get("/foo", (req, res) => res.send("foo")); - -app.listen(8000); -``` - -```javascript -import express from "express" -import helmet from "helmet" - -const app = express(); - -app.use(helmet()); // helmet detected - -app.get("/foo", (req, res) => res.send("foo")); - -app.listen(8000); -``` diff --git a/content/en/static_analysis/rules/javascript-express/path-traversal.md b/content/en/static_analysis/rules/javascript-express/path-traversal.md deleted file mode 100644 index df525854d8474..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/path-traversal.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/path-traversal - language: JavaScript - severity: Warning -title: Avoid allowing access to unintended directories or files ---- -## Metadata -**ID:** `javascript-express/path-traversal` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -By not sanitizing user input prior to using it in path resolution methods you open your application's access to unintended directories and files. - -> If you're using `replace` on a user input, this rule will assume you've done so correctly and will not report a violation - -#### Learn More -- [OWASP path traversal](https://owasp.org/www-community/attacks/Path_Traversal) - -## Non-Compliant Code Examples -```javascript -const path = require("path"); - -app.get("/", (req, res) => { - path.join("/user/", req.params.path) - - var pathname = path.join("/public/", req.body.foo) - path.resolve(pathname) - - path.resolve(__dirname, req.body.foo) - path.resolve(__dirname, `${req.body.foo}`) -}) -``` - -## Compliant Code Examples -```javascript -const path = require("path"); - -app.get("/", (req, res) => { - path.join("/user/", req.params.path.replace(/^(\.\.(\/|\\|$))+/, '')) - - var pathname = path.join("/public/", req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) - path.resolve(pathname) - - path.resolve(__dirname, req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) - path.resolve(__dirname, `${req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')}`) -}) -``` diff --git a/content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md b/content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md deleted file mode 100644 index c84c7296c3d0f..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/reduce-server-fingerprinting.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/reduce-server-fingerprinting - language: JavaScript - severity: Warning -title: Server fingerprinting misconfiguration ---- -## Metadata -**ID:** `javascript-express/reduce-server-fingerprinting` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Improve your overall server security by taking the step to reduce the likelihood of server fingerprinting the software being used on the server. - -By default, Express.js sends the `X-Powered-By` response header banner which can be disabled with `app.disable('X-Powered-By')`. - -If you're using `helmet`, you can use either of these methods too: -- `app.use(hidePoweredBy())` -- `app.use(helmet.hidePoweredBy())` - -#### Learn More -- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html) - -## Non-Compliant Code Examples -```javascript -const app = express() - -// express() is called but none of the following were detected afterwards -// app.disable('x-powered-by') -// app.use(hidePoweredBy()) -// app.use(helmet.hidePoweredBy()) -``` - -## Compliant Code Examples -```javascript -const app = express() - -app.use(helmet.hidePoweredBy()); - -// rest of your config -``` - -```javascript -const app = express() - -app.use(hidePoweredBy()) - -// rest of your config -``` - -```javascript -const app = express() - -app.disable('x-powered-by') - -// rest of your config -``` diff --git a/content/en/static_analysis/rules/javascript-express/xss-vulnerability.md b/content/en/static_analysis/rules/javascript-express/xss-vulnerability.md deleted file mode 100644 index 93f5223b447e8..0000000000000 --- a/content/en/static_analysis/rules/javascript-express/xss-vulnerability.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-express/xss-vulnerability - language: JavaScript - severity: Warning -title: Avoid sending unsanitized user input in response ---- -## Metadata -**ID:** `javascript-express/xss-vulnerability` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Returning unsanitized user input in a `send` or `write` method can increase your application's risk of cross-site scripting attacks. - -#### Learn More -- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) - -## Non-Compliant Code Examples -```javascript -app.get("/", (req, res) => { - res.send(req.body.foo); - res.send({ title: "foo", message: req.body.foo }); - res.write(req.body.foo); - res.write({ title: "foo", message: req.body.foo }); -}) -``` - -## Compliant Code Examples -```javascript -app.get("/", (req, res) => { - res.send("foo"); - res.send({ title: "foo", message: 'foo' }); - res.write("foo"); - res.write({ title: "foo", message: 'foo' }); -}) -``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/comments.md b/content/en/static_analysis/rules/javascript-inclusive/comments.md deleted file mode 100644 index 50f065567a676..0000000000000 --- a/content/en/static_analysis/rules/javascript-inclusive/comments.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-inclusive/comments - language: JavaScript - severity: Notice -title: Check comments for wording issues ---- -## Metadata -**ID:** `javascript-inclusive/comments` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Check the variable names and suggest better names. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```javascript -/** - * whitelist names to prevent unauthorized usage - */ - -// she SHE should check her code - -// he should check his -``` - -## Compliant Code Examples -```javascript -// allowlist names to prevent unauthorized usage - -/* the comments do not have a history of issues */ -``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/declarations.md b/content/en/static_analysis/rules/javascript-inclusive/declarations.md deleted file mode 100644 index e4dee86c4de12..0000000000000 --- a/content/en/static_analysis/rules/javascript-inclusive/declarations.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-inclusive/declarations - language: JavaScript - severity: Notice -title: Check declaration names for wording issues ---- -## Metadata -**ID:** `javascript-inclusive/declarations` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that some words are not used in the codebase and suggest a replacement when appropriate. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```javascript -function foo_blacklist() {} -a(function *blackList() {}); -function *whItEList() {} -function blacklist_names() {} -function whiteList() {} -class WhiteList {} -const slave = 0; -let master = ""; -var slave = b; -``` - -## Compliant Code Examples -```javascript -function foo_denyList() {} -a(function *allowedList() {}); -class primary {} -const secondary = 0; -``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md b/content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md deleted file mode 100644 index 8aa4632254173..0000000000000 --- a/content/en/static_analysis/rules/javascript-inclusive/formal-parameters.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-inclusive/formal-parameters - language: JavaScript - severity: Notice -title: Check parameter names for wording issues ---- -## Metadata -**ID:** `javascript-inclusive/formal-parameters` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that some words are not used in the codebase and suggest a replacement when appropriate. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```javascript -function a(master, slave) {} -function a(blacklist, whitelist) {} -class A { foo(master, slave) {} } - -``` - -## Compliant Code Examples -```javascript -function denyList(primary, secondary) {} -``` diff --git a/content/en/static_analysis/rules/javascript-inclusive/identifiers.md b/content/en/static_analysis/rules/javascript-inclusive/identifiers.md deleted file mode 100644 index a2b7f7b3ceb2b..0000000000000 --- a/content/en/static_analysis/rules/javascript-inclusive/identifiers.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: javascript-inclusive/identifiers - language: JavaScript - severity: Notice -title: Check identifier names for wording issues ---- -## Metadata -**ID:** `javascript-inclusive/identifiers` - -**Language:** JavaScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that some words are not used in the codebase and suggest a replacement when appropriate. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```javascript -{ slave: false } -const a = { 'master': false, }; -const a = { ['master']: false, }; -const a = { c, ...blacklist } = b; -const { whitelist } = b; -const a = { whitelist }; -const { whitelist: slave } = b; -[slave, ...master] = blacklist; -``` - -## Compliant Code Examples -```javascript -{ secondary: false } -const a = { 'primary': false, }; -const a = { c, ...denylist } = b; -const { AllowedList } = b; -[primary, ...secondary] = b; -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/argon2.md b/content/en/static_analysis/rules/javascript-node-security/argon2.md deleted file mode 100644 index 4a25b25f2f5b7..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/argon2.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/argon2 - language: JavaScript - severity: Error -title: Use strong security mechanisms with argon2 ---- -## Metadata -**ID:** `javascript-node-security/argon2` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Security - -## Description -Use secure and fast security mechanisms with using `argon2`. - -#### Learn More - - - [argon2 types](https://github.com/ranisalt/node-argon2/wiki/Options#type) - -## Non-Compliant Code Examples -```javascript -await argon2.hash('password', {type: argon2.argon2d}) -await argon2.hash('password', {type: argon2.argon2i}) -``` - -## Compliant Code Examples -```javascript -await argon2.hash('password', {type: argon2.argon2id}) -await argon2.hash('password', {}) -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md b/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md deleted file mode 100644 index 50aa4459f5f83..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-rc4.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/avoid-crypto-rc4 - language: JavaScript - severity: Warning -title: Avoid RC4 ---- -## Metadata -**ID:** `javascript-node-security/avoid-crypto-rc4` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of RC4 security protocol exposes your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library, RC4](https://cryptojs.gitbook.io/docs/#ciphers) - -## Non-Compliant Code Examples -```javascript -var encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase"); -var decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase"); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md b/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md deleted file mode 100644 index 86e7a5d06c0f5..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/avoid-crypto-sha1.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/avoid-crypto-sha1 - language: JavaScript - severity: Warning -title: Avoid SHA1 security protocol ---- -## Metadata -**ID:** `javascript-node-security/avoid-crypto-sha1` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of insecure encryption or hashing protocols expose your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hmac) - -## Non-Compliant Code Examples -```javascript -var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase"); -var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase", anotherargument); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/avoid-des.md b/content/en/static_analysis/rules/javascript-node-security/avoid-des.md deleted file mode 100644 index 3d81669904739..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/avoid-des.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/avoid-des - language: JavaScript - severity: Warning -title: Avoid DES and 3DES ---- -## Metadata -**ID:** `javascript-node-security/avoid-des` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of insecure encryption or hashing protocols expose your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library, DES and TripleDES](https://cryptojs.gitbook.io/docs/#ciphers) - -## Non-Compliant Code Examples -```javascript -var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase"); -var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase"); -var encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase"); -var decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase"); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md b/content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md deleted file mode 100644 index e4bf7406abe16..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/chmod-permissions.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/chmod-permissions - language: JavaScript - severity: Warning -title: Do not give 777 permissions to a file ---- -## Metadata -**ID:** `javascript-node-security/chmod-permissions` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always make sure you restrict permissions of your application files. Application files should not allow write and execution for other users as it may leak data and information. Always restrict the number of users and applications that can access your application data. - -## Non-Compliant Code Examples -```javascript -const fs = require('fs'); -const fsPromises = fs.promises; - -fs.chmodSync("/tmp/myfile", 0o777); -fsPromises.chmod("/tmp/fsPromises", 0o777); - -``` - -## Compliant Code Examples -```javascript -const fs = require('fs'); -const fsPromises = fs.promises; - -fs.chmodSync(myPath, 0o770); -fsPromises.chmod("/tmp/fsPromises", 0o770); - -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/command-injection.md b/content/en/static_analysis/rules/javascript-node-security/command-injection.md deleted file mode 100644 index 8885513efbea7..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/command-injection.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/command-injection - language: JavaScript - severity: Warning -title: Avoid command injection ---- -## Metadata -**ID:** `javascript-node-security/command-injection` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -When executing a command, never use unchecked variables. Make sure that each variable in the command has been checked. - -## Non-Compliant Code Examples -```javascript -childprocess.exec(`mv ${src} ${dst}`, (error, stdout, stderr) => {}); -childprocess.exec('mv ' + src + " " + dst, (error, stdout, stderr) => {}); -``` - -## Compliant Code Examples -```javascript -childprocess.exec('mv /tmp/src /tmp/dst', (error, stdout, stderr) => {}); - -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md b/content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md deleted file mode 100644 index 1390784e384a8..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/crypto-avoid-weak-hash - language: JavaScript - severity: Warning -title: Avoid weak hash algorithm from CryptoJS ---- -## Metadata -**ID:** `javascript-node-security/crypto-avoid-weak-hash` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of insecure hash functions like MD5 or SHA1 can expose your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hashing) - -## Non-Compliant Code Examples -```javascript -var hash = CryptoJS.MD5("Message", "Secret Passphrase"); -var hash = CryptoJS.SHA1("Message", "Secret Passphrase"); -var hash = CryptoJS.HmacMD5("Message", "Secret Passphrase"); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md b/content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md deleted file mode 100644 index de4d79a17bcaf..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detect-buffer-noassert.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/detect-buffer-noassert - language: JavaScript - severity: Error -title: Avoid calls to 'buffer' with 'noAssert' flag set ---- -## Metadata -**ID:** `javascript-node-security/detect-buffer-noassert` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Security - -## Description -Avoid calls to [`buffer`](https://nodejs.org/api/buffer.html) with `noAssert`. If you skip the `offset` validation it can go beyond the end of the `Buffer`. - -## Non-Compliant Code Examples -```javascript -a.readUInt8(0, true) -a.readUInt16LE(0, true) -a.readUInt16BE(0, true) -a.readUInt32LE(0, true) -a.readUInt32BE(0, true) -a.readInt8(0, true) -a.readInt16LE(0, true) -a.readInt16BE(0, true) -a.readInt32LE(0, true) -a.readInt32BE(0, true) -a.readFloatLE(0, true) -a.readFloatBE(0, true) -a.readDoubleLE(0, true) -a.readDoubleBE(0, true) -a.writeUInt8(0, 0, true) -a.writeUInt16LE(0, 0, true) -a.writeUInt16BE(0, 0, true) -a.writeUInt32LE(0, 0, true) -a.writeUInt32BE(0, 0, true) -a.writeInt8(0, 0, true) -a.writeInt16LE(0, 0, true) -a.writeInt16BE(0, 0, true) -a.writeInt32LE(0, 0, true) -a.writeInt32BE(0, 0, true) -a.writeFloatLE(0, 0, true) -a.writeFloatBE(0, 0, true) -a.writeDoubleLE(0, 0, true) -a.writeDoubleBE(0, 0, true) - -``` - -## Compliant Code Examples -```javascript -a.readUInt8(0) -a.readUInt16LE(0) -a.readUInt16BE(0) -a.readUInt32LE(0) -a.readUInt32BE(0) -a.readInt8(0) -a.readInt16LE(0) -a.readInt16BE(0) -a.readInt32LE(0) -a.readInt32BE(0) -a.readFloatLE(0) -a.readFloatBE(0) -a.readDoubleLE(0) -a.readDoubleBE(0) -a.writeUInt8(0) -a.writeUInt16LE(0) -a.writeUInt16BE(0) -a.writeUInt32LE(0) -a.writeUInt32BE(0) -a.writeInt8(0) -a.writeInt16LE(0) -a.writeInt16BE(0) -a.writeInt32LE(0) -a.writeInt32BE(0) -a.writeFloatLE(0) -a.writeFloatBE(0) -a.writeDoubleLE(0) -a.writeDoubleBE(0) -a.readUInt8(0, false) -a.readUInt16LE(0, false) -a.readUInt16BE(0, false) -a.readUInt32LE(0, false) -a.readUInt32BE(0, false) -a.readInt8(0, false) -a.readInt16LE(0, false) -a.readInt16BE(0, false) -a.readInt32LE(0, false) -a.readInt32BE(0, false) -a.readFloatLE(0, false) -a.readFloatBE(0, false) -a.readDoubleLE(0, false) -a.readDoubleBE(0, false) -a.writeUInt8(0, false) -a.writeUInt16LE(0, false) -a.writeUInt16BE(0, false) -a.writeUInt32LE(0, false) -a.writeUInt32BE(0, false) -a.writeInt8(0, false) -a.writeInt16LE(0, false) -a.writeInt16BE(0, false) -a.writeInt32LE(0, false) -a.writeInt32BE(0, false) -a.writeFloatLE(0, false) -a.writeFloatBE(0, false) -a.writeDoubleLE(0, false) -a.writeDoubleBE(0, false) -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-child-process.md b/content/en/static_analysis/rules/javascript-node-security/detect-child-process.md deleted file mode 100644 index 9510ed7134926..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detect-child-process.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: javascript-node-security/detect-child-process - language: JavaScript - severity: Warning -title: Avoid instances of 'child_process' and non-literal 'exec()' ---- -## Metadata -**ID:** `javascript-node-security/detect-child-process` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -In Node.js, the "child_process" module provides capabilities to execute shell commands directly. While this might seem beneficial, it comes with significant security risks. If the input to this module isn't properly sanitized, it can pave the way for command injection attacks. In such attacks, malicious actors could introduce harmful commands, which, when executed, could compromise system integrity or lead to data breaches. - -Additionally, using non-literal arguments with "exec()" presents another challenge. When arguments to "exec()" are dynamic or derived from untrusted sources, there's a risk that attackers could manipulate this input. This makes the system vulnerable to unauthorized actions, potentially causing significant damage. Therefore, for a more secure Node.js application, it's advised to tread cautiously with these features, employing rigorous input validation and considering safer alternatives. - -## Non-Compliant Code Examples -```javascript -require('child_process') -require('node:child_process') -var child = require('child_process'); child.exec(com) -var nodeChild = require('node:child_process'); nodeChild.exec(com) -import childImport from 'child_process'; childImport.exec(com) -import nodeChildImport from 'node:child_process'; nodeChildImport.exec(com) - -// not supported -// var child = sinon.stub(require('child_process')); child.exec.returns({}); -// var child = sinon.stub(require('node:child_process')); child.exec.returns({}); - -function fn () { - var result = child.exec(str); -} - -function fn () { - var result = childImport.exec(str); -} - -function fn () { - var result = nodeChildImport.exec(str); -} - -require('child_process').exec(str) - -function fn () { - require('child_process').exec(str) -} - -const {exec} = require('child_process'); -exec(str) - -const {exec: nodeExec} = require('node:child_process'); -nodeExec(str) - -import {exec as foo} from 'child_process'; -foo(com); -``` - -## Compliant Code Examples -```javascript -child_process.exec('ls') - -var {} = require('child_process'); -var result = /hello/.exec(str); - -var {} = require('node:child_process'); -var result = /hello/.exec(str); - -import {} from 'child_process'; -var result = /hello/.exec(str); - -import {} from 'node:child_process'; -var result = /hello/.exec(str); - -var { spawn } = require('child_process'); spawn(str); -var { spawn } = require('node:child_process'); spawn(str); -import { spawn } from 'child_process'; spawn(str); -import { spawn } from 'node:child_process'; spawn(str); - -// import redeclare not covered -// var foo = require('child_process'); -// function fn () { -// var foo = /hello/; -// var result = foo.exec(str); -// } - -var child = require('child_process'); child.spawn(str) -var child = require('node:child_process'); child.spawn(str) -import child from 'child_process'; child.spawn(str) -import child from 'node:child_process'; child.spawn(str) - -var foo = require('child_process'); -function fn () { - var result = foo.spawn(str); -} - -require('child_process').spawn(str) - -function fn () { - require('child_process').spawn(str) -} - -// constant assigment static analysis not covered -// var child_process = require('child_process'); -// var FOO = 'ls'; -// child_process.exec(FOO); - -// import child_process from 'child_process'; -// const FOO = 'ls'; -// child_process.exec(FOO); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md b/content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md deleted file mode 100644 index ccecd67079ed1..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detect-eval-with-expression.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/detect-eval-with-expression - language: JavaScript - severity: Warning -title: Avoid `eval` with expressions ---- -## Metadata -**ID:** `javascript-node-security/detect-eval-with-expression` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -The `eval` function could execute malicious code if used with non-literal values. The argument provided to the `eval` method could be used to execute malicious code. If an attacker manages to control the `eval` argument they can execute arbitrary code. - -In JavaScript, the `eval()` function evaluates or executes an argument if it's a string of JavaScript code. If this argument is influenced by user input or other external sources, it can lead to security vulnerabilities. Specifically, if an attacker can control or manipulate the value of the `variable` in `eval(variable)`, they can execute arbitrary code. - -You should avoid using `eval` at all costs, but if you face an advanced use case, use literal values that are under your control or sanitize the input. However, even then it is still recommended to avoid the use of `eval` as it has led to security breaches before. - -## Non-Compliant Code Examples -```javascript -eval(a); -global.eval(a); -globalThis.eval(a); - -const answer = eval(expression) -``` - -## Compliant Code Examples -```javascript -eval('alert()') -global.eval('a'); -globalThis.eval('a'); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md b/content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md deleted file mode 100644 index af9373e65ea5e..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detect-new-buffer.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/detect-new-buffer - language: JavaScript - severity: Warning -title: Avoid Buffer(argument) with non-literal values ---- -## Metadata -**ID:** `javascript-node-security/detect-new-buffer` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Dealing with binary data can be achieved with the Node.js Buffer class. However, if you use non-literal params, this could lead to malicious control over the value, resulting in an attack. - -For example, a large number could allocate a significant amount of memory leading to a denial of service attack. It is recommended to use literal values that you can control to prevent these attacks. - -## Non-Compliant Code Examples -```javascript -var a = new Buffer(c) -``` - -## Compliant Code Examples -```javascript -var a = new Buffer('test') -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md deleted file mode 100644 index d78b49079477c..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/detect-non-literal-fs-filename - language: JavaScript - severity: Warning -title: Avoid variables in 'fs' calls filename argument ---- -## Metadata -**ID:** `javascript-node-security/detect-non-literal-fs-filename` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -An attacker could manipulate the file system call argument, leading to a path traversal attack. In this case, the attacker can get access to files and directories within your server file system. - -## Non-Compliant Code Examples -```javascript -/// requires -var something = require('fs'); -var a = something.open(c); - -var one = require('fs').readFile; -one(filename); - -var one = require('node:fs').readFile; -one(filename); - -var one = require('fs/promises').readFile; -one(filename); - -var something = require('fs/promises'); -something.readFile(filename); - -var something = require('node:fs/promises'); -something.readFile(filename); - -var something = require('fs-extra'); -something.readFile(filename); - -var { readFile: something } = require('fs'); -something(filename) - -//// imports -import { readFile as something } from 'fs'; -something(filename); - -import { readFile as something } from 'node:fs'; -something(filename); - -import { readFile as something } from 'fs-extra'; -something(filename); - -import { readFile as something } from 'fs/promises' -something(filename) - -import { readFile as something } from 'node:fs/promises' -something(filename) - -import { readFile } from 'node:fs/promises' -something(readFile) - -import * as something from 'fs'; -something.readFile(filename); -import * as something from 'node:fs'; -something.readFile(filename); - -/// promises -var something = require('fs').promises; -something.readFile(filename) - -var something = require('node:fs').promises; -something.readFile(filename) - -var something = require('fs'); -something.promises.readFile(filename) - -var something = require('node:fs'); -something.promises.readFile(filename) - -var fs = require('fs'); -fs.readFile(`template with ${filename}`); - -// inline -function foo () { - var fs = require('fs'); - fs.readFile(filename); -} - -function foo () { - var { readFile: something } = require('fs'); - something(filename); -} - -var fs = require('fs'); -function foo () { - var { readFile: something } = fs.promises; - something(filename); -} - -import fs from 'fs'; -import path from 'path'; -const key = fs.readFileSync(path.resolve(__dirname, foo)); -``` - -## Compliant Code Examples -```javascript -var fs = require('fs'); -var a = fs.open('test') - -var something = require('some'); -var a = something.readFile(c); - -var something = require('fs').readFile, readFile = require('foo').readFile; -readFile(c); - - -// TODO: allow path with constant arguments -import { promises as fsp } from 'fs'; -import fs from 'fs'; -import path from 'path'; -// const index = await fsp.readFile(path.resolve(__dirname, './index.html'), 'utf-8'); -// const key = fs.readFileSync(path.join(__dirname, './ssl.key')); -await fsp.writeFile(path.resolve(__dirname, './sitemap.xml'), sitemap); - -import fs from 'fs'; -import path from 'path'; -const dirname = path.dirname(__filename) -// const key = fs.readFileSync(path.resolve(dirname, './index.html')); - -import fs from 'fs'; -// const key = fs.readFileSync(`${process.cwd()}/path/to/foo.json`); - -import fs from 'fs'; -import path from 'path'; -import url from 'url'; -// const dirname = path.dirname(url.fileURLToPath(import.meta.url)); -// const html = fs.readFileSync(path.resolve(dirname, './index.html'), 'utf-8'); - -import fs from 'fs'; -// const pkg = fs.readFileSync(require.resolve('eslint/package.json'), 'utf-8'); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md deleted file mode 100644 index 2b6f8435ee66a..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-regexp.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/detect-non-literal-regexp - language: JavaScript - severity: Warning -title: Detects non-literal values in regular expressions ---- -## Metadata -**ID:** `javascript-node-security/detect-non-literal-regexp` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Creating a regular expression with user input can lead to a Regular Expression Denial of Service (ReDoS) attack. In this type of attack, a user can submit a very complex regular expression that takes too long to execute. - -If you have an advanced use case that requires regex evaluation with user input, always make sure to sanitize the data and provide a safe timeout environment. - -## Non-Compliant Code Examples -```javascript -var a = new RegExp(c, 'i'); - -``` - -## Compliant Code Examples -```javascript -var a = new RegExp('ab+c', 'i'); - -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md b/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md deleted file mode 100644 index 66e422c9420ac..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detect-non-literal-require.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/detect-non-literal-require - language: JavaScript - severity: Warning -title: Avoid require with non-literal values ---- -## Metadata -**ID:** `javascript-node-security/detect-non-literal-require` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Importing packages from dynamic paths can be a security vulnerability. An attacker might provide an undesired path that leads to running arbitrary code or reading sensitive information from your file system. - -In Node.js, the `require()` function is a built-in function that allows modules to be loaded. You can use it to include various types of files (like .js, .json, .node, etc) in your project. - -If the argument to `require()` is a variable instead of a static string, and if that variable's value can be influenced by user input, then an attacker might be able to exploit this to run arbitrary code or read sensitive files from your server's disk. This is a serious security issue often referred to as arbitrary code execution. - -Dynamic imports are a common source of arbitrary file read and code execution vulnerabilities. Avoid using variables with `require` or `import` statements. If you have an advanced use case that requires the use of dynamic imports, make sure to sanitize the input and have an allowed list of paths you can import code from. Always set the proper access control to your file system. - -## Non-Compliant Code Examples -```javascript -var a = require(c); -var a = require(`${c}`); - -``` - -## Compliant Code Examples -```javascript -var a = require('b'); -var a = require(`b`); - -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md b/content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md deleted file mode 100644 index 153d9d1807402..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/detected-jwt-token.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/detected-jwt-token - language: JavaScript - severity: Error -title: Detects hardcoded JWT tokens within the codebase. ---- -## Metadata -**ID:** `javascript-node-security/detected-jwt-token` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Security - -## Description -JSON Web Tokens (JWT) are commonly used for authentication and information exchange in web applications. While they are a powerful tool, they must be handled with care. - -## Non-Compliant Code Examples -```javascript -"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" -"eyJ0eXAiOiJKV1QiLA0KImFsZyI6IkhTMjU2In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" -"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9lIiwKInN0YXR1cyI6ImVtcGxveWVlIgp9" -'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IsWww6HFkcOtIMOWxZHDqcOoIiwiaWF0IjoxNTE2MjM5MDIyfQ.k5HibI_uLn_RTuPcaCNkaVaQH2y5q6GvJg8GPpGMRwQ' -`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ` -``` - -## Compliant Code Examples -```javascript -"eyfoo" -`eybaz` -'eybla' -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md b/content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md deleted file mode 100644 index 2e8c403d2542b..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/hardcoded-hmac-key.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/hardcoded-hmac-key - language: JavaScript - severity: Warning -title: Avoid hardcoded HMAC keys ---- -## Metadata -**ID:** `javascript-node-security/hardcoded-hmac-key` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Hardcoding cryptographic keys, secrets, or other sensitive information within the code is a common but dangerous practice. This rule aims to detect and prevent this kind of code pattern. - -## Non-Compliant Code Examples -```javascript -import crypto from "crypto"; - -crypto.createHmac('sha256', 'pa4qacea4VK9t9nGv7yZtwmj').update(data).digest('hex'); - -const rsa_key = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' -const hmac = crypto.createHmac('sha256', rsa_key) - -const key = 'private'; -const secret = key; -const fail = crypto.createHmac('sha256', secret); -``` - -## Compliant Code Examples -```javascript -import crypto from "crypto"; -import config from "./config"; - -const safely_stored_key = config.get('AWS_KEY') -const safe_hmac = crypto.createHmac('sha256', safely_stored_key) - -crypto.createHmac('sha256', process.env.KEY); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/insecure-hash.md b/content/en/static_analysis/rules/javascript-node-security/insecure-hash.md deleted file mode 100644 index 6e895648262ec..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/insecure-hash.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/insecure-hash - language: JavaScript - severity: Warning -title: Do not use weak hash functions ---- -## Metadata -**ID:** `javascript-node-security/insecure-hash` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not use weak hash algorithms such as MD5 or SHA1. - -#### Learn More - - - [CWE-328: Use of Weak Hash](https://cwe.mitre.org/data/definitions/328.html) - -## Non-Compliant Code Examples -```javascript -crypto.createHash("md5") - -createHash("md5") - -crypto.createHash("sha1") -``` - -## Compliant Code Examples -```javascript -crypto.createHash("sha256") - -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md b/content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md deleted file mode 100644 index c9c76fbb8674e..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/insecure-jwt-secret-usage - language: JavaScript - severity: Error -title: Insecure Usage of a Static Secret in JWT Signing ---- -## Metadata -**ID:** `javascript-node-security/insecure-jwt-secret-usage` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Security - -## Description -Using a static secret for signing JSON Web Tokens (JWT) poses several security risks: - -1. **Static Secrets**: Static secrets embedded in the code can be easily discovered by attackers. This is particularly dangerous if the code becomes publicly available or is leaked. -2. **Weak Secrets**: A simple, static secret might be weak and easily guessable, rendering the security controls it supports ineffective. -3. **Lack of Key Rotation**: A static secret doesn't allow for key rotation, a recommended practice to mitigate the risk if a secret is compromised. - -## Non-Compliant Code Examples -```javascript -import jwt from 'jsonwebtoken'; - -const privateKey = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' -export const authorize = (user = {}) => jwt.sign(user, privateKey, { expiresIn: '6h', algorithm: 'RS256' }); - -jwt.sign({ user: 'foo' }, 'secret'); - -const key = 'shhh'; -const secret = key; -jwt.sign({ user: 'foo' }, secret); -``` - -## Compliant Code Examples -```javascript -import jwt from "jsonwebtoken"; -import config from './config'; - -const payload = {foo: 'bar'}; -const secret3 = process.env.SECRET -const token5 = jwt.sign(payload, secret3) - -jwt.sign(payload, process.env.KEY); -jwt.sign(payload, config.secret); - -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md b/content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md deleted file mode 100644 index 3e018fad0469d..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/jwt-hardcoded-secret - language: JavaScript - severity: Error -title: Do not use hardcoded secret with a JWT ---- -## Metadata -**ID:** `javascript-node-security/jwt-hardcoded-secret` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Security - -## Description -Never hardcode secrets. Instead, use secrets from environment variables or a secret vault. - - -## Non-Compliant Code Examples -```javascript -var jwt = require("jsonwebtoken"); - -var token = jwt.sign({ foo: "bar" }, "secret"); - -var token = jwt.sign({ foo: "bar" }, 'secret'); - -var token = jwt.sign({ foo: "bar" }, `secret`); -``` - -## Compliant Code Examples -```javascript -var jwt = require("jsonwebtoken"); - - var token = jwt.sign({ foo: "bar" }, process.env.JWT_SECRET); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md b/content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md deleted file mode 100644 index 2e5a0cdb78263..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/jwt-sensitive-data.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/jwt-sensitive-data - language: JavaScript - severity: Warning -title: Do not put sensitive data in objects ---- -## Metadata -**ID:** `javascript-node-security/jwt-sensitive-data` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Never include sensitive information in a JWT. Instead, only use non-personal information to identify the end-user. - -## Non-Compliant Code Examples -```javascript -jwt.sign( - {user: { email: 'foo@bar.com'}} -) - -jwt.sign( - {user: { lastname: 'babar'}} -) - -``` - -## Compliant Code Examples -```javascript -jwt.sign( - {user: { id: 42}} -) -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md b/content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md deleted file mode 100644 index ff8e803f7c756..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/jwt-weak-encryption.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/jwt-weak-encryption - language: JavaScript - severity: Warning -title: Use default encryption from the JWT library ---- -## Metadata -**ID:** `javascript-node-security/jwt-weak-encryption` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not use `none` as a validation algorithm for a JWT token. The none algorithm assumes that the token has been verified, which would allow attacker to create a token that would be automatically validated. - -Never use the `none` algorithm, always use a valid algorithm as directed by [the documentation](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback). - -## Non-Compliant Code Examples -```javascript -jwt.verify(token, secret, { algorithms: ['RS256', 'none'] }, func); -jwt.verify(token, secret, { algorithms: ['none', 'RS256'] }, func); -``` - -## Compliant Code Examples -```javascript -jwt.verify(token, secret, { algorithms: ['RS256', 'HS256'] }, func); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md b/content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md deleted file mode 100644 index 558ad338741bd..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/log-sensitive-data.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/log-sensitive-data - language: JavaScript - severity: Warning -title: Avoid logging sensitive data ---- -## Metadata -**ID:** `javascript-node-security/log-sensitive-data` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not log sensitive data such as user id, email or other personal data (first name, last name, etc). - -## Non-Compliant Code Examples -```javascript -console.log("email from user" + user.email); -console.log(`email from user ${user.email}`); -logger.info(`email from user ${user.email}`); -logger.info(`email from user ${user.name}: ${user.email}`); -logger.info(`email from user ${username}: ${user.email}`); -logger.warn(email); -logger.error(`email from user ${email}`); - -foobar.error(`email from user ${email}`); - -logger.foobar(`email from user ${email}`); - -``` - -## Compliant Code Examples -```javascript -console.log("email from user" + user.id); -console.log(`email from user ${user.uuid}`); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md b/content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md deleted file mode 100644 index 21c80d519460d..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/oauth2-hardcoded-secret - language: JavaScript - severity: Warning -title: Do not use hardcoded secret for OAuth2 providers ---- -## Metadata -**ID:** `javascript-node-security/oauth2-hardcoded-secret` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not put hardcoded credentials in code. Instead, put secrets in environment variables or a vault. - -## Non-Compliant Code Examples -```javascript -passport.use(new OAuth2Strategy({ - authorizationURL: 'https://www.example.com/oauth2/authorize', - tokenURL: 'https://www.example.com/oauth2/token', - clientID: `client_id`, - clientSecret: 'secret_id', - callbackURL: "http://localhost:3000/auth/example/callback" - }, - function(accessToken, refreshToken, profile, cb) { - User.findOrCreate({ exampleId: profile.id }, function (err, user) { - return cb(err, user); - }); - } -)); -``` - -## Compliant Code Examples -```javascript -passport.use(new OAuth2Strategy({ - authorizationURL: 'https://www.example.com/oauth2/authorize', - tokenURL: 'https://www.example.com/oauth2/token', - clientID: process.env.EXAMPLE_CLIENT_ID, - clientSecret: process.env.EXAMPLE_CLIENT_SECRET, - callbackURL: "http://localhost:3000/auth/example/callback" - }, - function(accessToken, refreshToken, profile, cb) { - User.findOrCreate({ exampleId: profile.id }, function (err, user) { - return cb(err, user); - }); - } -)); -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/sql-injection.md b/content/en/static_analysis/rules/javascript-node-security/sql-injection.md deleted file mode 100644 index 85545262a085f..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/sql-injection.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/sql-injection - language: JavaScript - severity: Error -title: Avoid SQL injection ---- -## Metadata -**ID:** `javascript-node-security/sql-injection` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Security - -## Description -Check for variable declarations in a SQL statement where there is potential for SQL injections. - -#### Learn More - - - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) - -## Non-Compliant Code Examples -```javascript -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - // only allow apple or orange related searches - if (!criteria.startsWith("apple") || !criteria.startsWith("orange")) { - res.status(400).send() - return - } - models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```javascript -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - criteria.replace(/"|'|;|and|or/i, "") - models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```javascript -const injectionChars = /"|'|;|and|or|;|#/i; - -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - if (criteria.match(injectionChars)) { - res.status(400).send() - return - } - models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```javascript -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name") - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```javascript -var express = require('express') - -var app = express() -const Sequelize = require('sequelize'); -const sequelize = new Sequelize('database', 'username', 'password', { - dialect: 'sqlite', - storage: 'data/juiceshop.sqlite' -}); - -app.post('/login', function (req, res) { - sequelize.query('SELECT * FROM Products WHERE name LIKE ' + req.body.username); - }) - - -app.post('/update', function (req, res) { - sequelize.query('UPDATE products SET bla=bli WHERE name LIKE ' + req.body.username); - }) - - - -app.post('/remove', function (req, res) { - sequelize.query('DELETE FROM product WHERE name LIKE ' + req.body.username); - }) -``` - -```javascript -const express = require('express'); -const router = express.Router() - -const config = require('../../config') -const mysql = require('mysql'); -const connection = mysql.createConnection({ - host : config.MYSQL_HOST, - port : config.MYSQL_PORT, - user : config.MYSQL_USER, - password : config.MYSQL_PASSWORD, - database : config.MYSQL_DB_NAME, -}); - -connection.connect(); - -router.get('/example1/user/:id', (req,res) => { - let userId = req.params.id; - let query = { - sql : "SELECT * FROM users WHERE id=" + userId - } - connection.query(query,(err, result) => { - res.json(result); - }); -}) - -router.get('/example2/user/:id', (req,res) => { - let userId = req.params.id; - connection.query("SELECT * FROM users WHERE id=" + userId,(err, result) => { - res.json(result); - }); -}) - -router.get('/example3/user/:id', (req,res) => { - let userId = req.params.id; - connection.query({ - sql : "SELECT * FROM users WHERE id=" +userId - },(err, result) => { - res.json(result); - }); -}) - - -module.exports = router -``` - -## Compliant Code Examples -```javascript -import {BasketModel} from "../../../models/basket"; - -module.exports = function login () { - function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { - BasketModel.findOrCreate({ where: { UserId: user.data.id } }) - .then(([basket]: [BasketModel, boolean]) => { - const token = security.authorize(user) - user.bid = basket.id // keep track of original basket - security.authenticatedUsers.put(token, user) - res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) - }).catch((error: Error) => { - next(error) - }) - } - - return (req: Request, res: Response, next: NextFunction) => { - models.sequelize.query(`SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL`, - { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) - .then((authenticatedUser: { data: User }) => { - const user = utils.queryResultToJson(authenticatedUser) - if (user.data?.id && user.data.totpSecret !== '') { - res.status(401).json({ - status: 'totp_token_required', - data: { - tmpToken: security.authorize({ - userId: user.data.id, - type: 'password_valid_needs_second_factor_token' - }) - } - }) - } else if (user.data?.id) { - afterLogin(user, res, next) - } else { - res.status(401).send(res.__('Invalid email or password.')) - } - }).catch((error: Error) => { - next(error) - }) - } -``` - -```javascript -import {BasketModel} from "../../../models/basket"; - -module.exports = function login () { - function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { - BasketModel.findOrCreate({ where: { UserId: user.data.id } }) - .then(([basket]: [BasketModel, boolean]) => { - const token = security.authorize(user) - user.bid = basket.id // keep track of original basket - security.authenticatedUsers.put(token, user) - res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) - }).catch((error: Error) => { - next(error) - }) - } - - return (req: Request, res: Response, next: NextFunction) => { - models.sequelize.query('SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL', - { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) - .then((authenticatedUser: { data: User }) => { - const user = utils.queryResultToJson(authenticatedUser) - if (user.data?.id && user.data.totpSecret !== '') { - res.status(401).json({ - status: 'totp_token_required', - data: { - tmpToken: security.authorize({ - userId: user.data.id, - type: 'password_valid_needs_second_factor_token' - }) - } - }) - } else if (user.data?.id) { - afterLogin(user, res, next) - } else { - res.status(401).send(res.__('Invalid email or password.')) - } - }).catch((error: Error) => { - next(error) - }) - } -``` diff --git a/content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md b/content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md deleted file mode 100644 index bb69f5b49c3fe..0000000000000 --- a/content/en/static_analysis/rules/javascript-node-security/variable-sql-statement-injection.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: javascript-node-security/variable-sql-statement-injection - language: JavaScript - severity: Warning -title: Avoid SQL injections ---- -## Metadata -**ID:** `javascript-node-security/variable-sql-statement-injection` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Check for variable declarations in a SQL statement where there is potential for SQL injections. - -## Non-Compliant Code Examples -```javascript -var table = 'baz'; - -const foo = "SELECT foo FROM " + table; -const select = `SELECT foo FROM ${table}`; -var del = `DELETE FROM ${table} WHERE condition;`; -let update = ' UPDATE ' + - table + - "SET column1 = value1, column2 = value2" + - "WHERE condition;"; -``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-key.md b/content/en/static_analysis/rules/jsx-react/jsx-key.md deleted file mode 100644 index 440b7ca7f83bd..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/jsx-key.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: jsx-react/jsx-key - language: JavaScript - severity: Error -title: Prevent missing key props in iterators/collection literals ---- -## Metadata -**ID:** `jsx-react/jsx-key` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -In JSX you need to specify a key prop for each item of a list because if it's missing it could lead to unexpected renders or stale UI. This rule checks for possible JSX lists and warns if the key prop is missing. - -## Non-Compliant Code Examples -```jsx -[<>]; -[, foo, ]; -[, foo, ]; -data.map(x => ); -data.map(x => {x}); -data.map(x => {x}); -data.map(x => { return {x}}); -data.map(x => { return {x}}); -data.map(function(x) { return {x}}); -data.map(function(x) { return {x}}); -Array.from([1, 2, 3], (x) => {x}); -``` - -## Compliant Code Examples -```jsx -[, , ]; -data.map((x) => {x}); -Array.from([1, 2, 3], (x) => {x}); - -``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md b/content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md deleted file mode 100644 index 67dfdcee08419..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/jsx-no-comment-textnodes.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: jsx-react/jsx-no-comment-textnodes - language: JavaScript - severity: Warning -title: Avoid comments from being inserted as text nodes ---- -## Metadata -**ID:** `jsx-react/jsx-no-comment-textnodes` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -As JSX mixes HTML and JavaScript together, it's easy to mistake text nodes and add comments to them. This rule prevents you from accidentally leaving comments as HTML text. - -## Non-Compliant Code Examples -```jsx -var Hello = createReactClass({ - render: function() { - return ( -
- asd /* empty div */ -
- ); - } -}); - -var Hello = createReactClass({ - render: function() { - return ( -
- /* empty div */ -
- ); - } -}); -``` - -## Compliant Code Examples -```jsx -var Hello = createReactClass({ - displayName: 'Hello', - render: function() { - return
{/* empty div */}
; - } -}); - -var Hello = createReactClass({ - displayName: 'Hello', - render: function() { - return
; - } -}); - -var Hello = createReactClass({ - displayName: 'Hello', - render: function() { - return
; - } -}); -``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md b/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md deleted file mode 100644 index 795e56bac664f..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-key.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: jsx-react/jsx-no-duplicate-key - language: JavaScript - severity: Error -title: Ensures unique key prop ---- -## Metadata -**ID:** `jsx-react/jsx-no-duplicate-key` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -Duplicate JSX element keys can lead to unexpected behavior. Keys should always be unique. - -## Non-Compliant Code Examples -```jsx -[, foo, ]; -[, foo]; -[, ]; -data.map(x => ); -data.map(x => {x}); -data.map(x => {x}); -data.map(x => { return {x}}); -data.map(function(x) { return {x}}); -Array.from([1, 2, 3], (x) => {x}); -``` - -## Compliant Code Examples -```jsx -[, foo, ]; -data.map(x => { return {x}}); -``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md b/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md deleted file mode 100644 index 905e02b8cd335..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/jsx-no-duplicate-props.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: jsx-react/jsx-no-duplicate-props - language: JavaScript - severity: Error -title: Avoid duplicate properties in JSX ---- -## Metadata -**ID:** `jsx-react/jsx-no-duplicate-props` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -Providing duplicate properties to JSX elements can produce unexpected results in your project. - -## Non-Compliant Code Examples -```jsx -; -foo; - -``` - -## Compliant Code Examples -```jsx -; -``` diff --git a/content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md b/content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md deleted file mode 100644 index db33a2d3356a7..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/jsx-no-target-blank.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: jsx-react/jsx-no-target-blank - language: JavaScript - severity: Warning -title: Prevent target='_blank' security risks ---- -## Metadata -**ID:** `jsx-react/jsx-no-target-blank` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Security - -## Description -Using `target="_blank"` in an anchor (``) tag allows a link to be opened in a new browser tab or window. - -A malicious website opened through `target="_blank"` can change the `window.opener.location` to a phishing page, potentially misleading users. - -This rule enforces using `rel="noreferrer"` with on links that have the `target="_blank"` attribute. It might not be needed if you target modern browsers, but is still recommended to follow it as a best practice. - -#### Known Limitations - -This rule does not support custom link components without an `href`, `target` and `rel` properties. - -## Non-Compliant Code Examples -```jsx -var Hello = -var Hello = -var Nested = -var Nested = -``` - -## Compliant Code Examples -```jsx -var Hello =

-var Hello =

-var Hello = -var Hello = -var Hello = -var Hello = -var Hello = -``` diff --git a/content/en/static_analysis/rules/jsx-react/no-children-prop.md b/content/en/static_analysis/rules/jsx-react/no-children-prop.md deleted file mode 100644 index 8741ec3406ff8..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/no-children-prop.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: jsx-react/no-children-prop - language: JavaScript - severity: Warning -title: Avoid passing children as props ---- -## Metadata -**ID:** `jsx-react/no-children-prop` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Children should be used as actual children not a JSX prop. This rule enforces the use of children as an element between the JSX element opening and closing tag. - -## Non-Compliant Code Examples -```jsx -
; - -} />; -; - -React.createElement("div", { children: 'Children' }); -``` - -## Compliant Code Examples -```jsx -
Children
; -Children; - - Child 1 - Child 2 -; -React.createElement("div", {}, 'Children'); -React.createElement("div", 'Child 1', 'Child 2'); -``` diff --git a/content/en/static_analysis/rules/jsx-react/no-danger-with-children.md b/content/en/static_analysis/rules/jsx-react/no-danger-with-children.md deleted file mode 100644 index 5b836c964f172..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/no-danger-with-children.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: jsx-react/no-danger-with-children - language: JavaScript - severity: Warning -title: Avoid using children with dangerouslySetInnerHTML ---- -## Metadata -**ID:** `jsx-react/no-danger-with-children` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -If both `children` and `dangerouslySetInnerHTML` are set, it's unclear which one should take precedence. React will throw a warning if both are set. This rule enforces the use of either `children` or `dangerouslySetInnerHTML` but not both. - -## Non-Compliant Code Examples -```jsx -
{Children}
; -Children; -; -React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); -React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); -``` - -## Compliant Code Examples -```jsx -
; -; -
Children
; -Children; -React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }); -React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }); -React.createElement("div", {}, "Children"); -React.createElement("Hello", {}, "Children"); -``` diff --git a/content/en/static_analysis/rules/jsx-react/no-deprecated.md b/content/en/static_analysis/rules/jsx-react/no-deprecated.md deleted file mode 100644 index ce0824fddf4f5..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/no-deprecated.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: jsx-react/no-deprecated - language: JavaScript - severity: Warning -title: Avoid deprecated methods ---- -## Metadata -**ID:** `jsx-react/no-deprecated` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -As React evolves, methods are deprecated over time. This rule warns you about deprecated methods. - -## Non-Compliant Code Examples -```jsx -React.render(, root); -React.unmountComponentAtNode(root); -React.findDOMNode(this.refs.foo); -React.renderToString(); -React.renderToStaticMarkup(); -React.createClass({ /* Class object */ }); - -//Any factories under React.DOM -React.DOM.div(); - -import React, { PropTypes } from 'react'; - -// old lifecycles (since React 16.9) -componentWillMount() { } -componentWillReceiveProps() { } -componentWillUpdate() { } - -// React 18 deprecations -import { render } from 'react-dom'; -ReactDOM.render(
, container); - -import { hydrate } from 'react-dom'; -ReactDOM.hydrate(
, container); - -import { unmountComponentAtNode } from 'react-dom'; -ReactDOM.unmountComponentAtNode(container); - -import { renderToNodeStream } from 'react-dom/server'; -ReactDOMServer.renderToNodeStream(element); -``` - -## Compliant Code Examples -```jsx -import { PropTypes } from 'prop-types'; - -UNSAFE_componentWillMount() { } -UNSAFE_componentWillReceiveProps() { } -UNSAFE_componentWillUpdate() { } - -ReactDOM.createPortal(child, container); - -import { createRoot } from 'react-dom/client'; -const root = createRoot(container); -root.unmount(); - -import { hydrateRoot } from 'react-dom/client'; -const root = hydrateRoot(container, ); -``` diff --git a/content/en/static_analysis/rules/jsx-react/no-render-return-value.md b/content/en/static_analysis/rules/jsx-react/no-render-return-value.md deleted file mode 100644 index 41f206bf860be..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/no-render-return-value.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: jsx-react/no-render-return-value - language: JavaScript - severity: Warning -title: Avoid usage of the return value of ReactDOM.render ---- -## Metadata -**ID:** `jsx-react/no-render-return-value` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Using the return value of the render method is a legacy feature. If you have a valid reason to reference the root React instance, you should assign a callback ref to the root component. - -## Non-Compliant Code Examples -```jsx -const inst = ReactDOM.render(, document.body); -``` - -## Compliant Code Examples -```jsx -ReactDOM.render(, document.body); - -ReactDOM.render(, document.body, doSomethingWithInst); -``` diff --git a/content/en/static_analysis/rules/jsx-react/no-string-refs.md b/content/en/static_analysis/rules/jsx-react/no-string-refs.md deleted file mode 100644 index 12c9f8de3bec0..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/no-string-refs.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: jsx-react/no-string-refs - language: JavaScript - severity: Warning -title: Avoid using string references ---- -## Metadata -**ID:** `jsx-react/no-string-refs` - -**Language:** JavaScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -String references are a legacy feature of React, use a reference callback instead. - -## Non-Compliant Code Examples -```jsx -var Hello = createReactClass({ - render: function() { - return
; - } -}); -var Hello = createReactClass({ - render: function() { - return
Hello, world.
; - } -}); -var Hello = createReactClass({ - componentDidMount: function() { - var component = this.refs.hello; - // ...do something with component - }, - render: function() { - return
Hello, world.
; - } -}); -``` - -## Compliant Code Examples -```jsx -var Hello = createReactClass({ - componentDidMount: function() { - var component = this.hello; - // ...do something with component - }, - render() { - return
{ this.hello = c; }}>Hello, world.
; - } -}); -``` diff --git a/content/en/static_analysis/rules/jsx-react/require-render-return.md b/content/en/static_analysis/rules/jsx-react/require-render-return.md deleted file mode 100644 index 5df03cc0d9570..0000000000000 --- a/content/en/static_analysis/rules/jsx-react/require-render-return.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: jsx-react/require-render-return - language: JavaScript - severity: Error -title: Enforce class for returning value in render function ---- -## Metadata -**ID:** `jsx-react/require-render-return` - -**Language:** JavaScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -It's easy to forget the return value of a class component render method. This rule warns when the render method does not return a value. - -## Non-Compliant Code Examples -```jsx -var Hello = createReactClass({ - render() { -
Hello
; - } -}); - -class Hello extends React.Component { - render() { -
Hello
; - } -} -``` - -## Compliant Code Examples -```jsx -var Hello = createReactClass({ - render() { - return
Hello
; - } -}); - -class Hello extends React.Component { - render() { - return
Hello
; - } -} -``` diff --git a/content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md b/content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md deleted file mode 100644 index 011587838e1f4..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/ambiguous-class-name.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/ambiguous-class-name - language: Python - severity: Notice -title: make sure class names are readable ---- -## Metadata -**ID:** `python-best-practices/ambiguous-class-name` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -In some fonts, some characters are indistinguishable from the numerals one and zero, such as, O looks like a zero. Use characters that are not ambiguous. - -## Non-Compliant Code Examples -```python -class I: # use i instead - pass -``` - -## Compliant Code Examples -```python -class MyClass: - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md b/content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md deleted file mode 100644 index 0d96a676b5713..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/ambiguous-function-name.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/ambiguous-function-name - language: Python - severity: Notice -title: make sure function names are readable ---- -## Metadata -**ID:** `python-best-practices/ambiguous-function-name` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -In some fonts, these characters are indistinguishable from the numerals one and zero. Use characters that are not ambiguous. - -## Non-Compliant Code Examples -```python -def I(): # use i instead - pass -``` - -## Compliant Code Examples -```python -def i(): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md b/content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md deleted file mode 100644 index 52a3d88f7877a..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/ambiguous-variable-name.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/ambiguous-variable-name - language: Python - severity: Notice -title: make sure variable names are readable ---- -## Metadata -**ID:** `python-best-practices/ambiguous-variable-name` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -In some fonts, some characters are indistinguishable from the numerals one and zero, such as, O looks like a zero. Use characters that are not ambiguous. - -## Non-Compliant Code Examples -```python -I = 1 # use i instead -``` - -## Compliant Code Examples -```python -def i(): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/any-type-disallow.md b/content/en/static_analysis/rules/python-best-practices/any-type-disallow.md deleted file mode 100644 index 5f5368079a3ae..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/any-type-disallow.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/any-type-disallow - language: Python - severity: Warning -title: do not use Any type ---- -## Metadata -**ID:** `python-best-practices/any-type-disallow` - -**Language:** Python - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Use the `Any` type very carefully. Most of the time, the `Any` type is used because we do not know exactly what type is being used. If you want to specify that a value can be of any type, use `object` instead of `Any`. - - -#### Learn More - - - [Python documentation: the `Any` type](https://docs.python.org/3/library/typing.html#the-any-type) - -## Non-Compliant Code Examples -```python -my_var: Any = 1 -``` - -```python -def foo(x: Any): # do not use Any, use a specific type - pass -``` - -## Compliant Code Examples -```python -my_var: int = 1 - -def my_function(a: str) -> str: - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/argument-same-name.md b/content/en/static_analysis/rules/python-best-practices/argument-same-name.md deleted file mode 100644 index 2f7b1a3735381..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/argument-same-name.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/argument-same-name - language: Python - severity: Error -title: do not have arguments with the same name ---- -## Metadata -**ID:** `python-best-practices/argument-same-name` - -**Language:** Python - -**Severity:** Error - -**Category:** Error Prone - -## Description -Function parameters cannot have the same name. Each function parameter must have a distinct name. - -## Non-Compliant Code Examples -```python -def foo(bar, bar: int): # use another name for the second argument - pass -``` - -## Compliant Code Examples -```python -def foo(bar, baz): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md b/content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md deleted file mode 100644 index c2e8caaa822e0..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/assertraises-specific-exception.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/assertraises-specific-exception - language: Python - severity: Warning -title: assertRaises must check for a specific exception ---- -## Metadata -**ID:** `python-best-practices/assertraises-specific-exception` - -**Language:** Python - -**Severity:** Warning - -**Category:** Error Prone - -## Description -When checking an exception, check for a specific exception. Checking for `Exception` may bypass the verification of the correct behavior of the program. - -Using a generic exception is error-prone and give a false sense of correctness. Instead, use the correct exception to check against. - -## Non-Compliant Code Examples -```python -self.assertRaises(Exception, foo) # check a specific Exception, not a generic one -``` - -## Compliant Code Examples -```python -self.assertRaises(ValueError, foo) -``` diff --git a/content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md b/content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md deleted file mode 100644 index e63f25fd05eb3..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/avoid-duplicate-keys.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/avoid-duplicate-keys - language: Python - severity: Warning -title: Avoid duplicate keys in dictionaries ---- -## Metadata -**ID:** `python-best-practices/avoid-duplicate-keys` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Keys in a dictionary must be unique. - -## Non-Compliant Code Examples -```python -dict = { - "key1": "key2", - "key2": "key3", - "key3": "key4", - "key1": "bla" -} - -``` - -## Compliant Code Examples -```python -dict = { - "key1": "key2", - "key2": "key3", - "key3": "key4", -} - -``` diff --git a/content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md b/content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md deleted file mode 100644 index 429fef63c2ac6..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/avoid-string-concat.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Performance - id: python-best-practices/avoid-string-concat - language: Python - severity: Warning -title: avoid string concatenation ---- -## Metadata -**ID:** `python-best-practices/avoid-string-concat` - -**Language:** Python - -**Severity:** Warning - -**Category:** Performance - -## Description -Concatenation of multiple strings is not efficient and make the code hard to read and understand. - -Instead of concatenating multiple strings, use an f-string or a format string. - -#### Learn More - - - [Python Documentation: `str.format()`](https://docs.python.org/3/library/stdtypes.html#str.format) - - [Python Documentation - f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) - -## Non-Compliant Code Examples -```python -"my" + awesome + "string" -plop = "super" + "awesome" + "text" -``` - -## Compliant Code Examples -```python -"my {0} string".format(awesome) -f"my {awesome} string" -plop = "superawesometext" - -function( - tags = ( - user_tags - + s.get("tags", []) - + [ - f"schedule_id:{s['_id']}", - f"schedule_name:{s['schedule_name']}", - f"git_ref:{schedule_git_ref}", - ] -) -) -``` diff --git a/content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md b/content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md deleted file mode 100644 index bb034ef5da930..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/class-methods-use-self.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/class-methods-use-self - language: Python - severity: Error -title: Class methods should not use self ---- -## Metadata -**ID:** `python-best-practices/class-methods-use-self` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -In a class method (that is not a class method nor a static method), the first argument must be `self` by convention. - -#### Learn More - - - [Method Objects on the Python documentation](https://docs.python.org/3.8/tutorial/classes.html#method-objects) - - [PEP8 style guide](https://peps.python.org/pep-0008/#function-and-method-arguments) - -## Non-Compliant Code Examples -```python -class Foo: - def bar(bar): # use def bar(self) instead - pass -``` - -## Compliant Code Examples -```python -class Foo: - @staticmethod - def static_method(bar): - pass - - @classmethod - def class_method(bar): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md b/content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md deleted file mode 100644 index f9d71581127d3..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/collection-while-iterating.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/collection-while-iterating - language: Python - severity: Error -title: do not modify a dictionary while iterating on it ---- -## Metadata -**ID:** `python-best-practices/collection-while-iterating` - -**Language:** Python - -**Severity:** Error - -**Category:** Error Prone - -## Description -Never update a dictionary while iterating on it. If you wish to update the dictionary, create a new dictionary from the existing values. - -## Non-Compliant Code Examples -```python -i = 0 -for element in my_list: - my_list["stuff"] = i # modifying a dictionary while iterating - i += 1 -``` - -## Compliant Code Examples -```python -i = 0 -new_list = {} -for element in my_list: - new_list["stuff"] = i # putting value to a new dictionary - i += 1 -``` diff --git a/content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md b/content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md deleted file mode 100644 index cf22b69206d5e..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/comment-fixme-todo-ownership - language: Python - severity: Notice -title: TODO and FIXME comments must have ownership ---- -## Metadata -**ID:** `python-best-practices/comment-fixme-todo-ownership` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When using `TODO` or `FIXME`, specify who write the annotation. It's a best practice to remind you who created the annotation and have potential context and information about this issue. - -## Non-Compliant Code Examples -```python -# TODO fix this function -def my_function(): - pass - -# FIXME fix this function -def my_function(): - pass -``` - -## Compliant Code Examples -```python -# TODO(bob) fix this function -def my_function(): - pass - -# FIXME(julien) fix this function -def my_other_function(): - pass - -# FIXME[julien] fix this function -def my_other_function(): - pass - -# TODO[bob] fix this function -def my_function(): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md b/content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md deleted file mode 100644 index f021e24fa4099..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/comparison-constant-left.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/comparison-constant-left - language: Python - severity: Notice -title: in comparisons, variables must be left ---- -## Metadata -**ID:** `python-best-practices/comparison-constant-left` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -In a comparison that compare a variable with a value, put the variable on the left side of the comparison expression. - -## Non-Compliant Code Examples -```python -if 1 <= i: # use i >= 1 - pass -``` - -```python -if 1.0 <= i: # use i >= 1.0 - pass -``` - -## Compliant Code Examples -```python -if i >= 1: - pass - -if 0 < nextSx <= len(subject): - px = nextPx - sx = nextSx - -if 1 in ctx: - print("foo") - -``` diff --git a/content/en/static_analysis/rules/python-best-practices/condition-similar-block.md b/content/en/static_analysis/rules/python-best-practices/condition-similar-block.md deleted file mode 100644 index 34be359370f61..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/condition-similar-block.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/condition-similar-block - language: Python - severity: Warning -title: if conditions must have different code blocks ---- -## Metadata -**ID:** `python-best-practices/condition-similar-block` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Code in the branches of an `if` condition must be unique. If you have duplicated branches, merge the conditions. - -## Non-Compliant Code Examples -```python -if foo: - printf("bar") -elif baz: - printf("bar2") -elif bap: - # same code than the if condition - printf("bar") -else: - # same code than the if condition - printf("bar") -``` - -## Compliant Code Examples -```python -if foo: - printf("bar") -elif baz: - printf("bar2") -elif bap: - printf("bar3") -else: - printf("bar4") -``` diff --git a/content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md b/content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md deleted file mode 100644 index 056a1f263f635..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/ctx-manager-enter-exit-defined - language: Python - severity: Error -title: ensure that both __exit__ and __enter__ are defined ---- -## Metadata -**ID:** `python-best-practices/ctx-manager-enter-exit-defined` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -Methods `__enter__` and `__exit__` must be declared together. If one method is missing, we should make sure both are defined. - -#### Learn More - - - [contextlib documentation](https://docs.python.org/3/library/contextlib.html) - -## Non-Compliant Code Examples -```python -class Ctx: - def __exit__(self, *exc): # the method __enter__ should be defined. - pass -``` - -```python -class Ctx: - def __enter__(self): # the method __exit__ should also be defined. - pass -``` - -## Compliant Code Examples -```python -class Ctx: - def __enter__(self): - pass - def __exit__(self, *exc): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md b/content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md deleted file mode 100644 index 1a5cf0cf6e217..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/dataclass-special-methods.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/dataclass-special-methods - language: Python - severity: Notice -title: do not use special method on data class ---- -## Metadata -**ID:** `python-best-practices/dataclass-special-methods` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Data classes (annotated with @dataclass) do not use special method such as `__init__`, `__gt__`, and more. - -## Non-Compliant Code Examples -```python -@dataclass -class _Leaf(Generic[T]): - parent: _Leaf - value: T - - def __init__(self, value: Optional[T] = None): - self.value = value - self.parent = self - - def update(self, value: T): - self.value = value - return self - - def __lt__(self, other: _Leaf): - return repr(self) < repr(other) - - def __gt__(self, other: _Leaf): - return repr(self) > repr(other) - - # __eq__ should not be used - def __eq__(self, other: _Leaf): - return repr(self) == repr(other) - - def __repr__(self): - return self.value -``` - -## Compliant Code Examples -```python -@dataclass -class _Leaf(Generic[T]): - parent: _Leaf - value: T - - def update(self, value: T): - self.value = value - return self - - def __repr__(self): - return self.value -``` diff --git a/content/en/static_analysis/rules/python-best-practices/equal-basic-types.md b/content/en/static_analysis/rules/python-best-practices/equal-basic-types.md deleted file mode 100644 index bae5144a88694..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/equal-basic-types.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/equal-basic-types - language: Python - severity: Warning -title: check equal is used on consistent basic types ---- -## Metadata -**ID:** `python-best-practices/equal-basic-types` - -**Language:** Python - -**Severity:** Warning - -**Category:** Error Prone - -## Description -When comparing basic types (string, integer, float), we should always values of the same types. - -## Non-Compliant Code Examples -```python -1 == "1" # Comparing an integer and a string -1.0 == "foo" # Comparing a float and a string -``` - -## Compliant Code Examples -```python -1 == 1 -"abc" == "def" -a == 1 -a == b -``` diff --git a/content/en/static_analysis/rules/python-best-practices/exception-inherit.md b/content/en/static_analysis/rules/python-best-practices/exception-inherit.md deleted file mode 100644 index 8c0b71fde3c9a..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/exception-inherit.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/exception-inherit - language: Python - severity: Warning -title: ensure exception inherit a base exception ---- -## Metadata -**ID:** `python-best-practices/exception-inherit` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -New `Exception` must inherit the base `Exception`. Always use another exception as parent or use at least the `Exception` base class. - -#### Learn More - -- [Python Documentation: User-defined Exceptions](https://docs.python.org/3/tutorial/errors.html#user-defined-exceptions) - -## Non-Compliant Code Examples -```python -class CustomException: - """An Invalid exception class.""" -``` - -## Compliant Code Examples -```python -class CustomException(Exception): - """An Invalid exception class.""" -``` diff --git a/content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md b/content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md deleted file mode 100644 index 203393c3e7c20..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/finally-no-break-continue-return.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/finally-no-break-continue-return - language: Python - severity: Warning -title: do not use break or continue in finally block ---- -## Metadata -**ID:** `python-best-practices/finally-no-break-continue-return` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -When using `return`, `break` or `continue` in a `finally` block, it will stop the spread of any exceptions that were thrown in the `try`, `else`, or `except` blocks and will disregard any return statements. - -#### Learn More - - - [Official Python documentation](https://docs.python.org/3/reference/compound_stmts.html#except) - -## Non-Compliant Code Examples -```python -try: - client_obj.get_url(url) -except (URLError, ValueError): - client_obj.remove_url(url) -except SocketTimeout: - client_obj.handle_url_timeout(url) -finally: - break # avoid break in the finally block -``` - -```python -try: - client_obj.get_url(url) -except (URLError, ValueError): - client_obj.remove_url(url) -except SocketTimeout: - client_obj.handle_url_timeout(url) -finally: - return 0 # avoid return in the finally block -``` - -```python -try: - client_obj.get_url(url) -except (URLError, ValueError): - client_obj.remove_url(url) -except SocketTimeout: - client_obj.handle_url_timeout(url) -finally: - continue # avoid continue in the finally block -``` - -## Compliant Code Examples -```python -try: - client_obj.get_url(url) -except (URLError, ValueError): - client_obj.remove_url(url) -except SocketTimeout: - client_obj.handle_url_timeout(url) -finally: - print("cleanup the mess") -``` diff --git a/content/en/static_analysis/rules/python-best-practices/function-already-exists.md b/content/en/static_analysis/rules/python-best-practices/function-already-exists.md deleted file mode 100644 index a1cd3a88a3ff9..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/function-already-exists.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/function-already-exists - language: Python - severity: Error -title: a function must be defined only once ---- -## Metadata -**ID:** `python-best-practices/function-already-exists` - -**Language:** Python - -**Severity:** Error - -**Category:** Error Prone - -## Description -A function should only be defined once. Make sure you use unique name for each function in a module. - -## Non-Compliant Code Examples -```python - -def my_function(): - pass - -def foo(): - pass - -def my_function(): # function already defined - pass - -``` - -## Compliant Code Examples -```python - -def my_function(): - pass - -def foo(): - pass - -def my_other_function(): - pass - -``` diff --git a/content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md b/content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md deleted file mode 100644 index f9a5247ec86e0..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/function-variable-argument-name.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/function-variable-argument-name - language: Python - severity: Warning -title: Do not assign to function arguments ---- -## Metadata -**ID:** `python-best-practices/function-variable-argument-name` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -A function parameter should only be read and not be modified. If your intent is to modify the value of the parameter, return the value in the function and handle the new value in the caller of the function. - -## Non-Compliant Code Examples -```python -def func(arg1, arg2): - arg1 = foo # assign to a variable that is an argument -``` - -```python -def func(arg1, arg2): - (arg1, arg3, arg2) = foo # assign to a variable that is an argument -``` - -## Compliant Code Examples -```python -def func(arg1, arg2): - arg3 = foo -``` diff --git a/content/en/static_analysis/rules/python-best-practices/generic-exception-last.md b/content/en/static_analysis/rules/python-best-practices/generic-exception-last.md deleted file mode 100644 index d7cae4a1e2ba2..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/generic-exception-last.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/generic-exception-last - language: Python - severity: Notice -title: If using generic exception, it should be last ---- -## Metadata -**ID:** `python-best-practices/generic-exception-last` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When multiple exceptions are caught, the generic `Exception` must be caught last. Catching `Exception` is very generic and if placed before specific exceptions, it will caught all exceptions and specific exception handlers will not be caught. - -For this reason, generic `Exception` must be the last to be handled to let specific exception handlers to be triggered/executed. - -#### Learn More - -- [Python tutorials on errors](https://docs.python.org/3/tutorial/errors.html) - -## Non-Compliant Code Examples -```python -try: - pass -except Exception: - pass -except FileNotFound as e: - pass -``` - -## Compliant Code Examples -```python -try: - pass -except MyError: - pass -except Exception as e: - pass -``` - -```python -try: - pass -except MyError: - pass -except FileNotFound as e: - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/get-set-arguments.md b/content/en/static_analysis/rules/python-best-practices/get-set-arguments.md deleted file mode 100644 index 091a45dd72adc..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/get-set-arguments.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/get-set-arguments - language: Python - severity: Warning -title: getter/setter must have 1 or 2 arguments respectively ---- -## Metadata -**ID:** `python-best-practices/get-set-arguments` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Ensure that getter and setter have the right number of parameters: - - getters must have exactly one parameter (the instance we are reading from) - - setters must have exactly two parameters (the instance we are updating and the associated value) - -#### Learn More - - - [Python documentation - property](https://docs.python.org/3/library/functions.html#property) - -## Non-Compliant Code Examples -```python -class Foo: - @property - def get_my_attribute(self, foo): # getter should have only one argument - return self.my_attribute - - @attr.setter - def set_attr(self, v, bar): # setter should have only two arguments - self._attr = v - - @attr.deleter - def del_attr(self, foo): # deleter should have only one argument - del self._attr -``` - -## Compliant Code Examples -```python -class Foo: - def get_my_attribute(self): - return self.my_attribute - - def get_my_attribute(self, foo): # Not a property or attr, valid - return self.my_attribute - - @property - def get_my_attribute(self): - return self.my_attribute - - def set_my_attribute(self, v): - self.my_attribute = v - - @attr.setter - def set_attr(self, v): - self._attr = v - - @attr.deleter - def del_attr(self,): - return self._attr -``` diff --git a/content/en/static_analysis/rules/python-best-practices/if-return-no-else.md b/content/en/static_analysis/rules/python-best-practices/if-return-no-else.md deleted file mode 100644 index 035265b18a04c..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/if-return-no-else.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/if-return-no-else - language: Python - severity: Notice -title: when an if condition returns an value, else is not necessary ---- -## Metadata -**ID:** `python-best-practices/if-return-no-else` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -If the code in the `if` branch returns a value, do not have the `else` branch present. - -## Non-Compliant Code Examples -```python -if bla: - foo() - return 1 -else: # unnecessary, remove the else branch - return 2 -``` - -## Compliant Code Examples -```python -if bla: - foo() - return 1 -return 2 -``` - -```python -if bla: - foo() -else: - return 2 -``` diff --git a/content/en/static_analysis/rules/python-best-practices/import-modules-twice.md b/content/en/static_analysis/rules/python-best-practices/import-modules-twice.md deleted file mode 100644 index a8ca70c531380..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/import-modules-twice.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/import-modules-twice - language: Python - severity: Warning -title: module imported twice ---- -## Metadata -**ID:** `python-best-practices/import-modules-twice` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Always define a module once. Do not import the module multiple times and/or import the module using different methods. It makes the code harder to understand. Import a module once and for all with only one import mechanism. - -## Non-Compliant Code Examples -```python -import logging -import logging # do not import the same module again. - -``` - -## Compliant Code Examples -```python -import typing -from typing import cast -``` - -```python -import logging -``` - -```python -import logging -from logging import foo # not an issue since we are using a from import - -``` diff --git a/content/en/static_analysis/rules/python-best-practices/import-single-module.md b/content/en/static_analysis/rules/python-best-practices/import-single-module.md deleted file mode 100644 index 9954df84a41b9..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/import-single-module.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/import-single-module - language: Python - severity: Notice -title: only one module to import per import statement ---- -## Metadata -**ID:** `python-best-practices/import-single-module` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Import using the `import` keyword should be done on separate lines. - -## Non-Compliant Code Examples -```python -import os, sys # when using an import statement, import one module at a time -``` - -## Compliant Code Examples -```python -from collections.abc import Mapping, Sequence -import os -import sys -from typing import Any, NewType -``` diff --git a/content/en/static_analysis/rules/python-best-practices/init-call-parent.md b/content/en/static_analysis/rules/python-best-practices/init-call-parent.md deleted file mode 100644 index f90641be401c7..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/init-call-parent.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/init-call-parent - language: Python - severity: Warning -title: use super() to call the parent constructor ---- -## Metadata -**ID:** `python-best-practices/init-call-parent` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Calling the parent constructor should be done by calling `super()`, not by calling the parent object directly. - -## Non-Compliant Code Examples -```python -class Class(Parent): - def __init__(self): - SomeClass.__init__(self) # should use super() -``` - -## Compliant Code Examples -```python -# More than one parent, we need to know exactly what -# parent constructor to use -class DummyCIVisibilityWriter(DummyWriterMixin, CIVisibilityWriter): - def __init__(self, *args, **kwargs): - CIVisibilityWriter.__init__(self, *args, **kwargs) - DummyWriterMixin.__init__(self, *args, **kwargs) - self._encoded = None -``` - -```python -class Class(Parent): - def foo(self): - SomeClass.__init__(self) # outside of __init__, valid -``` - -```python -class Class(Parent): - def __init__(self): - super().__init__(self) -``` diff --git a/content/en/static_analysis/rules/python-best-practices/init-method-required.md b/content/en/static_analysis/rules/python-best-practices/init-method-required.md deleted file mode 100644 index 145bd56892f49..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/init-method-required.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/init-method-required - language: Python - severity: Notice -title: ensure classes have an __init__ method ---- -## Metadata -**ID:** `python-best-practices/init-method-required` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Ensure that a class has an `__init__` method. This check is bypassed when the class is a data class (annotated with @dataclass). - -## Non-Compliant Code Examples -```python -class Foo: # need to define __init__ - def foo(bar): - pass - def bar(baz): - pass -``` - -## Compliant Code Examples -```python -# dataclass do not require an init class -@dataclass -class Requests: - cpu: float # expressed in cpu cores - memory: int # expressed in bytes - - @staticmethod - def from_pod(pod: V1Pod): - cpu = 0.0 - memory = 0 - - for container in pod.spec.containers: - cpu += parse_cpu_string(container.resources.requests["cpu"]) - memory += parse_memory_string(container.resources.requests["memory"]) - - return Requests(cpu, memory) - - def add(self, other): - self.cpu += other.cpu - self.memory += other.memory - -``` - -```python -class Foo(Bar): - - def foo(): - pass -``` - -```python -class UserLoginTest(TestCase): - def setUp(self): - self.username = 'testuser' - self.password = 'testpassword' - self.user = User.objects.create_user(username=self.username, password=self.password) - - def test_correct_credentials(self): - user = authenticate(username=self.username, password=self.password) - self.assertIsNotNone(user) - self.assertEqual(user, self.user) - - def test_incorrect_credentials(self): - user = authenticate(username=self.username, password='wrongpassword') - self.assertIsNone(user) -``` - -```python -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ] - - operations = [ - ] -``` - -```python -@dataclass -class Foo: # no __init__ required for dataclass - value = 51 -``` - -```python -class Foo: - def __init__(self): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/init-no-return-value.md b/content/en/static_analysis/rules/python-best-practices/init-no-return-value.md deleted file mode 100644 index d5712ed737291..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/init-no-return-value.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/init-no-return-value - language: Python - severity: None -title: No return in an __init__ function ---- -## Metadata -**ID:** `python-best-practices/init-no-return-value` - -**Language:** Python - -**Severity:** None - -**Category:** Error Prone - -## Description -The `__init__` method (and the `__new__` method) should never return a non-`None` value. - -#### Learn More - - - [`__init__` function on the Python datamodel documentation](https://docs.python.org/3/reference/datamodel.html#object.__init__) - -## Non-Compliant Code Examples -```python -class Foo: - def __init__(self): - # __init__ should not return a value - return 3 - - def my_method(): - return 10 -``` - -## Compliant Code Examples -```python -class Foo: - def __init__(self): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md b/content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md deleted file mode 100644 index 698c53f5b891a..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/invalid-strip-call.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/invalid-strip-call - language: Python - severity: Notice -title: strip() argument should not have duplicate characters ---- -## Metadata -**ID:** `python-best-practices/invalid-strip-call` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When using `.strip()`, you only need to pass the letters you want to split on. There is no need to specify the same letter twice. - -## Non-Compliant Code Examples -```python -"Hello World".strip("Hello") # letter l is present twice in the string -``` - -## Compliant Code Examples -```python -"Hello World".strip("Helo") # letter l is present twice in the string -``` diff --git a/content/en/static_analysis/rules/python-best-practices/logging-no-format.md b/content/en/static_analysis/rules/python-best-practices/logging-no-format.md deleted file mode 100644 index 87446c8e1f34d..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/logging-no-format.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/logging-no-format - language: Python - severity: Notice -title: do not use format string with logging functions ---- -## Metadata -**ID:** `python-best-practices/logging-no-format` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Avoid using format string with the `format` method when logging information. - -## Non-Compliant Code Examples -```python -import logging -import shlex - -logging.info("error {0}".format(plop)) # use instead logging.info("error %s", plop) -``` - -## Compliant Code Examples -```python -import logging - -logging.info("wfwef") -``` diff --git a/content/en/static_analysis/rules/python-best-practices/method-hidden.md b/content/en/static_analysis/rules/python-best-practices/method-hidden.md deleted file mode 100644 index fcaa77c406db1..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/method-hidden.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/method-hidden - language: Python - severity: Warning -title: a method has the same name than an attribute ---- -## Metadata -**ID:** `python-best-practices/method-hidden` - -**Language:** Python - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Make sure that class attribute and class methods have a unique name without any collision. - -## Non-Compliant Code Examples -```python -class MyClass: - def __init__(self, something): - self.foo = something - - def bla(foo): - pass - - def foo(self): # hidden by self.foo - pass -``` - -## Compliant Code Examples -```python -class MyClass: - def __init__(self, something): - self.foo = something - - def bla(foo): - pass - - def bar(self): # hidden by self.foo - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/nested-blocks.md b/content/en/static_analysis/rules/python-best-practices/nested-blocks.md deleted file mode 100644 index f6fe127599c12..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/nested-blocks.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-best-practices/nested-blocks - language: Python - severity: Error -title: Do not have too many nested blocks ---- -## Metadata -**ID:** `python-best-practices/nested-blocks` - -**Language:** Python - -**Severity:** Error - -**Category:** Code Style - -## Description -Avoid to nest too many loops together. Having too many loops make your code harder to understand. -Prefer to organize your code in functions and unit of code you can clearly understand. - -#### Learn More - - - [Computer Programming wikibooks - Minimize nesting](https://en.wikibooks.org/wiki/Computer_Programming/Coding_Style/Minimize_nesting) - - -## Non-Compliant Code Examples -```python -def func(): - for v in bla: - if bar: - if baz: - if wiz: # too many nested elements - pass -``` - -```python -def func(): - if foo: - pass - else: - if bar: - if baz: - if wiz: # too many nested elements - pass -``` - -```python -def func(): - if foo: - if bar: - if baz: - if wiz: # too many nested elements - pass -``` - -```python -def func(): - if foo: - pass - elif bar: - if bar: - if baz: - if wiz: # too many nested elements - pass - else: - pass -``` - -## Compliant Code Examples -```python -while Foo: - while Bar: - print("foobar") -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md b/content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md deleted file mode 100644 index c334dcc0264d0..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-assert-on-tuples.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/no-assert-on-tuples - language: Python - severity: Error -title: no assert on tuples ---- -## Metadata -**ID:** `python-best-practices/no-assert-on-tuples` - -**Language:** Python - -**Severity:** Error - -**Category:** Error Prone - -## Description -Do not assert on tuples. Asserting on tuples will always evaluate to `True` if the tuple is not empty. Instead, assert on each value rather than asserting on a tuple. - -## Non-Compliant Code Examples -```python -assert (1, 2) # do not assert on tuples -``` - -## Compliant Code Examples -```python -assert x - -assert exitcode == 42, (stdout, stderr) -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-assert.md b/content/en/static_analysis/rules/python-best-practices/no-assert.md deleted file mode 100644 index 6ec19cbc902f3..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-assert.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-assert - language: Python - severity: Error -title: do not use assert in production code ---- -## Metadata -**ID:** `python-best-practices/no-assert` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -Avoid having `assert` statements in code as they are not being used when . This rule does not apply to test files, such as, files ending with `_test.py`. - -## Non-Compliant Code Examples -```python -def foo(bar): - assert bar # no assert in production code -``` - -## Compliant Code Examples -```python -ctx1.set_baggage_item("test", 3) -ctx2 = SpanContext() -# Assert in a test file does not raise an error -assert "test" not in ctx2._baggage -``` - -```python -def foo(bar): - assert bar # assert ok in test code (see filename) -``` - -```python -def foo(bar): - assert bar # assert ok in test code -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-bare-except.md b/content/en/static_analysis/rules/python-best-practices/no-bare-except.md deleted file mode 100644 index 61536c42df172..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-bare-except.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-bare-except - language: Python - severity: Warning -title: do not use bare except ---- -## Metadata -**ID:** `python-best-practices/no-bare-except` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Avoid bare `except`. Try to always use specialized exception names in `except` blocks. - -## Non-Compliant Code Examples -```python -try: - print("foo") -except: # use a specialized exception name - print("bar") -``` - -## Compliant Code Examples -```python -try: - parsed = json.loads(response.body) -except json.JSONDecodeError: - log.warning("Test skips request responded with invalid JSON '%s'", response.body) - return -``` - -```python -try: - pass -except (TypeError, ValueError): - log.debug( - ( - "received invalid x-datadog-* headers, " - "trace-id: %r, parent-id: %r, priority: %r, origin: %r, tags:%r" - ), - trace_id, - parent_span_id, - sampling_priority, - origin, - tags_value, - ) -``` - -```python -try: - foo() -except MyError as e: - bar() -``` - -```python -try: - print("foo") -except MyException: - print("bar") -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-bare-raise.md b/content/en/static_analysis/rules/python-best-practices/no-bare-raise.md deleted file mode 100644 index e411e131185d4..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-bare-raise.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-bare-raise - language: Python - severity: Warning -title: Do not use a raise statement without a specific exception ---- -## Metadata -**ID:** `python-best-practices/no-bare-raise` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Never use a bare raise and always use a specific exception. Using a specific exception helps you distinguish errors in your program and have appropriate error handling code. - -## Non-Compliant Code Examples -```python -def myfunc(): - raise # should use specific exception - -if foo: - raise -else: - func1() - raise - -for v in list: - do_something() - raise -``` - -## Compliant Code Examples -```python -def myfunc(): - raise MyException - -try: - foo() -except MyException: - raise # re-raise exception -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-base-exception.md b/content/en/static_analysis/rules/python-best-practices/no-base-exception.md deleted file mode 100644 index 18abec10ada1c..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-base-exception.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-base-exception - language: Python - severity: Notice -title: do not raise base exception ---- -## Metadata -**ID:** `python-best-practices/no-base-exception` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not raise `Exception` and `BaseException`. These are too generic. Having generic exceptions makes it difficult to differentiate errors in a program. Use a specific exception, for example, `ValueError`, or create your own instead of using generic ones. - -#### Learn More - - - [Stop using `raise Exception`](https://jerrynsh.com/stop-using-exceptions-like-this-in-python/#2-stop-using-raise-exception) - -## Non-Compliant Code Examples -```python -if foo: - raise Exception("bla") -elif bar: - raise Exception -else: - raise Exception -``` - -```python -def use_base_exception(): - raise Exception - raise Exception("awesome") -``` - -```python -for v in list: - raise BaseException -``` - -## Compliant Code Examples -```python -if foo: - print("bar") -else: - raise ValueError -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-datetime-today.md b/content/en/static_analysis/rules/python-best-practices/no-datetime-today.md deleted file mode 100644 index d37b621c4d7f2..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-datetime-today.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-datetime-today - language: Python - severity: Notice -title: do not use datetime.today() ---- -## Metadata -**ID:** `python-best-practices/no-datetime-today` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Avoid using `datetime.today()` and use instead `datetime.now()`. The two calls are equivalent (as mentioned in the [official documentation](https://docs.python.org/3/library/datetime.html#datetime.date.today)) and the use of `now()` is more explicit than `today()`. - -Using `today()` makes you think it only returns the year/month/day but it returns a full timestamp. For this reason, prefer using `now()`. - -## Non-Compliant Code Examples -```python -from datetime import datetime -print("foo") -bla = datetime.today() # use datetime.now() instead -``` - -## Compliant Code Examples -```python -from datetime import datetime -print("foo") -bla = datetime.now() -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-double-not.md b/content/en/static_analysis/rules/python-best-practices/no-double-not.md deleted file mode 100644 index 2e9b3b05492d6..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-double-not.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/no-double-not - language: Python - severity: Warning -title: do not use double negation ---- -## Metadata -**ID:** `python-best-practices/no-double-not` - -**Language:** Python - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Do not use two negation. It makes the code more complex to read and understand. Instead of using two negation, use the expression directly. - -## Non-Compliant Code Examples -```python -if not not foo: # just use if foo - pass -``` - -## Compliant Code Examples -```python -if not foo: - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md b/content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md deleted file mode 100644 index 69dbaf2f9ae56..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-double-unary-operator.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-double-unary-operator - language: Python - severity: Error -title: do not use operator -- and ++ ---- -## Metadata -**ID:** `python-best-practices/no-double-unary-operator` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -Operator `--` and `++` do not exists in Python. Increment or decrement the variable appropriately. - -## Non-Compliant Code Examples -```python ---n # use n = n - 1 -++n # use n = n + 1 - -``` - -## Compliant Code Examples -```python -n = n + 1 -n = n - 1 -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md b/content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md deleted file mode 100644 index f8de46813cd59..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-duplicate-base-class.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/no-duplicate-base-class - language: Python - severity: Warning -title: use a base class only once ---- -## Metadata -**ID:** `python-best-practices/no-duplicate-base-class` - -**Language:** Python - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Classes should not have the same superclass specified twice. Each superclass must be unique. - -## Non-Compliant Code Examples -```python -class MyClass: - pass - - -# The SuperClass parent is specified twice -class MyClassTwo(SuperClass, SuperClass): - pass -``` - -## Compliant Code Examples -```python -class MyClass: - pass - - -class MyClassTwo(SuperClass): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-equal-unary.md b/content/en/static_analysis/rules/python-best-practices/no-equal-unary.md deleted file mode 100644 index 78fe13cd09d79..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-equal-unary.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-equal-unary - language: Python - severity: Error -title: do not use operations =+ and =- ---- -## Metadata -**ID:** `python-best-practices/no-equal-unary` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -Operator `=+` and `=-` do not exist in Python. The code is valid but is unlikely doing what the developer wants to achieve. - -## Non-Compliant Code Examples -```python -# =+ does not exists in Python, use n = n + 3 -n =+ 3 - -# =- does not exists in Python, use n = n - 3 -n =- 3 -``` - -## Compliant Code Examples -```python -n = n + 3 - -n = n - 3 - -foo = -1 -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-exit.md b/content/en/static_analysis/rules/python-best-practices/no-exit.md deleted file mode 100644 index a1d52afc61556..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-exit.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-exit - language: Python - severity: Error -title: do not use exit() ---- -## Metadata -**ID:** `python-best-practices/no-exit` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -Use `sys.exit()` instead of `exit()`. Exit is a [builtin](https://docs.python.org/3/library/constants.html#exit) and done mostly for the console. `sys.exit()` is done for program with a proper return argument ([see documentation](https://docs.python.org/3/library/sys.html#sys.exit)). - -#### Learn More - - [Python documentation for `sys.exit()`](https://docs.python.org/3/library/sys.html#sys.exit) - -## Non-Compliant Code Examples -```python -print("bla") -exit(0) # use sys.exit() instead -``` - -## Compliant Code Examples -```python -import sys -print("bla") -sys.exit(0) -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-generic-exception.md b/content/en/static_analysis/rules/python-best-practices/no-generic-exception.md deleted file mode 100644 index 50e2b1b795502..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-generic-exception.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-generic-exception - language: Python - severity: Warning -title: Do not use generic exceptions ---- -## Metadata -**ID:** `python-best-practices/no-generic-exception` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -The specific error must be raised, not a generic `Exception`. Use the exact exception(s) you want to handle and have a recovery handler for each exception that your program may raise. - -#### Learn More - - - [Avoid using `except Exception`](https://jerrynsh.com/stop-using-exceptions-like-this-in-python/#3-avoid-using-except-exception) - -## Non-Compliant Code Examples -```python -a = 2 -b = 0 -try: - c = a /b -except Exception as e: - pass -``` - -## Compliant Code Examples -```python -a = 2 -b = 0 -try: - c = a /b -except ValueError as e: - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-if-true.md b/content/en/static_analysis/rules/python-best-practices/no-if-true.md deleted file mode 100644 index 3667005f7dff7..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-if-true.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-best-practices/no-if-true - language: Python - severity: Notice -title: do not compare to True in a condition ---- -## Metadata -**ID:** `python-best-practices/no-if-true` - -**Language:** Python - -**Severity:** Notice - -**Category:** Code Style - -## Description -Do not use `variable == True`, just use `variable`. Comparing against `True` makes the code more complicated to read. - -## Non-Compliant Code Examples -```python -if foo == True: # just used if foo - print("bar") -``` - -## Compliant Code Examples -```python -if foo: - print("bar") -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md b/content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md deleted file mode 100644 index 555801f945df9..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-range-loop-with-len.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-range-loop-with-len - language: Python - severity: Error -title: Do not use for i in range(len()) ---- -## Metadata -**ID:** `python-best-practices/no-range-loop-with-len` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -Do not iterate over an array using `for in range(len(array))`. Use instead `for i in array`. - -#### Learn More - - - [Python Loop Through an Array](https://www.w3schools.com/python/gloss_python_array_loop.asp) - -## Non-Compliant Code Examples -```python -for i in range(len(tab)): # iterate directly over the array - bla(tab[i]) -``` - -```python -for i in range(len(tab)): # iterate directly over the array - tab[i] = bla -``` - -## Compliant Code Examples -```python -for i in tab: - bla(i) -``` diff --git a/content/en/static_analysis/rules/python-best-practices/no-silent-exception.md b/content/en/static_analysis/rules/python-best-practices/no-silent-exception.md deleted file mode 100644 index caf244b30a26b..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/no-silent-exception.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/no-silent-exception - language: Python - severity: Error -title: Do not ignore Exception with a pass statement ---- -## Metadata -**ID:** `python-best-practices/no-silent-exception` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -Using the `pass` statement in an exception block ignores the exception. Exceptions should never be ignored. Instead, the user must add code to notify an exception occurred and attempt to handle it or recover from it. - -## Non-Compliant Code Examples -```python -a = 2 -b = 0 -try: - c = a /b -except Exception as e: - pass # should use a regular statement and not ignore the exception -``` - -## Compliant Code Examples -```python -a = 2 -b = 0 -try: - c = a /b -except ValueError as e: - print(e) - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/open-add-flag.md b/content/en/static_analysis/rules/python-best-practices/open-add-flag.md deleted file mode 100644 index 59352d039538e..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/open-add-flag.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/open-add-flag - language: Python - severity: Error -title: do not define an open flag for reading ---- -## Metadata -**ID:** `python-best-practices/open-add-flag` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -If a flag is opened for read-only, no need to put a flag to open the file. - - -#### Learn More - - - [Python documentation: `open()`](https://docs.python.org/3/library/functions.html#open) - -## Non-Compliant Code Examples -```python -def print_foo(): - with open("myfile.txt", "r") as myfile: # no need to specify the "r" flag - content = myfile.read() - - with open(path, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): - hasher.update(chunk) -``` - -## Compliant Code Examples -```python -def print_foo(): - with open("myfile.txt") as myfile: - content = myfile.read() -``` diff --git a/content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md b/content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md deleted file mode 100644 index 595c8d3b08b68..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/os-environ-no-assign.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/os-environ-no-assign - language: Python - severity: Error -title: assigning to os.environ does not clear the environment ---- -## Metadata -**ID:** `python-best-practices/os-environ-no-assign` - -**Language:** Python - -**Severity:** Error - -**Category:** Error Prone - -## Description -Assigning to `os.environ` does not clear the environment. To clear the environment, use `os.environ.clear()` - -## Non-Compliant Code Examples -```python -import os - -os.environ = {} # use os.environ.clear -``` - -## Compliant Code Examples -```python -import os - -os.environ.clear() - -``` diff --git a/content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md b/content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md deleted file mode 100644 index a1822159ef15c..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/raising-not-implemented.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/raising-not-implemented - language: Python - severity: Warning -title: Do not raise NotImplemented - it does not exists ---- -## Metadata -**ID:** `python-best-practices/raising-not-implemented` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Code should not raise `NotImplemented` and instead use `NotImplementedError`. `NotImplemented` is a value (as per the [documentation](https://docs.python.org/3/library/constants.html#NotImplemented), not an exception. The proper exception is [NotImplementedError](https://docs.python.org/3/library/exceptions.html#NotImplementedError) - -#### Learn More - - - [NotImplementedError documentation](https://docs.python.org/3/library/exceptions.html#NotImplementedError) - -## Non-Compliant Code Examples -```python -a = 1 -b = 2 -raise NotImplemented # use NotImplementedError instead -c = 3 -``` - -## Compliant Code Examples -```python -a = 1 -b = 2 -raise NotImplementedError -c = 3 -``` diff --git a/content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md b/content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md deleted file mode 100644 index 413961cad5c80..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/return-bytes-not-string.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/return-bytes-not-string - language: Python - severity: Notice -title: __bytes__ method should returns bytes, not string ---- -## Metadata -**ID:** `python-best-practices/return-bytes-not-string` - -**Language:** Python - -**Severity:** Notice - -**Category:** Error Prone - -## Description -The `__bytes__` method should not return a string and instead, ensure to return bytes. - -## Non-Compliant Code Examples -```python -class MyClass: - def __bytes__(self): - pass - return "123" # should return b"123" -``` - -## Compliant Code Examples -```python -class MyClass: - def __bytes__(self): - pass - return b"123" -``` diff --git a/content/en/static_analysis/rules/python-best-practices/return-outside-function.md b/content/en/static_analysis/rules/python-best-practices/return-outside-function.md deleted file mode 100644 index 5f0b4c9fdc6ff..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/return-outside-function.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/return-outside-function - language: Python - severity: Notice -title: do not return outside a function ---- -## Metadata -**ID:** `python-best-practices/return-outside-function` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -All `return` statements must be within a function. Putting a `return` statement outside of a function may have unexpected behaviors (such as exiting the program early). - -## Non-Compliant Code Examples -```python -class Foo: - return 1 # return must be done within a function -``` - -```python -def foo(): - return "bar" - -return "bar" # return must be done within a function -``` - -## Compliant Code Examples -```python -def foobar() - return 2 -``` diff --git a/content/en/static_analysis/rules/python-best-practices/self-assignment.md b/content/en/static_analysis/rules/python-best-practices/self-assignment.md deleted file mode 100644 index 797b098da73c1..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/self-assignment.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/self-assignment - language: Python - severity: Notice -title: do not assign to itself ---- -## Metadata -**ID:** `python-best-practices/self-assignment` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not assign a value to itself. Instead, assign the value to a different variable to make the data flow clear to read and understand. - -## Non-Compliant Code Examples -```python -def foo(): - bar = bar # avoid self assignment -``` - -## Compliant Code Examples -```python -def foo(): - bar = baz -``` diff --git a/content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md b/content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md deleted file mode 100644 index 0f64865eac30c..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/slots-no-single-string.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: python-best-practices/slots-no-single-string - language: Python - severity: Error -title: __slots__ should not be a single string ---- -## Metadata -**ID:** `python-best-practices/slots-no-single-string` - -**Language:** Python - -**Severity:** Error - -**Category:** Error Prone - -## Description -The `__slots__` attribute must be a non-string iterable. - -#### Learn More - - - [Python Wiki: Using slots](https://wiki.python.org/moin/UsingSlots) - -## Non-Compliant Code Examples -```python -class MyClass: - __slots__ = "attr" # should be an iterable - - def __init__(self): - pass -``` - -## Compliant Code Examples -```python -from django.apps import AppConfig - - -class TweetsConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'tweets' -``` - -```python -class MyClass: - __slots__ = ("attr", ) - - def __init__(self): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md b/content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md deleted file mode 100644 index 5a85a7925dd5b..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/special-methods-arguments.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/special-methods-arguments - language: Python - severity: Error -title: ensure special methods have the correct arguments ---- -## Metadata -**ID:** `python-best-practices/special-methods-arguments` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -For all special methods for an class (`__add__`, `__sub__`, and more) make sure the method has the correct number of arguments. - -## Non-Compliant Code Examples -```python -class GFG: - - def __init__(self, val): - self.val = val - - def __next__(self, val2, val3): # invalid, we should have only one argument. - return GFG(self.val + val2.val) -``` - -```python -class GFG: - - def __init__(self, val): - self.val = val - - def __add__(self, val2, val3): # we should hvea only two arguments. - return GFG(self.val + val2.val) -``` - -## Compliant Code Examples -```python -class GFG: - - def __init__(self, val): - self.val = val - - def __add__(self, val2): - return GFG(self.val + val2.val) -``` diff --git a/content/en/static_analysis/rules/python-best-practices/static-method-no-self.md b/content/en/static_analysis/rules/python-best-practices/static-method-no-self.md deleted file mode 100644 index 0c9a7708ad6b3..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/static-method-no-self.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/static-method-no-self - language: Python - severity: Error -title: do not use self as parameter for static methods ---- -## Metadata -**ID:** `python-best-practices/static-method-no-self` - -**Language:** Python - -**Severity:** Error - -**Category:** Best Practices - -## Description -A static method makes no use of an instance. Therefore, the `self` argument is not needed nor useful and should not be used. - -## Non-Compliant Code Examples -```python -class Foo: - @staticmethod - def foo(self, bar): # no need to use the self argument with a @staticmethod - pass -``` - -## Compliant Code Examples -```python -class Foo: - @staticmethod - def foo(bar): - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md b/content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md deleted file mode 100644 index 19db77d99f217..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/too-many-nested-if.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/too-many-nested-if - language: Python - severity: Warning -title: do not use too many nested if conditions ---- -## Metadata -**ID:** `python-best-practices/too-many-nested-if` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Too many nested loops make the code hard to read and understand. Simplify your code by removing nesting levels and separate code in small units. - -## Non-Compliant Code Examples -```python -if foo: - if bar: - if baz: - if bao: - pass -``` - -## Compliant Code Examples -```python -if foo: - if bar: - if baz: - pass -``` diff --git a/content/en/static_analysis/rules/python-best-practices/too-many-while.md b/content/en/static_analysis/rules/python-best-practices/too-many-while.md deleted file mode 100644 index 5d7377293e0ec..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/too-many-while.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/too-many-while - language: Python - severity: Warning -title: do not use too many nested loops and conditions ---- -## Metadata -**ID:** `python-best-practices/too-many-while` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -A program should have a maximum level of nesting loops. If your program has too many nested loops (`if`/`for`/`while`), consider refactoring your program to avoid too many nesting levels. - -## Non-Compliant Code Examples -```python -while bla: - while foo: - while bar: - while baz: - pass - -``` - -## Compliant Code Examples -```python -while bla: - while foo: - while bar: - pass - -``` diff --git a/content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md b/content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md deleted file mode 100644 index 532db22e84de9..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/type-check-isinstance.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/type-check-isinstance - language: Python - severity: Notice -title: use isinstance instead of type ---- -## Metadata -**ID:** `python-best-practices/type-check-isinstance` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Using `isinstance` is faster than `type` but also consider inheritance, which makes it more accurate. - -## Non-Compliant Code Examples -```python -# use isinstance instead of -if type(Foo()) == Foo: - print("is foo") -``` - -## Compliant Code Examples -```python -raise ValueError("target %s config %s has type of %s" % (target, config_content, type(config_content))) -``` - -```python -if isinstance(Bar(), Foo): - print("foo") -``` diff --git a/content/en/static_analysis/rules/python-best-practices/unreachable-code.md b/content/en/static_analysis/rules/python-best-practices/unreachable-code.md deleted file mode 100644 index 11daefb5dc8b9..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/unreachable-code.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/unreachable-code - language: Python - severity: Notice -title: avoid unreachable code ---- -## Metadata -**ID:** `python-best-practices/unreachable-code` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Avoid unreachable code. If the code cannot be reached because of a coding mistake, fix the business logic. If the code should not be used, remove it. - - -#### Learn More - - - [Carnegie Mellon University: Avoid having unreachable code](https://wiki.sei.cmu.edu/confluence/display/android/Avoid+having+unreachable+code) - -## Non-Compliant Code Examples -```python -def foo(): - return 3 - foo() # unreachable code - pass # unreachable code -``` - -## Compliant Code Examples -```python -def foo(): - foo() - pass - return 3 - -``` diff --git a/content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md b/content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md deleted file mode 100644 index 16b06a582a312..0000000000000 --- a/content/en/static_analysis/rules/python-best-practices/use-callable-not-hasattr.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-best-practices/use-callable-not-hasattr - language: Python - severity: Notice -title: do not use hasattr to check if a value is callable ---- -## Metadata -**ID:** `python-best-practices/use-callable-not-hasattr` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not make any check using `hasattr` to check if a function is callable since the object may have redefine `__getattr__`. Instead, use `callable()`. - -#### Learn More - - - [Python Documentation: callable() built-in](https://docs.python.org/3/library/functions.html#callable) - -## Non-Compliant Code Examples -```python -hasattr(x, '__call__') # use callable -``` - -## Compliant Code Examples -```python -callable(x) -``` diff --git a/content/en/static_analysis/rules/python-code-style/assignment-names.md b/content/en/static_analysis/rules/python-code-style/assignment-names.md deleted file mode 100644 index 90e2436dfdc2c..0000000000000 --- a/content/en/static_analysis/rules/python-code-style/assignment-names.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-code-style/assignment-names - language: Python - severity: Error -title: variable names must use snake_case ---- -## Metadata -**ID:** `python-code-style/assignment-names` - -**Language:** Python - -**Severity:** Error - -**Category:** Code Style - -## Description -Ensure that variable names use `snake_case` and not `camelCase`. - -#### Learn More - -- [PEP8 - Naming Style](https://peps.python.org/pep-0008/#descriptive-naming-styles) - -## Non-Compliant Code Examples -```python -fooBar = foobar() -``` - -```python -firstVariable, secondVariable = functioncall() -``` - -## Compliant Code Examples -```python -hello = 1 -``` - -```python -fooBAr = foobar() -``` diff --git a/content/en/static_analysis/rules/python-code-style/class-name.md b/content/en/static_analysis/rules/python-code-style/class-name.md deleted file mode 100644 index 9b7e795b40459..0000000000000 --- a/content/en/static_analysis/rules/python-code-style/class-name.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-code-style/class-name - language: Python - severity: Notice -title: class name should be CamelCase ---- -## Metadata -**ID:** `python-code-style/class-name` - -**Language:** Python - -**Severity:** Notice - -**Category:** Code Style - -## Description -Class names should be `CamelCase` and not `camelCase` or `snake_case`. - -#### Learn More - - - [PEP8 style guide](https://peps.python.org/pep-0008/#descriptive-naming-styles) - -## Non-Compliant Code Examples -```python -class _runtimeMetricsStatus(type): - pass -``` - -```python -class myClass(Parent): - def __init__(self): - pass - - -``` - -## Compliant Code Examples -```python -class REQUESTS_MODE(IntEnum): - AGENTLESS_EVENTS = 0 - EVP_PROXY_EVENTS = 1 -``` - -```python -class _RuntimeMetricsStatus(type): - pass -``` - -```python -class Migration(migrations.Migration): - - dependencies = [ - ('tweets', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='tweet', - name='parent', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='tweets.tweet'), - ), - migrations.DeleteModel( - name='Reply', - ), - ] -``` - -```python -class MyClass(Parent): - def __init__(self): - pass - -class TestRestapiV4Lock(FunctionalTestController): - pass - -class TestS3Storage(TestCase): - pass - - -class TestS35Storage(TestCase): - pass - - - -class TestS35Storage(TestCase): - pass - -``` diff --git a/content/en/static_analysis/rules/python-code-style/function-naming.md b/content/en/static_analysis/rules/python-code-style/function-naming.md deleted file mode 100644 index 76416f658c724..0000000000000 --- a/content/en/static_analysis/rules/python-code-style/function-naming.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-code-style/function-naming - language: Python - severity: Notice -title: function name and parameters should use snake_case ---- -## Metadata -**ID:** `python-code-style/function-naming` - -**Language:** Python - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that function use `snake_case`. - -This rule is not valid for tests files (prefixed by `test_` or suffixed by `_test.py`) because testing requires some camel case methods, such as, `tearDown`, `setUp`, and more. - -#### Learn More - - - [Python Documentation Testing: `setUp()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUp) - -## Non-Compliant Code Examples -```python -def my_function(myParameter, otherParameter): - pass -``` - -```python -def myFunction(arg1, arg2): - pass - -def myOtherFunction(): - pass -``` - -## Compliant Code Examples -```python -# name used in many testing frameworks. Do not warn on it -def tearDown(self): - """After each test case, reset and remove the dummy tracer""" - super(TracerTestCase, self).tearDown() -``` - -```python -class TestModel(unittest.TestCase): - def setUp(self): # used in a file model_test.py, skip the rule for setUp and tearDown - pass - - def tearDown(self): # used in a file model_test.py, skip the rule for setUp and tearDown - pass - - def test_violation_category(self): - self.assertEqual(ViolationCategory.BEST_PRACTICE.value, 1) - self.assertEqual(ViolationCategory.DESIGN.value, 2) - v1 = Violation("bla", 1, "description", 2, ViolationCategory.BEST_PRACTICE, 10, "notool") - self.assertEqual(v1.get_category_string(), "Best Practices") - v1 = Violation("bla", 1, "description", 2, 1, 10, "notool") - self.assertEqual(v1.get_category_string(), "Unknown") -``` diff --git a/content/en/static_analysis/rules/python-code-style/max-class-lines.md b/content/en/static_analysis/rules/python-code-style/max-class-lines.md deleted file mode 100644 index 873be711fa561..0000000000000 --- a/content/en/static_analysis/rules/python-code-style/max-class-lines.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-code-style/max-class-lines - language: Python - severity: Warning -title: classes must be less than 100 lines ---- -## Metadata -**ID:** `python-code-style/max-class-lines` - -**Language:** Python - -**Severity:** Warning - -**Category:** Code Style - -## Description -A class must stay short (less than 100 lines) to be easy to understand. If your class or function is more than 100 lines, you should refactor your code and ensure that your class is less than 100 lines. - -## Non-Compliant Code Examples -```python -class MyClass: - def __init__(self): - pass - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def foo(self): - pass -``` - -## Compliant Code Examples -```python -class MyClass: - def __init__(self): - pass - - def foo(self): - pass -``` diff --git a/content/en/static_analysis/rules/python-code-style/max-function-lines.md b/content/en/static_analysis/rules/python-code-style/max-function-lines.md deleted file mode 100644 index 9afecd61d1cf6..0000000000000 --- a/content/en/static_analysis/rules/python-code-style/max-function-lines.md +++ /dev/null @@ -1,259 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-code-style/max-function-lines - language: Python - severity: Error -title: Functions must be less than 200 lines ---- -## Metadata -**ID:** `python-code-style/max-function-lines` - -**Language:** Python - -**Severity:** Error - -**Category:** Code Style - -## Description -Ensure that a function is not too long. A function should be less than 100 lines. Otherwise, it's too long and hard to understand. - -## Non-Compliant Code Examples -```python -def myfunction(): - foo() - bar() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - pass -``` - -## Compliant Code Examples -```python -def myfunction(args): - foo() - bar() - pass -``` diff --git a/content/en/static_analysis/rules/python-design/function-too-long.md b/content/en/static_analysis/rules/python-design/function-too-long.md deleted file mode 100644 index ed0777e1c5006..0000000000000 --- a/content/en/static_analysis/rules/python-design/function-too-long.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-design/function-too-long - language: Python - severity: Warning -title: functions must have less than 100 lines ---- -## Metadata -**ID:** `python-design/function-too-long` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Function should be short to be easy to understand and maintain. Functions more of 100 lines trigger a warning and should be refactored into smaller units of code. - -## Non-Compliant Code Examples -```python -def myfunc(): # function is too long - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - pass -``` - -## Compliant Code Examples -```python -def myfunc(): - pass -``` diff --git a/content/en/static_analysis/rules/python-django/http-response-from-request.md b/content/en/static_analysis/rules/python-django/http-response-from-request.md deleted file mode 100644 index ee9ce1411d90c..0000000000000 --- a/content/en/static_analysis/rules/python-django/http-response-from-request.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-django/http-response-from-request - language: Python - severity: Error -title: Lack of sanitization of user data ---- -## Metadata -**ID:** `python-django/http-response-from-request` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -The response sent with an `HttpResponse` contains unsanitized request data. The data should be sanitized before being returns in an `HttpResponse`. - -#### Learn More - - - [CWE-20: Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html) - -## Non-Compliant Code Examples -```python -def execute_command(request): - data = request.GET.get("data") - print("foobar") - foo = HttpResponse("data: '{0}'".format(data)) - foo = HttpResponse(data) - return HttpResponse("data: '{0}'".format(data)) -``` - -## Compliant Code Examples -```python -def execute_command(request): - data = request.GET.get("data") - print("foobar") - return HttpResponse("user '{user}' does not exist".format(sanitize_data(data))) - -``` diff --git a/content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md b/content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md deleted file mode 100644 index f91b81853f8c8..0000000000000 --- a/content/en/static_analysis/rules/python-django/http-response-with-json-dumps.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-django/http-response-with-json-dumps - language: Python - severity: Notice -title: use JsonResponse instead of HttpResponse to send JSON data ---- -## Metadata -**ID:** `python-django/http-response-with-json-dumps` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Use `JsonResponse` instead of `HttpResponse` when attempting to send JSON data. - -## Non-Compliant Code Examples -```python -import json - -from django.http import HttpResponse - -response_data = {} -response_data['result'] = 'error' -response_data['message'] = 'Some error message' -return HttpResponse(json.dumps(response_data)) # use a JsonResponse to send JSON data - -``` - -## Compliant Code Examples -```python -import json - -from django.http import HttpResponse - -response_data = {} -response_data['result'] = 'error' -response_data['message'] = 'Some error message' -return JsonResponse(response_data) -``` diff --git a/content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md b/content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md deleted file mode 100644 index 09a07b6e8b0b7..0000000000000 --- a/content/en/static_analysis/rules/python-django/jsonresponse-no-content-type.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-django/jsonresponse-no-content-type - language: Python - severity: Notice -title: do not specify content-type for JsonResponse ---- -## Metadata -**ID:** `python-django/jsonresponse-no-content-type` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -The `JsonResponse` is already setting the content type of the response. Do not redefine the content type being sent. - -## Non-Compliant Code Examples -```python -import json - -from django.http import HttpResponse - -response_data = {} -response_data['result'] = 'error' -response_data['message'] = 'Some error message' -return JsonResponse(response_data, content_type="application/json") # content-type is not necessary for JsonResponse -``` - -## Compliant Code Examples -```python -import json - -from django.http import HttpResponse - -response_data = {} -response_data['result'] = 'error' -response_data['message'] = 'Some error message' -return JsonResponse(response_data) # content-type is not necessary for JsonResponse -``` diff --git a/content/en/static_analysis/rules/python-django/model-charfield-max-length.md b/content/en/static_analysis/rules/python-django/model-charfield-max-length.md deleted file mode 100644 index 2286a3fab02e4..0000000000000 --- a/content/en/static_analysis/rules/python-django/model-charfield-max-length.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-django/model-charfield-max-length - language: Python - severity: Warning -title: always specify max_length for a Charfield ---- -## Metadata -**ID:** `python-django/model-charfield-max-length` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -On a `Charfield`, define the attribute `max_length` to specify the maximum size of a field. - -## Non-Compliant Code Examples -```python -class Person(models.Model): - first_name = models.CharField() # define max_length - last_name = models.CharField() # define max_length -``` - -## Compliant Code Examples -```python -class Person(models.Model): - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=40) -``` diff --git a/content/en/static_analysis/rules/python-django/model-help-text.md b/content/en/static_analysis/rules/python-django/model-help-text.md deleted file mode 100644 index feb1e6aeadc72..0000000000000 --- a/content/en/static_analysis/rules/python-django/model-help-text.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-django/model-help-text - language: Python - severity: Notice -title: use help_text to document model columns ---- -## Metadata -**ID:** `python-django/model-help-text` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Use `help_text` to document the fields used in your database. - -#### Learn More - - - [Django Documentation: `help_text`](https://docs.djangoproject.com/en/4.2/ref/models/fields/#help-text) - -## Non-Compliant Code Examples -```python -class MyModel(models.Model): - my_field = models.DateField() - last_name = models.CharField(max_length=40) # add help_text to explain what this field is doing -``` - -## Compliant Code Examples -```python -class MyModel(models.Model): - my_field = models.DateField(help_text = "Use format YYYY/MM/DD") -``` diff --git a/content/en/static_analysis/rules/python-django/no-null-boolean.md b/content/en/static_analysis/rules/python-django/no-null-boolean.md deleted file mode 100644 index 478864f235207..0000000000000 --- a/content/en/static_analysis/rules/python-django/no-null-boolean.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-django/no-null-boolean - language: Python - severity: Notice -title: do not use NullBooleanField ---- -## Metadata -**ID:** `python-django/no-null-boolean` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -The `NullBooleanField` type is deprecated. Use the `BooleanField` instead. - -## Non-Compliant Code Examples -```python -class Person(models.Model): - is_adult = models.NullBooleanField() # use BooleanField - -``` - -## Compliant Code Examples -```python -class Person(models.Model): - is_adult = models.BooleanField(null=True) -``` diff --git a/content/en/static_analysis/rules/python-django/no-unicode-on-models.md b/content/en/static_analysis/rules/python-django/no-unicode-on-models.md deleted file mode 100644 index 544c715a5a75c..0000000000000 --- a/content/en/static_analysis/rules/python-django/no-unicode-on-models.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-django/no-unicode-on-models - language: Python - severity: Warning -title: do not use __unicode__ ---- -## Metadata -**ID:** `python-django/no-unicode-on-models` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Do not use `__unicode__` on Django models. The field `__unicode__` is used for Python 2. Use `__str__` instead, `__str__` is used with Python 3. - -## Non-Compliant Code Examples -```python -class Person(models.Model): - - def __unicode__(self): # do not define __unicode__, define __str__ - pass -``` - -## Compliant Code Examples -```python -class Person(models.Model): - - def __str__(self): - "person" -``` diff --git a/content/en/static_analysis/rules/python-django/open-filename-from-request.md b/content/en/static_analysis/rules/python-django/open-filename-from-request.md deleted file mode 100644 index 16cbaa5681ef5..0000000000000 --- a/content/en/static_analysis/rules/python-django/open-filename-from-request.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-django/open-filename-from-request - language: Python - severity: Error -title: Filename coming from the request ---- -## Metadata -**ID:** `python-django/open-filename-from-request` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Improper validation of input data, leading to potential data leaks. The path should be checked and validated before opening a file in order to prevent opening random files and leaking data. - -#### Learn More - - - [CWE-22: Improper Limitation of a Pathname to a Restricted Directory](https://cwe.mitre.org/data/definitions/22.html) - -## Non-Compliant Code Examples -```python -def download_file1(request): - url = request.GET.get("filename") - print(f"url of the file: {url}") - file = open(url, "rb") - - with open(url) as f: - pass - pass - - -def download_file2(request): - url = request.POST.get("filename") - print(f"url of the file: {url}") - file = open(url, "rb") - - with open(url) as f: - pass - pass - -def download_file3(request): - url = request.BLA.get("filename") - print(f"url of the file: {url}") - file = open(url, "rb") - - with open(url) as f: - pass - pass -``` - -## Compliant Code Examples -```python -import os - -def download_file(request): - url = request.GET.get("filename") - - if ".." in url: - return - - sanitized_path = os.path.realpath(url, strict=True) - - print(f"url of the file: {url}") - file = open(sanitized_path, "rb") - - with open(sanitized_path) as f: - pass - pass -``` diff --git a/content/en/static_analysis/rules/python-django/os-system-from-request.md b/content/en/static_analysis/rules/python-django/os-system-from-request.md deleted file mode 100644 index 9d86318dd4c1e..0000000000000 --- a/content/en/static_analysis/rules/python-django/os-system-from-request.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-django/os-system-from-request - language: Python - severity: Error -title: Command coming from incoming request ---- -## Metadata -**ID:** `python-django/os-system-from-request` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Execute a process using unsanitized and unvalidated user-inputs. The user data should be sanitized and validated before being used to launch a new process. - -#### Learn More - - - [CWE-20: Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html) - -## Non-Compliant Code Examples -```python -import os - -def execute_command(request): - cmd = request.GET.get("cmd") - print("foobar") - os.system(cmd) - - bli = os.system(cmd) - -``` - -## Compliant Code Examples -```python -import os -import shlex - -def execute_command(request): - cmd = request.GET.get("cmd") - print("foobar") - os.system(shlex.escape(cmd)) - -``` diff --git a/content/en/static_analysis/rules/python-django/subprocess-from-request.md b/content/en/static_analysis/rules/python-django/subprocess-from-request.md deleted file mode 100644 index f588019689648..0000000000000 --- a/content/en/static_analysis/rules/python-django/subprocess-from-request.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-django/subprocess-from-request - language: Python - severity: Error -title: Command coming from incoming request ---- -## Metadata -**ID:** `python-django/subprocess-from-request` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Execute a process using unsanitized and unvalidated user-inputs. The user data should be sanitized and validated before being used to launch a new process. - -#### Learn More - - - [CWE-20: Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html) - -## Non-Compliant Code Examples -```python -import subprocess - -def execute_command(request): - cmd = request.GET.get("cmd") - print("foobar") - subprocess.run(cmd) - subprocess.call(cmd) - subprocess.capture_output(cmd) - subprocess.call(["bash", cmd]) - - bli = subprocess.run(cmd) - bla = subprocess.call(cmd) - ble = subprocess.capture_output(cmd) - blo = subprocess.call(["bash", cmd]) - blip = subprocess.call("bash {0}".format(cmd)) - blop = subprocess.call("bash " + cmd) - - -``` - -## Compliant Code Examples -```python -import subprocess - -def execute_command(request): - cmd = request.GET.get("cmd") - print("foobar") - subprocess.run(shlex.escape(cmd)) - -``` diff --git a/content/en/static_analysis/rules/python-django/use-convenience-imports.md b/content/en/static_analysis/rules/python-django/use-convenience-imports.md deleted file mode 100644 index 7f5d0c4e926b0..0000000000000 --- a/content/en/static_analysis/rules/python-django/use-convenience-imports.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-django/use-convenience-imports - language: Python - severity: Notice -title: use convenience imports whenever possible ---- -## Metadata -**ID:** `python-django/use-convenience-imports` - -**Language:** Python - -**Severity:** Notice - -**Category:** Code Style - -## Description -Use convenient imports from Django whenever possible. - -## Non-Compliant Code Examples -```python -from django.views.generic.base import View # use django.views -``` - -## Compliant Code Examples -```python -from django.views import View -``` diff --git a/content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md b/content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md deleted file mode 100644 index 8e0938cb9af9f..0000000000000 --- a/content/en/static_analysis/rules/python-flask/disable-sqlalchemy-text.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/disable-sqlalchemy-text - language: Python - severity: Warning -title: Do not use text() as it leads to SQL injection ---- -## Metadata -**ID:** `python-flask/disable-sqlalchemy-text` - -**Language:** Python - -**Severity:** Warning - -**Category:** Security - -## Description -The `text` function from SQLAlchemy lets you build custom SQL statements. It is recommended to use the ORM functions to build queries and avoid building custom queries, which are vulnerable to SQL injections. - -#### Learn More - - - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) - -## Non-Compliant Code Examples -```python -from sqlalchemy.sql import text - - -con = engine.connect() - -data = ( { "id": 1, "title": "The Hobbit", "primary_author": "Tolkien" }, - { "id": 2, "title": "The Silmarillion", "primary_author": "Tolkien" }, -) - -statement = text("""INSERT INTO book(id, title, primary_author) VALUES(:id, :title, :primary_author)""") - -for line in data: - con.execute(statement, **line) -``` - -## Compliant Code Examples -```python -con = engine.connect() - -data = ( { "id": 1, "title": "The Hobbit", "primary_author": "Tolkien" }, - { "id": 2, "title": "The Silmarillion", "primary_author": "Tolkien" }, -) - -statement = text("""INSERT INTO book(id, title, primary_author) VALUES(:id, :title, :primary_author)""") - -for line in data: - con.execute(statement, **line) -``` - -```python -from sqlalchemy import text - -BOOKS = meta.tables['books'] -query = sqlalchemy.select(BOOKS).where(BOOKS.c.genre == 'fiction') -result = engine.execute(query).fetchall() - - -``` diff --git a/content/en/static_analysis/rules/python-flask/html-format-from-user-input.md b/content/en/static_analysis/rules/python-flask/html-format-from-user-input.md deleted file mode 100644 index 83bbeea8397dc..0000000000000 --- a/content/en/static_analysis/rules/python-flask/html-format-from-user-input.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/html-format-from-user-input - language: Python - severity: Error -title: Use of unsanitized data to make API calls ---- -## Metadata -**ID:** `python-flask/html-format-from-user-input` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Use of unsanitized from incoming request for SQL queries is unsafe and leads to SQL injections. Data from requests must be sanitized before being used to issues SQL queries, open file or deserialize data. Make sure the data is sanitized before use. - -#### Learn More - - - [CWE-79: Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) - -## Non-Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - - -@app.route("/route/to/resource/") -def resource1(resource_id): - return f"Click me!" - -@app.route("/route/to/resource/") -def resource2(resource_id): - return "Click me!".format(resource_id) - - -@app.route("/route/to/resource/") -def resource3(): - resource_id = flask.request.args.get("resource_id") - return "Click me!" % resource_id - - -@app.route("/route/to/resource/") -def resource4(resource_id): - ret = f"Click me!" - return ret - -@app.route("/route/to/resource/") -def resource2(): - resource_id = flask.request.args.get("resource_id") - ret = "Click me!".format(resource_id) - return ret - - -@app.route("/route/to/resource/") -def resource3(resource_id): - ret = "Click me!" % resource_id - return ret - -``` - -## Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - - -@app.route("/route/to/resource/") -def resource2(resource_id): - return "Click me!".format(sanitize(resource_id)) - - -@app.route("/route/to/resource/") -def resource2(): - resource_id = get.data() - ret = requests.get(foo); - ret = "Click me!".format(resource_id) - return ret - - -``` diff --git a/content/en/static_analysis/rules/python-flask/listen-all-interfaces.md b/content/en/static_analysis/rules/python-flask/listen-all-interfaces.md deleted file mode 100644 index e6caf84799504..0000000000000 --- a/content/en/static_analysis/rules/python-flask/listen-all-interfaces.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/listen-all-interfaces - language: Python - severity: Notice -title: Your application should not listen on all interfaces ---- -## Metadata -**ID:** `python-flask/listen-all-interfaces` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -Avoid giving access to your resources to all connected interfaces. Instead, bind the resources on a specific interface. Running the server on 0.0.0.0 exposes the server publicly. - -#### Learn More - - - [CWE-668 - Exposure of Resource to Wrong Sphere](https://cwe.mitre.org/data/definitions/668.html) - - [OWASP A01-2021 - Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) - -## Non-Compliant Code Examples -```python -#ruleid:avoid_app_run_with_bad_host -app.run(host="0.0.0.0") - -#ruleid:avoid_app_run_with_bad_host -app.run("0.0.0.0") - -``` - -## Compliant Code Examples -```python -#ruleid:avoid_app_run_with_bad_host -app.run(host="192.168.10.4") - -#ruleid:avoid_app_run_with_bad_host -app.run("192.168.10.4") - -``` diff --git a/content/en/static_analysis/rules/python-flask/no-render-template-string.md b/content/en/static_analysis/rules/python-flask/no-render-template-string.md deleted file mode 100644 index 0a9ceb4400d44..0000000000000 --- a/content/en/static_analysis/rules/python-flask/no-render-template-string.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/no-render-template-string - language: Python - severity: Error -title: Do not use template created with strings ---- -## Metadata -**ID:** `python-flask/no-render-template-string` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Using templates created with string leads to server-side injection. Use template based on files. - -#### Learn More - - - [CWE-96: Improper Neutralization of Directives in Statically Saved](https://cwe.mitre.org/data/definitions/96.html) - -## Non-Compliant Code Examples -```python -import os -from functools import wraps -from flask import request, redirect, url_for, render_template_string - - -API_KEY = os.environ.get('VULN_FLASK_APP_API_KEY') - -# Decorator to check if user is logged in -def require_api_key(f): - @wraps(f) - def wrap(*args, **kwargs): - api_key = request.cookies.get('api_key') - if API_KEY is None or api_key == API_KEY: - return f(*args, **kwargs) - else: - return render_template_string('no api key found'), 401 - return wrap -``` diff --git a/content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md b/content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md deleted file mode 100644 index a29eeb18bdfb8..0000000000000 --- a/content/en/static_analysis/rules/python-flask/open-file-unsanitized-data.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/open-file-unsanitized-data - language: Python - severity: Error -title: Use of unsanitized data to open file ---- -## Metadata -**ID:** `python-flask/open-file-unsanitized-data` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Use of unsanitized from incoming request, leading to potential data leak and lack of control of the service. Do not use unsanitized data to control file operations. The code should check any incoming data and make sure it's safe to use it. - -#### Learn More - - - [CWE-22: CWE-22: Improper Limitation of a Pathname to a Restricted Directory](https://cwe.mitre.org/data/definitions/22.html) - -## Non-Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - - -@app.route("/route/to/resource/") -def resource1(resource_id): - with open(resource_id) as f: - pass - with open(f"/path/to/{resource_id}") as f: - pass - with open("/path/to/{0}".format(resource_id)) as f: - pass - with open("/path/to/{0}".other(resource_id)) as f: - pass - -@app.route("/route/to/resource/") -def resource2(resource_id): - file1 = open(resource_id) - file2 = open(f"/path/to/{resource_id}") - file3 = open("/path/to/{0}".format(resource_id)) - - -@app.route("/route/to/resource") -def resource2(): - resource_id = flask.request.args.get("resource_id") - file1 = open(resource_id) - file2 = open(f"/path/to/{resource_id}") - file3 = open("/path/to/{0}".format(resource_id)) -``` - -## Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - -@app.route("/route/to/resource/") -def resource2(resource_id): - sanitized_resource_id = sanitize(resource_id) - file1 = open(sanitized_resource_id) -``` diff --git a/content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md b/content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md deleted file mode 100644 index 3d66e94e692c5..0000000000000 --- a/content/en/static_analysis/rules/python-flask/os-system-unsanitized-data.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/os-system-unsanitized-data - language: Python - severity: Error -title: Use of unsanitized data to create processes ---- -## Metadata -**ID:** `python-flask/os-system-unsanitized-data` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Use of unsanitized from incoming request to execute a command may lead to command injection. It is highly recommended that data is checked and sanitized before use. - -#### Learn More - - - [CWE-78: roper Neutralization of Special Elements used in an OS](https://cwe.mitre.org/data/definitions/78.html) - -## Non-Compliant Code Examples -```python -import flask -import os - -app = flask.Flask(__name__) - - - -@app.route("/route/to/resource/") -def resource2(resource_id): - file1 = subprocess.call(resource_id) - file2 = subprocess.capture_output(f"/path/to/{resource_id}") - -@app.route("/route/to/resource/") -def resource2(resource_id): - file4 = os.system("/path/to/{0}".format(resource_id)) - os.system(request.remote_addr) - bla = os.system(request.foo) - -@app.route("/route/to/resource") -def resource2(): - resource_id = flask.request.args.get("resource_id") - subprocess.call(resource_id) - subprocess.run(["command", resource_id]) -``` - -## Compliant Code Examples -```python -import flask -import os - -app = flask.Flask(__name__) - -@app.route("/route/to/resource/") -def resource2(resource_id): - file1 = subprocess.call(sanitize(resource_id)) - file2 = subprocess.capture_output(f"/path/to/{sanitize(resource_id)}") -``` diff --git a/content/en/static_analysis/rules/python-flask/secure-cookie.md b/content/en/static_analysis/rules/python-flask/secure-cookie.md deleted file mode 100644 index 5f0b30df266f0..0000000000000 --- a/content/en/static_analysis/rules/python-flask/secure-cookie.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/secure-cookie - language: Python - severity: Notice -title: Make sure cookies are safe and secure ---- -## Metadata -**ID:** `python-flask/secure-cookie` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -Cookies must have the `secure` and `httponly` parameters set to True. - -#### Learn More - - - [CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute](https://cwe.mitre.org/data/definitions/614.html) - -## Non-Compliant Code Examples -```python -response.set_cookie('username', 'flask', secure=False, httponly=False, samesite="Lax") -response.set_cookie('username', 'flask', secure=True, httponly=False, samesite="Lax") -response.set_cookie('username', 'flask', secure=False, httponly=True, samesite=None) -response.set_cookie('username', 'flask', samesite=None, secure=False, httponly=True) -response.set_cookie('username', 'flask', secure=False, samesite=None) -response.set_cookie('username', 'flask', samesite=None, httponly=True) - -``` - -## Compliant Code Examples -```python -response.set_cookie('username', 'flask', secure=True, httponly=True, samesite='Lax') -``` diff --git a/content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md b/content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md deleted file mode 100644 index 8d8de47616b4d..0000000000000 --- a/content/en/static_analysis/rules/python-flask/sqlalchemy-injection.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/sqlalchemy-injection - language: Python - severity: Error -title: Use of unsanitized data to issue SQL queries ---- -## Metadata -**ID:** `python-flask/sqlalchemy-injection` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Use of unsanitized data from incoming requests in SQL queries may lead to SQL injections. Instead, the data should be filtered and sanitized before use, making sure all potential SQL injections are avoided. - -#### Learn More - - - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) - -## Non-Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - - - -@app.route("/route/to/resource/") -def resource2(resource_id): - file1 = query.order_by(resource_id) - file2 = query.having(f"{resource_id}") - -@app.route("/route/to/resource/") -def resource3(resource_id): - file3 = query.filter("{0}".format(resource_id)) - - -@app.route("/route/to/resource") -def resource2(): - resource_id = flask.request.args.get("resource_id") - file1 = query.group_by(resource_id) -``` - -## Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - -@app.route("/route/to/resource") -def resource2(): - resource_id = flask.request.args.get("resource_id") - file1 = query.group_by(sanitize(resource_id)) -``` diff --git a/content/en/static_analysis/rules/python-flask/ssrf-requests.md b/content/en/static_analysis/rules/python-flask/ssrf-requests.md deleted file mode 100644 index 69fd3f752d5f5..0000000000000 --- a/content/en/static_analysis/rules/python-flask/ssrf-requests.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/ssrf-requests - language: Python - severity: Error -title: Use of unsanitized data to make API calls ---- -## Metadata -**ID:** `python-flask/ssrf-requests` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Use of unsanitized data from incoming request for handling SQL request may lead to SQL injection. Incoming request data must always be sanitized before used. - -#### Learn More - - - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) - -## Non-Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - -@app.route("/route/to/resource/") -def resource(resource_id): - foo = requests.get(f"https://api.service.ext/get/by/id/{resource_id}") - return None - - -@app.route("/route/to/resource/") -def resource2(resource_id): - bar = requests.get("https://api.service.ext/get/by/id/" + resource_id}) - return None - -@app.route("/route/to/resource/") -def resource3(resource_id): - baz = requests.get("https://api.service.ext/get/by/id/{0}".format(resource_id})) - return None - - -@app.get("/route/to/another/resource/") -def resource4(resource_id): - foo = requests.get(f"https://api.service.ext/get/by/id/{resource_id}") - return None - -@app.get("/route/to/another/resource/") -def resource5(resource_id): - bar = requests.get("https://api.service.ext/get/by/id/" + resource_id}) - return None - -@app.get("/route/to/another/resource/") -def resource6(resource_id): - baz = requests.get("https://api.service.ext/get/by/id/{0}".format(resource_id})) - return None - -@app.route("/route/to/resource/the/return/", methods=["GET"]) -def get_param(): - rid = flask.request.args.get("resource_id") - # unsanitized data - requests.post(f"https://api.service.ext/get/by/id/{rid}", timeout=10) - requests.patch(rid, timeout=10) - requests.get("https://api.service.ext/get/by/id/{0}".format(rid)) - requests.get("https://api.service.ext/get/by/id/" + rid) - requests.patch(rid, timeout=10) - return None - -@app.route("/this/is/fine/") -def fine(sure): - print("foobar") - return requests.get("https://api.service.ext/nothing") -``` - -## Compliant Code Examples -```python -import flask -import requests - -app = flask.Flask(__name__) - -@app.route("/route/to/resource/") -def resource(resource_id): - sanitized_resource_id = sanitize(resource_id) - foo = requests.get(f"https://api.service.ext/get/by/id/{sanitized_resource_id}") - return foo -``` diff --git a/content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md b/content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md deleted file mode 100644 index 3d48206294fdc..0000000000000 --- a/content/en/static_analysis/rules/python-flask/urlopen-unsanitized-data.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-flask/urlopen-unsanitized-data - language: Python - severity: Error -title: Use of unsanitized data to open API ---- -## Metadata -**ID:** `python-flask/urlopen-unsanitized-data` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Use of unsanitized from incoming request, leading to potential data leak and lack of control of the service. The code should check any incoming data and make sure it's safe to use it. - -#### Learn More - - - [CWE-918: Server-Side Request Forgery (SSRF)](https://cwe.mitre.org/data/definitions/918.html) - -## Non-Compliant Code Examples -```python -import flask -from urllib.request import urlopen - -app = flask.Flask(__name__) - - - -@app.route("/route/to/resource/") -def resource2(resource_id): - file1 = urlopen(resource_id) - file2 = urlopen(f"/path/to/{resource_id}") - - -@app.route("/route/to/resource") -def resource2(): - resource_id = flask.request.args.get("resource_id") - file1 = urlopen(resource_id) - file2 = urlopen(f"/path/to/{resource_id}") - file3 = urlopen("/path/to/{0}".format(resource_id)) -``` - -## Compliant Code Examples -```python -import flask -from urllib.request import urlopen - -app = flask.Flask(__name__) - -@app.route("/route/to/resource/") -def resource2(resource_id): - sanitized_resource_id = sanitize(resource_id) - file1 = urlopen(sanitized_resource_id) -``` diff --git a/content/en/static_analysis/rules/python-flask/use-jsonify.md b/content/en/static_analysis/rules/python-flask/use-jsonify.md deleted file mode 100644 index b75795d8fa853..0000000000000 --- a/content/en/static_analysis/rules/python-flask/use-jsonify.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-flask/use-jsonify - language: Python - severity: Notice -title: use jsonify instead of json.dumps for JSON output ---- -## Metadata -**ID:** `python-flask/use-jsonify` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -With the flask framework, `jsonify` helps you write API endpoints that return JSON data. - -#### Learn More - - - [Python Flask: `jsonify()`](https://flask.palletsprojects.com/en/2.3.x/api/#flask.json.jsonify) - - - -## Non-Compliant Code Examples -```python -@app.route("/article") -def get_article(): - article = get_article_by_id(request.args.get("id")) - return json.dumps(article) # use flask.jsonify instead of json.dumps -``` - -## Compliant Code Examples -```python -from flask import jsonify - -@app.route("/article") -def get_article(): - article = get_article_by_id(request.args.get("id")) - return jsonify(article) -``` diff --git a/content/en/static_analysis/rules/python-inclusive/comments.md b/content/en/static_analysis/rules/python-inclusive/comments.md deleted file mode 100644 index de460dac2a0c1..0000000000000 --- a/content/en/static_analysis/rules/python-inclusive/comments.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-inclusive/comments - language: Python - severity: Notice -title: check comments for wording issues ---- -## Metadata -**ID:** `python-inclusive/comments` - -**Language:** Python - -**Severity:** Notice - -**Category:** Code Style - -## Description -Check the variable names and suggest better names. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```python -# whitelist names to prevent unauthorized usage -def filter_names(names): - pass - -# she SHE should check her code -def new_function_from_helen(): - pass - - -class Foo: - # he should check his - def new_function_from_joe(): - pass -``` - -## Compliant Code Examples -```python -# allowlist names to prevent unauthorized usage -def filter_names(names): - pass - -# the comments do not have an history of issues -def foo(bar): - baz() -``` diff --git a/content/en/static_analysis/rules/python-inclusive/function-definition.md b/content/en/static_analysis/rules/python-inclusive/function-definition.md deleted file mode 100644 index 234b33c04f011..0000000000000 --- a/content/en/static_analysis/rules/python-inclusive/function-definition.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-inclusive/function-definition - language: Python - severity: Notice -title: check function names for wording issues ---- -## Metadata -**ID:** `python-inclusive/function-definition` - -**Language:** Python - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that some words are not used in the codebase and suggest replacement when appropriate. - -Examples of replacement suggestions: - - `blacklist` with `denylist` - - `whitelist` with `allowlist` - - `master` with `primary` - - `slave` with `secondary` - -## Non-Compliant Code Examples -```python -# blacklist located at the end of the string -def foo_blacklist(): - pass -``` - -```python -# Do not use the name blacklist, even if casing is mixed -def BlaCKliSt_NaMeS(): - pass - -def wHiTeLisT_NaMeS(): - pass -``` - -```python -# blacklist at the beginning of the function name -def blacklist_names(): - pass -``` - -```python -# wrong identifier in the function name and parameters -def blacklist_names(master, slave): - pass -``` - -## Compliant Code Examples -```python -def foo_denylist(): - pass -``` diff --git a/content/en/static_analysis/rules/python-inclusive/variable-name.md b/content/en/static_analysis/rules/python-inclusive/variable-name.md deleted file mode 100644 index 5613f82619bb1..0000000000000 --- a/content/en/static_analysis/rules/python-inclusive/variable-name.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: python-inclusive/variable-name - language: Python - severity: Notice -title: check variable names for wording issues ---- -## Metadata -**ID:** `python-inclusive/variable-name` - -**Language:** Python - -**Severity:** Notice - -**Category:** Code Style - -## Description -Check the variable names and suggest better names. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```python -# banned name, will suggest allowlist -whitelist = "foo" -names_whitelist = "bla"; - -names_blacklist = "bla"; - -addr_master_ip = "5.4.3.8"; -addr_slave_ip = "1.2.3.4"; -``` - -## Compliant Code Examples -```python -# not a problem with the name -snow_white = "happy" -``` diff --git a/content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md b/content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md deleted file mode 100644 index 78e409c914ac7..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/arith-operator-not-functions.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/arith-operator-not-functions - language: Python - severity: Notice -title: Use arithmetic operator instead of a function ---- -## Metadata -**ID:** `python-pandas/arith-operator-not-functions` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -User should use arithmetic operators (`+`, `-`, etc) instead of function (`.add`) to make the code more clear. - -## Non-Compliant Code Examples -```python -def myfunction(): - foo = pd.DataFrame({'angles': [0, 3, 4], - 'degrees': [360, 180, 360]}, - index=['circle', 'triangle', 'rectangle']) - if something: - baz = foo.add(1) - elif other_thing: - baz = foo.add(42) - else: - baz = foo.add(51) - - bar = whatever() - baz = bar.add(4) -``` - -```python -def myfunction(): - foo = pd.DataFrame({'angles': [0, 3, 4], - 'degrees': [360, 180, 360]}, - index=['circle', 'triangle', 'rectangle']) - baz = foo.add(1) - - bar = whatever() - baz = bar.add(4) -``` - -## Compliant Code Examples -```python -foo = pd.DataFrame({'angles': [0, 3, 4], - 'degrees': [360, 180, 360]}, - index=['circle', 'triangle', 'rectangle']) -baz = foo + 1 - - -``` diff --git a/content/en/static_analysis/rules/python-pandas/avoid-inplace.md b/content/en/static_analysis/rules/python-pandas/avoid-inplace.md deleted file mode 100644 index 4bbb2767900d3..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/avoid-inplace.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/avoid-inplace - language: Python - severity: Warning -title: Avoid using inplace=True ---- -## Metadata -**ID:** `python-pandas/avoid-inplace` - -**Language:** Python - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Avoid using `inplace=True` as it does not have clear performance impact and is potentially dangerous and does not behave as it should. - -#### Learn More - - - [Why You Should Probably Never Use pandas inplace=True](https://towardsdatascience.com/why-you-should-probably-never-use-pandas-inplace-true-9f9f211849e4?gi=ae387a166946) - -## Non-Compliant Code Examples -```python -df.drop(['a'], axis=1, inplace=True) -``` - -## Compliant Code Examples -```python -df.drop(['a'], axis=1, inplace=False) -``` diff --git a/content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md b/content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md deleted file mode 100644 index 4f43fbce8055e..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/comp-operator-not-function.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/comp-operator-not-function - language: Python - severity: None -title: Use operators to compare values, not functions ---- -## Metadata -**ID:** `python-pandas/comp-operator-not-function` - -**Language:** Python - -**Severity:** None - -**Category:** Best Practices - -## Description -User should use comparison operators (`<`, `>`, etc) instead of function (`.ld`) to make the code more clear. - -## Non-Compliant Code Examples -```python -foo.le(bar) -``` - -## Compliant Code Examples -```python -foo < bar -``` diff --git a/content/en/static_analysis/rules/python-pandas/import-as-pd.md b/content/en/static_analysis/rules/python-pandas/import-as-pd.md deleted file mode 100644 index 329ad28394951..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/import-as-pd.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/import-as-pd - language: Python - severity: Notice -title: Import pandas according to coding guidelines ---- -## Metadata -**ID:** `python-pandas/import-as-pd` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -The `pandas` library is generally imported using the following code snippet. - -```python -import pandas as pd -``` - -It is good practice to ensure that all pandas import are done this way. This rule ensures that all code uses this pattern. - -## Non-Compliant Code Examples -```python -import pandas # should use import pandas as pd - - -import pandas as foo - - -import foo as bar -``` - -```python -from pandas import something # should use import pandas as pd - -``` - -```python -import pandas as something # should use import pandas as pd -``` - -## Compliant Code Examples -```python -import pandas as pd # should use import pandas as pd -``` diff --git a/content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md b/content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md deleted file mode 100644 index 5cbb1416b3a67..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/isna-instead-of-isnull.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/isna-instead-of-isnull - language: Python - severity: Notice -title: Use isna instead of isnull ---- -## Metadata -**ID:** `python-pandas/isna-instead-of-isnull` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -The functions `isna` and `isnull` are similar. However, this is a best practice to use `isna` since other methods use the same naming patterns. - -#### Learn More - - - [Pandas isna() and isnull(), what is the difference?](https://stackoverflow.com/questions/52086574/pandas-isna-and-isnull-what-is-the-difference) - -## Non-Compliant Code Examples -```python -nulls = pd.isnull(val) # prefer using isna -``` - -## Compliant Code Examples -```python -nas = pd.isna(val) -``` diff --git a/content/en/static_analysis/rules/python-pandas/loc-not-ix.md b/content/en/static_analysis/rules/python-pandas/loc-not-ix.md deleted file mode 100644 index a8e0a6489fa19..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/loc-not-ix.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/loc-not-ix - language: Python - severity: None -title: prefer iloc or loc rather than ix ---- -## Metadata -**ID:** `python-pandas/loc-not-ix` - -**Language:** Python - -**Severity:** None - -**Category:** Best Practices - -## Description -The functions `notna` and `notnull` are similar. However, this is a best practice to use `notna` since other methods use the same naming patterns. - -## Non-Compliant Code Examples -```python -index = df.iat[:, 1:3] -``` - -```python -index = df.at[:, ['B', 'A']] -``` - -```python -s = df.ix[[0, 2], 'A'] -``` - -## Compliant Code Examples -```python -new_df = df.iloc[] -``` diff --git a/content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md b/content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md deleted file mode 100644 index 6f5960e7fe3e1..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/notna-instead-of-notnull.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/notna-instead-of-notnull - language: Python - severity: None -title: prefer notna to notnull ---- -## Metadata -**ID:** `python-pandas/notna-instead-of-notnull` - -**Language:** Python - -**Severity:** None - -**Category:** Best Practices - -## Description -The functions `notna` and `notnull` are similar. However, this is a best practice to use `notna` since other methods use the same naming patterns. - -## Non-Compliant Code Examples -```python -notnulls = pd.notnull(val) -``` - -## Compliant Code Examples -```python -notnas = pd.notna(val) -``` diff --git a/content/en/static_analysis/rules/python-pandas/pivot-table.md b/content/en/static_analysis/rules/python-pandas/pivot-table.md deleted file mode 100644 index e65a95261ce10..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/pivot-table.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/pivot-table - language: Python - severity: Notice -title: Use pivot_table instead of pivot or unstack ---- -## Metadata -**ID:** `python-pandas/pivot-table` - -**Language:** Python - -**Severity:** Notice - -**Category:** Best Practices - -## Description -The functions `isna` and `isnull` are similar. However, this is a best practice to use `isna` since other methods use the same naming patterns. - -#### Learn More - - - [Pandas isna() and isnull(), what is the difference?](https://stackoverflow.com/questions/52086574/pandas-isna-and-isnull-what-is-the-difference) - -## Non-Compliant Code Examples -```python -table = df.unstack(level=0) -``` - -```python -table = pd.pivot( - df, - index='foo', - columns='bar', - values='baz' - ) -``` - -## Compliant Code Examples -```python -table = df.pivot_table( - df, - values='D', - index=['A', 'B'], - columns=['C'], - aggfunc=np.sum, - fill_value=0 -``` diff --git a/content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md b/content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md deleted file mode 100644 index dd1cc1fc41339..0000000000000 --- a/content/en/static_analysis/rules/python-pandas/use-read-csv-not-read-table.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-pandas/use-read-csv-not-read-table - language: Python - severity: None -title: prefer read_csv to read_table ---- -## Metadata -**ID:** `python-pandas/use-read-csv-not-read-table` - -**Language:** Python - -**Severity:** None - -**Category:** Best Practices - -## Description -The functions `notna` and `notnull` are similar. However, this is a best practice to use `notna` since other methods use the same naming patterns. - -## Non-Compliant Code Examples -```python -employees = pd.read_table(input_file) -``` - -## Compliant Code Examples -```python -employees = pd.read_csv(input_file) -``` diff --git a/content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md b/content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md deleted file mode 100644 index 0e65974da4e9e..0000000000000 --- a/content/en/static_analysis/rules/python-security/asyncio-subprocess-create-shell.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/asyncio-subprocess-create-shell - language: Python - severity: Error -title: Unsafe execution of shell commands ---- -## Metadata -**ID:** `python-security/asyncio-subprocess-create-shell` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Detect unsafe shell execution in the asyncio framework. When we invoke the shell, we should make sure that the data is safe and secure. Use `shlex` to sanitize user inputs. - -#### Learn More - - - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) - - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) - -## Non-Compliant Code Examples -```python -import asyncio - -def handler(event, context): - # Should sanitize arguments - async_loop.run_until_complete(async_loop.create_subprocess_shell("mycommand")) - -``` - -## Compliant Code Examples -```python -import asyncio -import shlex - -def handler(event, context): - # Should sanitize arguments - async_loop.run_until_complete(async_loop.create_subprocess_shell(shlex.escape("mycommand"))) -``` diff --git a/content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md b/content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md deleted file mode 100644 index 82825c0402220..0000000000000 --- a/content/en/static_analysis/rules/python-security/asyncio-subprocess-exec.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/asyncio-subprocess-exec - language: Python - severity: Error -title: Unsafe execution of shell commands ---- -## Metadata -**ID:** `python-security/asyncio-subprocess-exec` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Detect unsafe shell execution in the asyncio framework. When we invoke the shell, we should make sure that the data is safe and secure. Use `shlex` to sanitize user inputs. - -#### Learn More - - - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) - - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) - -## Non-Compliant Code Examples -```python -import asyncio - -def handler(event, context): - # Should sanitize arguments - async_loop.run_until_complete(async_loop.subprocess_exec(waiting_protocol, ["/bin/sh", "mycommand"])) -``` - -## Compliant Code Examples -```python -import asyncio -import shlex - -def handler(event, context): - # Should sanitize arguments - async_loop.run_until_complete(async_loop.subprocess_exec(waiting_protocol, shlex.split(shlex.quote("/bin/sh mycommand")))) -``` diff --git a/content/en/static_analysis/rules/python-security/avoid-random.md b/content/en/static_analysis/rules/python-security/avoid-random.md deleted file mode 100644 index 52b67fbc5100f..0000000000000 --- a/content/en/static_analysis/rules/python-security/avoid-random.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/avoid-random - language: Python - severity: Error -title: use secrets package over random package ---- -## Metadata -**ID:** `python-security/avoid-random` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Make sure to use values that are *actually* random. The `random` module in Python should generally not be used and replaced with the `secrets` module, as noted in the [official Python documentation](https://docs.python.org/3/library/random.html). - -#### Learn More - - - [CWE-330](https://cwe.mitre.org/data/definitions/330.html) - - [Python random module documentation](https://docs.python.org/3/library/random.html) - - [Python secrets module documentation](https://docs.python.org/3/library/secrets.html#module-secrets) - -## Non-Compliant Code Examples -```python -from random import randrange - -randrange(10) # # randrange is not actually random -``` - -```python -from random import random - -v = random() # random is not actually random -``` - -```python -import random - -n = random.randrange(10) # randrange is not actually random -``` - -```python -import random - -n = random.random(1) # randrange is not actually random -``` - -```python -import random - -n = random.random() # randrange is not actually random -``` - -## Compliant Code Examples -```python -n = random.random() -``` diff --git a/content/en/static_analysis/rules/python-security/aws-boto-credentials.md b/content/en/static_analysis/rules/python-security/aws-boto-credentials.md deleted file mode 100644 index 5fb60e28cbd9c..0000000000000 --- a/content/en/static_analysis/rules/python-security/aws-boto-credentials.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/aws-boto-credentials - language: Python - severity: Notice -title: use env vars over hardcoded values ---- -## Metadata -**ID:** `python-security/aws-boto-credentials` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -This rule makes sure that the `boto3` library use the environments variables to authenticate instead of using hardcoded credentials. This rule checks for the `boto3.client` and `boto3.Session` calls. It addresses the [CWE-798 rule](https://cwe.mitre.org/data/definitions/798.html) - uses of hardcoded credentials in code. - -#### Learn More - - - [AWS credentials](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials) - - [CWE-798: Use of Hard-coded Credentials](https://cwe.mitre.org/data/definitions/798.html) - -## Non-Compliant Code Examples -```python -from boto3 import client - -cli = client( - 's3', - aws_access_key_id="AGPAFOOBAR", - aws_secret_access_key="bar", - aws_session_token=SESSION_TOKEN -) -``` - -```python -import boto3 - -client = boto3.client( - 's3', - aws_access_key_id="AGPAFOOBAR", - aws_secret_access_key="bar", - aws_session_token=SESSION_TOKEN -) -``` - -```python -import boto3 - -client = boto3.Session( - 's3', - aws_access_key_id=ACCESS_KEY, - aws_secret_access_key=SECRET_KEY, - aws_session_token="foobar" # hard coded credential -) -``` - -## Compliant Code Examples -```python -import boto3 - -client = boto3.Session( - 's3', - aws_session_token=SESSION_TOKEN -) -``` - -```python -import boto3 - -client = boto3.client( - 's3', - aws_session_token=SESSION_TOKEN -) -``` - -```python -client = boto3.client( - 's3', - aws_access_key_id=ACCESS_KEY, - aws_secret_access_key=SECRET_KEY, - aws_session_token=SESSION_TOKEN -) -``` diff --git a/content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md b/content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md deleted file mode 100644 index c449210c2505e..0000000000000 --- a/content/en/static_analysis/rules/python-security/deserialize-untrusted-data.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/deserialize-untrusted-data - language: Python - severity: Notice -title: avoid unsafe function to (de)serialize data ---- -## Metadata -**ID:** `python-security/deserialize-untrusted-data` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -Do not deserialize untrusted data. Make sure you use alternatives to check that the data can be deserialized safely. There is no workaround around this: unless you **really** trust the data source, it's better to use another way to exchange data, such as an API or other protocols such as [protobuf](https://developers.google.com/protocol-buffers) or [thrift](https://thrift.apache.org/). - -**Read More** - - - [Unsafe Deserialization in Python (CWE-502)](https://www.codiga.io/blog/python-unsafe-deserialization/) - - - [CWE-502: Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html) - -## Non-Compliant Code Examples -```python -import marshal -person = {"name":"xyz", "age":22, "marks":[45,56,78]} -data = marshal.dumps(person) -obj = marshal.loads(data) -``` - -```python -import pickle - -data = pickle.loads(data) -``` - -## Compliant Code Examples -```python -import pickle - -data = pickle.loads(data) - -``` - -```python -data = pickle.loads(data) -``` diff --git a/content/en/static_analysis/rules/python-security/file-write-others.md b/content/en/static_analysis/rules/python-security/file-write-others.md deleted file mode 100644 index 3feb11440a57e..0000000000000 --- a/content/en/static_analysis/rules/python-security/file-write-others.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/file-write-others - language: Python - severity: Warning -title: do not let all users write permissions ---- -## Metadata -**ID:** `python-security/file-write-others` - -**Language:** Python - -**Severity:** Warning - -**Category:** Security - -## Description -Make sure that programs do not let write permissions for all users. When using `os.chmod`, the user should never use `S_IWOTH` that gives the permission to all users to write the file on the filesystem. - -Instead, this permission should be removed, and proper control access should be configured. - -See the following related CWE: - - [CWE-275](https://cwe.mitre.org/data/definitions/275.html) category - Permission Issues - - [CWE-280](https://cwe.mitre.org/data/definitions/280.html) - Improper Handling of Insufficient Permissions or Privileges - -## Non-Compliant Code Examples -```python -import stat - -path = "/path/to/file" -os.chmod(path, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH) -``` - -## Compliant Code Examples -```python -import stat - -path = "/path/to/file" -os.chmod(path, stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH) # skipping because it's in a test file -``` - -```python -import stat - -path = "/path/to/file" -os.chmod(path, stat.S_IROTH | stat.S_IXOTH) # no write by others -``` diff --git a/content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md b/content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md deleted file mode 100644 index b0b2347eec75a..0000000000000 --- a/content/en/static_analysis/rules/python-security/hardcoded-tmp-file.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: python-security/hardcoded-tmp-file - language: Python - severity: None -title: Do not hardcode temp file or directory ---- -## Metadata -**ID:** `python-security/hardcoded-tmp-file` - -**Language:** Python - -**Severity:** None - -**Category:** Best Practices - -## Description -Do not hardcode the name or directory of temporary files. Use the `tempfile` Python instead of hardcoding values. - - -#### Learn More - - - [CWE-377 - Insecure Temporary File](https://cwe.mitre.org/data/definitions/377.html) - - [Create, use and remove. temporary files securely](https://security.openstack.org/guidelines/dg_using-temporary-files-securely.html) - - [`tempfile` module](https://docs.python.org/3/library/tempfile.html) - -## Non-Compliant Code Examples -```python -with open("/tmp/acme.pub", "rb") as key_file: - public_key = serialization.load_pem_public_key( - key_file.read(), - backend=default_backend() - ) - -def foobar(): - api_key_file = Path('/tmp/supersecret.txt') - -keyfile = '/tmp/vulpy.apikey.{}.{}'.format(username, key) -keyfile = f"/tmp/vulpy.apikey.{username}.{key}" -def authenticate(request): - if 'X-APIKEY' not in request.headers: - return None - - key = request.headers['X-APIKEY'] - - for f in Path('/tmp/').glob('vulpy.apikey.*.' + key): - return f.name.split('.')[2] - - return None -``` - -## Compliant Code Examples -```python -secure_temp = tempfile.mkstemp(prefix="pre_",suffix="_suf") -print(secure_temp) - -temp = tempfile.NamedTemporaryFile() -print(temp) -print(temp.name) -``` diff --git a/content/en/static_analysis/rules/python-security/html-string-from-parameters.md b/content/en/static_analysis/rules/python-security/html-string-from-parameters.md deleted file mode 100644 index 26b74ebb4801b..0000000000000 --- a/content/en/static_analysis/rules/python-security/html-string-from-parameters.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/html-string-from-parameters - language: Python - severity: Error -title: Avoid HTML built in strings ---- -## Metadata -**ID:** `python-security/html-string-from-parameters` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Detect unsafe HTML content. User-input may be injected into HTML content without being sanitized. - -User input should always be checked before being used in HTML data. - -#### Learn More - -- [CWE-79: Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) - -## Non-Compliant Code Examples -```python -def my_function(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): - html1 = f"
{arg1}
" - html1 = "
{0}
".format(arg1) - html2 = f"
{arg2['bli']}
" - html2 = "
{0}
".format(arg2['bli']) - html3 = "
" + arg1 + "
" - render(f"
{arg1}
") - return html - - -def my_function2(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): - html1 = f"
{arg51}
" - html1 = "
{0}
".format(arg42) - html2 = f"
{arg26['bli']}
" - html2 = "
{0}
".format(arg51['bli']) - html3 = "
" + arg41 + "
" - render(f"
{arg51}
") - return html - - -def my_function3(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): - html1 = f"
{arg1}
" - html1 = "
{0}
".format(arg1) - html2 = f"
{arg2['bli']}
" - html2 = "
{0}
".format(arg2['bli']) - html3 = "
" + arg1 + "
" - render(f"
{arg1}
") - return html -``` - -## Compliant Code Examples -```python -def my_function(arg1: str, arg2, arg3 = "blabla", arg4: str = "blibli"): - html1 = f"
{sanitize_value(arg1)}
" - html1 = "
{0}
".format(sanitize_value(arg1)) - html2 = f"
{sanitize_value(arg2['bli'])}
" - html2 = "
{0}
".format(sanitize_value(arg2['bli'])) - html3 = "
" + sanitize_value(arg1) + "
" - render(f"
{sanitize_value(arg1)}
") - return html - - - - -``` diff --git a/content/en/static_analysis/rules/python-security/insecure-hash-functions.md b/content/en/static_analysis/rules/python-security/insecure-hash-functions.md deleted file mode 100644 index 2c5dce020d899..0000000000000 --- a/content/en/static_analysis/rules/python-security/insecure-hash-functions.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/insecure-hash-functions - language: Python - severity: Warning -title: Do not use insecure functions ---- -## Metadata -**ID:** `python-security/insecure-hash-functions` - -**Language:** Python - -**Severity:** Warning - -**Category:** Security - -## Description -Do not use a broken or risky cryptographic algorithm. This exposes you to unwanted attacks. - -It checks the following modules - - [hashlib](https://docs.python.org/3/library/hashlib.html) - - [cryptography](https://cryptography.io/) - -#### Learn More - - - [CWE-327](https://cwe.mitre.org/data/definitions/327.html) - Use of a Broken or Risky Cryptographic Algorithm - - [CWE-328](https://cwe.mitre.org/data/definitions/328.html) - Use of Weak Hash - -## Non-Compliant Code Examples -```python -from cryptography.hazmat.primitives import hashes -digest = hashes.Hash(hashes.MD5()) -``` - -```python -from cryptography.hazmat.primitives import hashes -digest = hashes.Hash(hashes.MD5()) -``` - -```python -import hashlib - -hashlib.new('md5') -hashlib.new('md4') - - -hashlib.md5("bla"); -``` diff --git a/content/en/static_analysis/rules/python-security/insecure-jwt.md b/content/en/static_analysis/rules/python-security/insecure-jwt.md deleted file mode 100644 index 0acb67adc9fd5..0000000000000 --- a/content/en/static_analysis/rules/python-security/insecure-jwt.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/insecure-jwt - language: Python - severity: Notice -title: Ensure JWT signatures are verified ---- -## Metadata -**ID:** `python-security/insecure-jwt` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -Use `"verify_signature": False` when decoding a JWT bypasses security and may authenticate users that should not be authenticated. - -**See Also** - - - [CWE-287 - Improper Authentication](https://cwe.mitre.org/data/definitions/287.html) - -## Non-Compliant Code Examples -```python -import jwt - -jwt.decode(encoded, options={"verify_signature": False}) -``` - -## Compliant Code Examples -```python -import jwt - -jwt.decode(encoded, bla={"verify_signature": False}) - -jwt.decode(encoded, options={"foobar": False}) - -``` - -```python -import jwt - -jwt.decode(encoded, options={"verify_signature": True}) -``` - -```python -jwt.decode(encoded, options={"verify_signature": True}) -``` diff --git a/content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md b/content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md deleted file mode 100644 index 5b656bf26967a..0000000000000 --- a/content/en/static_analysis/rules/python-security/insecure-ssl-protocols.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/insecure-ssl-protocols - language: Python - severity: Notice -title: Do not use insecure encryption protocols ---- -## Metadata -**ID:** `python-security/insecure-ssl-protocols` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -The following security protocols should never be used in Python: `SSLv3`, `SSLv2`, `TLSv1`. For more details, read the [SSL module page](https://docs.python.org/3/library/ssl.html) of the official documentation. - -The issue addresses the [CWE-757](https://cwe.mitre.org/data/definitions/757.html) - selection of less-secure algorithm during negotiation. - - - -## Non-Compliant Code Examples -```python -import ssl - -def newconnect(self): - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - remote = ssl.wrap_socket(s, - ca_certs= CA, - cert_reqs=ssl.CERT_REQUIRED, - ssl_version = ssl.PROTOCOL_SSLv3) - remote.connect(self.server.seradd) - if not self.server.seradd[0] == remote.getpeercert()['subjectAltName'][0][1]: - logging.error('Server crt error !! Server Name don\'t mach !!') - logging.error(remote.getpeercert()['subjectAltName'][0][1]) - return - if not self.send_PW(remote): - logging.warn('PW error !') - return - except socket.error, e: - logging.warn(e) - return -``` - -## Compliant Code Examples -```python -import ssl - -def newconnect(self): - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - remote = ssl.wrap_socket(s, - ca_certs= CA, - cert_reqs=ssl.CERT_REQUIRED, - ssl_version = ssl.PROTOCOL_TLS) - remote.connect(self.server.seradd) - if not self.server.seradd[0] == remote.getpeercert()['subjectAltName'][0][1]: - logging.error('Server crt error !! Server Name don\'t mach !!') - logging.error(remote.getpeercert()['subjectAltName'][0][1]) - return - if not self.send_PW(remote): - logging.warn('PW error !') - return - except socket.error, e: - logging.warn(e) - return -``` diff --git a/content/en/static_analysis/rules/python-security/jinja-autoescape.md b/content/en/static_analysis/rules/python-security/jinja-autoescape.md deleted file mode 100644 index eeba30b9e66ad..0000000000000 --- a/content/en/static_analysis/rules/python-security/jinja-autoescape.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/jinja-autoescape - language: Python - severity: Notice -title: Auto escape should be set to true ---- -## Metadata -**ID:** `python-security/jinja-autoescape` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -By default, jinja2 is not autoescaping. This can lead to XSS attacks. The `autoescape` parameter should always be `True`. - - -#### Learn More - - - [OWASP XSS](https://owasp.org/www-community/attacks/xss/) - - [CWE-94 - Improper Control of Generation of Code](https://cwe.mitre.org/data/definitions/94.html) - -## Non-Compliant Code Examples -```python -import jinja2 -env = jinja2.Environment( - loader=PackageLoader("yourapp"), - autoescape=False # should be True -) -``` - -```python -from jinja2 import Environment, PackageLoader, select_autoescape -env = Environment( - loader=PackageLoader("yourapp"), - autoescape=False # should be True -) -``` - -## Compliant Code Examples -```python -import jinja2 -env = Environment( - loader=PackageLoader("yourapp"), - autoescape=True -) -``` - -```python -from jinja2 import Environment, PackageLoader, select_autoescape -env = Environment( - loader=PackageLoader("yourapp"), - autoescape=select_autoescape() -) -``` - -```python -from jinja2 import Environment, PackageLoader, select_autoescape -env = Environment( - loader=PackageLoader("yourapp"), - autoescape=True -) -``` diff --git a/content/en/static_analysis/rules/python-security/mktemp.md b/content/en/static_analysis/rules/python-security/mktemp.md deleted file mode 100644 index e4190cdfa3a40..0000000000000 --- a/content/en/static_analysis/rules/python-security/mktemp.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/mktemp - language: Python - severity: Notice -title: Make sure temporary files are secure ---- -## Metadata -**ID:** `python-security/mktemp` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -Using insecure temporary files makes your program vulnerable to attacks. The official [Python documentation](https://docs.python.org/3/library/tempfile.html) reports this module being vulnerable to attacks. Instead of `mktemp`, use the secure version `mkstemp()`. - - -#### Learn More - - - [CWE-377 - Insecure Temporary File](https://cwe.mitre.org/data/definitions/377.html) - - [Python documentation for mktemp()](https://docs.python.org/3/library/tempfile.html) - -## Non-Compliant Code Examples -```python -from tempfile import mktemp -mktemp(dir=self._tmp_dir) -``` - -```python -import tempfile -tempfile.mktemp(dir=self._tmp_dir) -``` - -## Compliant Code Examples -```python -tempfile.mktemp(dir=self._tmp_dir) -``` - -```python -import tempfile -tempfile.mkstemp(dir=self._tmp_dir) -``` diff --git a/content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md b/content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md deleted file mode 100644 index 99802e754e476..0000000000000 --- a/content/en/static_analysis/rules/python-security/no-empty-array-as-parameter.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/no-empty-array-as-parameter - language: Python - severity: Warning -title: Do not use empty array as default parameter ---- -## Metadata -**ID:** `python-security/no-empty-array-as-parameter` - -**Language:** Python - -**Severity:** Warning - -**Category:** Security - -## Description -We should never pass an empty array parameter to a function. Instead, use `None` and check the value if defined. This can cause unwanted behavior as the value of the argument is only evaluated once. - -**Read more** - - - [Avoid using empty list as default argument](https://nikos7am.com/posts/mutable-default-arguments/) - -## Non-Compliant Code Examples -```python -def newFunction(arg1, arg2: int, arg3 = [], arg4: MyType = []): # do not use empty array/list as default parameter - print("bla") -``` - -## Compliant Code Examples -```python -def newFunction(arg1, arg2: int, arg3 = None): # do not use empty array/list as default parameter - print("bla") -``` diff --git a/content/en/static_analysis/rules/python-security/no-eval.md b/content/en/static_analysis/rules/python-security/no-eval.md deleted file mode 100644 index b8426e74b128c..0000000000000 --- a/content/en/static_analysis/rules/python-security/no-eval.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/no-eval - language: Python - severity: Notice -title: use of eval can be insecure ---- -## Metadata -**ID:** `python-security/no-eval` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -`eval()` is insecure, and uncontrolled data could then create a vulnerability, as reported by the [official Python documentation](https://docs.python.org/3/library/functions.html#eval). Generated code should be controlled as mentioned by [CWE-94](https://cwe.mitre.org/data/definitions/94.html). - -#### Learn More - - - [CWE-94](https://cwe.mitre.org/data/definitions/94.html) - Improper Control of Generation of Code - - [Safe and Secure Python: do not use eval()](https://www.codiga.io/blog/python-eval/) - -## Non-Compliant Code Examples -```python -print("bla") -eval('[1, 2, 3]') # eval() can be unsafe -``` - -## Compliant Code Examples -```python -import foo -foo.eval('[1, 2, 3]') -``` - -```python -from ast import literal_eval -print("bla") -literal_eval('[1, 2, 3]') -``` diff --git a/content/en/static_analysis/rules/python-security/os-spawn.md b/content/en/static_analysis/rules/python-security/os-spawn.md deleted file mode 100644 index 03a7c7777d515..0000000000000 --- a/content/en/static_analysis/rules/python-security/os-spawn.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/os-spawn - language: Python - severity: Error -title: Call of a spawn process without sanitization ---- -## Metadata -**ID:** `python-security/os-spawn` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Detect unsafe shell execution with the `os` module. We should ensure the command is safe before execution. Use `shlex` to sanitize user inputs. - -#### Learn More - - - [Python `os.spawn*()` documentation](https://docs.python.org/3/library/os.html#os.spawnl) - - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) - - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) - -## Non-Compliant Code Examples -```python -import os - -directory = "/tmp" - -# Use of unsanitized data to create a process -os.spawnl(os.P_WAIT, "/bin/ls") -os.spawnle(os.P_WAIT, "/bin/ls") -os.spawnlp(os.P_WAIT, "/bin/ls") -os.spawnlpe(os.P_WAIT, "/bin/ls") -os.spawnv(os.P_WAIT, "/bin/ls") -os.spawnve(os.P_WAIT, "/bin/ls") -os.spawnvp(os.P_WAIT, "/bin/ls") -os.spawnvpe(os.P_WAIT, "/bin/ls") - - -os.spawnvpe(os.P_WAIT, "/bin/ls " + directory) -``` - -## Compliant Code Examples -```python -import os -import shlex - -# Use of shlex() to sanitize data -os.spawnl(os.P_WAIT, shlex.escape("/bin/ls")) -``` diff --git a/content/en/static_analysis/rules/python-security/os-system.md b/content/en/static_analysis/rules/python-security/os-system.md deleted file mode 100644 index c64831bd4f0e0..0000000000000 --- a/content/en/static_analysis/rules/python-security/os-system.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/os-system - language: Python - severity: Error -title: Command execution without sanitization ---- -## Metadata -**ID:** `python-security/os-system` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Detect unsafe shell execution with the `os` module. We should ensure the command is safe before execution. Use `shlex` to sanitize user inputs. - -#### Learn More - - - [Python `os.system()` documentation](https://docs.python.org/3/library/os.html#os.system) - - [`Python shlex() module`](https://docs.python.org/3/library/shlex.html) - - [CWE 78 - Improper Neutralization of Special Elements used in an OS Command](https://cwe.mitre.org/data/definitions/78.html) - -## Non-Compliant Code Examples -```python -os.system(f'mv {saved_file_path} {public_upload_file_path}') -``` - -```python -command = f'convert "{temp_upload_file_path}" -resize 50% "{resized_image_path}"' -os.system(command) - - -command2 = f'convert "{temp_upload_file_path}" -resize 50% "{resized_image_path}"' -os.system(command4) -``` - -```python -import os - -directory = "/tmp" - -# Use of unsanitized data to execute a process -os.system("/bin/ls") -os.system("/bin/ls " + directory) - - -os.system(f'mv {saved_file_path} {public_upload_file_path}') - - -def file_upload_api(request, app): - file = request.files['file'] - - if not _validate_file(file.filename): - return { - 'message': 'Invalid file extension', - 'allowed_ext': ALLOWED_EXTENSIONS, - 'filename': file.filename - }, 422 - - saved_file_result = _save_temp_file(file, app) - saved_file_path = saved_file_result['saved_path'] - - file_name = Path(saved_file_path).name - - public_upload_file_path = os.path.join(app.config['PUBLIC_UPLOAD_FOLDER'], file_name) - - os.system(f'mv {saved_file_path} {public_upload_file_path}') - - return render_template('file_upload.html', file_url=f'{get_uploads_folder_url()}/{file_name}') -``` - -## Compliant Code Examples -```python -import os -import shlex - -# Use of shlex() to sanitize data -os.system(shlex.escape("/bin/ls")) - - -``` diff --git a/content/en/static_analysis/rules/python-security/request-verify.md b/content/en/static_analysis/rules/python-security/request-verify.md deleted file mode 100644 index acb1dddf7833d..0000000000000 --- a/content/en/static_analysis/rules/python-security/request-verify.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/request-verify - language: Python - severity: Error -title: verify should be True ---- -## Metadata -**ID:** `python-security/request-verify` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -The `verify` parameter controls whether the SSL certificate should be verified during your server requests. It's strongly recommended to set this parameter to `True` which is the default value. This rule will warn you when it's detected `False` has been set. - -## Non-Compliant Code Examples -```python -from requests import get -r = get(w, verify=False) # verify should be True -r = get(w, verify=False, timeout=10) # verify should be True -``` - -## Compliant Code Examples -```python -from requests import get -r = get(w) -r = get(w, timeout=10, verify=True) -``` - -```python -from requests import get -r = get(w) -r = get(w, timeout=10) -``` diff --git a/content/en/static_analysis/rules/python-security/requests-http.md b/content/en/static_analysis/rules/python-security/requests-http.md deleted file mode 100644 index 5211822365364..0000000000000 --- a/content/en/static_analysis/rules/python-security/requests-http.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/requests-http - language: Python - severity: Warning -title: Do not make http calls without encryption ---- -## Metadata -**ID:** `python-security/requests-http` - -**Language:** Python - -**Severity:** Warning - -**Category:** Security - -## Description -Making a request with http enables attackers to listen to the traffic and obtain sensitive information. Use `https://` instead. - -#### Learn More - - - [CWE-319: Cleartext Transmission of Sensitive Information](https://cwe.mitre.org/data/definitions/319.html) - -## Non-Compliant Code Examples -```python -def test1(): - url1 = "http://api.tld" - requests.get(url1) - - -def test2(): - url2 = "http://api.tld/user/{0}".format(user_id) - requests.get(url2) - -def test3(): - url3 = f"http://api.tld/user/{user_id}" - requests.get(url3) - requests.get(url4) -``` - -```python -def test1(): - requests.get("http://api.tld") - requests.get("http://api.tld/user/{0}".format(user_id)) - requests.get(f"http://api.tld/user/{user_id}") -``` - -## Compliant Code Examples -```python -def download_stuff(identifier, data): - directory = "/tmp" - attachments = data.get("attachments", []) - - attachment_url = attachments[0].get("attachment_url", "") - - try: - response = requests.get(attachment_url, timeout=300) - response.raise_for_status() - except requests.exceptions.RequestException: - return (False, "") -``` - -```python -def test1(): - requests.get("https://api.tld") - requests.get("https://api.tld/user/{0}".format(user_id)) - requests.get(f"https://api.tld/user/{user_id}") -``` diff --git a/content/en/static_analysis/rules/python-security/requests-timeout.md b/content/en/static_analysis/rules/python-security/requests-timeout.md deleted file mode 100644 index 9f83c4abb7bb2..0000000000000 --- a/content/en/static_analysis/rules/python-security/requests-timeout.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/requests-timeout - language: Python - severity: Error -title: no timeout was given on call to external resource ---- -## Metadata -**ID:** `python-security/requests-timeout` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Access to remote resources should always use a timeout and appropriately handle the timeout and recovery. When using `requests.get`, `requests.put`, `requests.patch`, etc. - we should always use a `timeout` as an argument. - -#### Learn More - - - [CWE-1088 - Synchronous Access of Remote Resource without Timeout](https://cwe.mitre.org/data/definitions/1088.html) - - [Python Best Practices: always use a timeout with the requests library](https://www.codiga.io/blog/python-requests-timeout/) - -## Non-Compliant Code Examples -```python -from requests import get, put -r = get(w, verify=False) # missing a timeout -r = get(w, verify=False, timeout=10) - -def bla(): - r = get(w, verify=False) -``` - -```python -import requests -r = requests.put(w, verify=False) # missing a timeout -``` - -```python -import requests -r = requests.get(w, verify=False) # missing a timeout -r = requests.get(w, verify=False, timeout=10) - - - -def foo(): - r = requests.get(w, verify=False) # missing a timeout -``` - -## Compliant Code Examples -```python -r = requests.put(w, verify=False) -``` - -```python -import requests -r = requests.get(w, verify=False, timeout=5) -r = requests.get(w, verify=False, timeout=10) -``` diff --git a/content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md b/content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md deleted file mode 100644 index 24ccda29f0d50..0000000000000 --- a/content/en/static_analysis/rules/python-security/ruamel-unsafe-yaml.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/ruamel-unsafe-yaml - language: Python - severity: Error -title: Do not use insecure YAML deserialization ---- -## Metadata -**ID:** `python-security/ruamel-unsafe-yaml` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Unsafe YAML deserialization. Make sure to use safe deserialization methods to avoid execution or arbitrary code. - -#### Learn More - - - [ruamel.yaml documentation](https://yaml.readthedocs.io/en/latest/basicuse.html?highlight=typ) - - [CWE 502 - Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html) - -## Non-Compliant Code Examples -```python -from ruamel.yaml import YAML - -foo = YAML(typ='unsafe') - -def myfunction(arg): - bar = YAML(typ='base') -``` - -## Compliant Code Examples -```python -foo = YAML(typ='unsafe') - -def myfunction(arg): - bar = YAML(typ='base') -``` - -```python -from ruamel.yaml import YAML - -default = YAML() - -rt = YAML(typ='rt') - -safe = YAML(typ='safe') -``` diff --git a/content/en/static_analysis/rules/python-security/sql-server-security-credentials.md b/content/en/static_analysis/rules/python-security/sql-server-security-credentials.md deleted file mode 100644 index d8944d08ec526..0000000000000 --- a/content/en/static_analysis/rules/python-security/sql-server-security-credentials.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/sql-server-security-credentials - language: Python - severity: Error -title: do not pass hardcoded credentials ---- -## Metadata -**ID:** `python-security/sql-server-security-credentials` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Hardcoding database credentials directly in your source code is a security risk as anyone with access to your source code and see your credentials. It's strongly recommended to use a different approach that limits the exposure of your credentials. - -## Non-Compliant Code Examples -```python -import psycopg2 - -conn = psycopg2.connect(database="db_name", - host="db_host", - user="db_user", - password="db_pass", # hardcoded password - port="db_port") -``` - -```python -import mysql.connector - -connection = mysql.connector.connect( - host=host, - user=user, - passwd=f"password", # hardcoded password - database=database, - charset='utf8mb4', - use_pure=True, - connection_timeout=5) -``` - -```python -import mysql.connector - -connection = mysql.connector.connect( - host=host, - user=user, - passwd="password", # hardcoded password - database=database, - charset='utf8mb4', - use_pure=True, - connection_timeout=5) -``` - -## Compliant Code Examples -```python -import mysql.connector - -connection = mysql.connector.connect( - host=host, - user=user, - passwd=password, - database=database, - charset='utf8mb4', - use_pure=True, - connection_timeout=5) -``` - -```python -import mysql.connector - -connection = mysql.connector.another_function( - host=host, - user=user, - passwd=f"password", - database=database, - charset='utf8mb4', - use_pure=True, - connection_timeout=5) -``` diff --git a/content/en/static_analysis/rules/python-security/ssl-unverified-context.md b/content/en/static_analysis/rules/python-security/ssl-unverified-context.md deleted file mode 100644 index 81416a90ca0db..0000000000000 --- a/content/en/static_analysis/rules/python-security/ssl-unverified-context.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/ssl-unverified-context - language: Python - severity: Notice -title: should not bypass certificate verification ---- -## Metadata -**ID:** `python-security/ssl-unverified-context` - -**Language:** Python - -**Severity:** Notice - -**Category:** Security - -## Description -The call to `_create_unverified_context` from the ssl module bypass certificates verification. It should not be used and instead, certificates must be verified. - -## Non-Compliant Code Examples -```python -import xmlrpclib -import ssl - -test = xmlrpclib.ServerProxy('https://admin:bz15h9v9n@localhost:9999/API', - verbose=False, use_datetime=True, - context=ssl._create_unverified_context()) -test.list_satellites() -``` - -## Compliant Code Examples -```python -import xmlrpclib -import ssl - -test = xmlrpclib.ServerProxy('https://admin:bz15h9v9n@localhost:9999/API', - verbose=False, use_datetime=True) -test.list_satellites() -``` - -```python -import xmlrpclib - -test = xmlrpclib.ServerProxy('https://admin:bz15h9v9n@localhost:9999/API', - verbose=False, use_datetime=True, - context=ssl._create_unverified_context()) -test.list_satellites() -``` diff --git a/content/en/static_analysis/rules/python-security/subprocess-shell-true.md b/content/en/static_analysis/rules/python-security/subprocess-shell-true.md deleted file mode 100644 index ccc85e8c7e727..0000000000000 --- a/content/en/static_analysis/rules/python-security/subprocess-shell-true.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/subprocess-shell-true - language: Python - severity: Warning -title: shell argument leads to unnecessary privileges ---- -## Metadata -**ID:** `python-security/subprocess-shell-true` - -**Language:** Python - -**Severity:** Warning - -**Category:** Security - -## Description -Never invoke `subprocess.Popen` with `shell = True` leads to unnecessary privileges and access to the underlying execution runtime. Execution with `shell = True` should clearly be verified and checked for code in production. - -#### Learn More - - - [CWE-250](https://cwe.mitre.org/data/definitions/250.html) - Execution with Unnecessary Privileges - - [CWE-657](https://cwe.mitre.org/data/definitions/657.html) - Violation of Secure Design Principles - -## Non-Compliant Code Examples -```python -from subprocess import Popen -Popen('/bin/ls %s' % ('something',), shell=True) -``` - -```python -import subprocess -subprocess.Popen('/bin/ls %s' % ('something',), shell=True) -``` - -## Compliant Code Examples -```python -subprocess.Popen('/bin/ls %s' % ('something',), shell=True) -``` diff --git a/content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md b/content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md deleted file mode 100644 index 7b32f74745810..0000000000000 --- a/content/en/static_analysis/rules/python-security/variable-sql-statement-injection.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/variable-sql-statement-injection - language: Python - severity: Error -title: Avoid SQL injections ---- -## Metadata -**ID:** `python-security/variable-sql-statement-injection` - -**Language:** Python - -**Severity:** Error - -**Category:** Security - -## Description -Check for declarations of variables for a SQL statement where we have potential SQL injections. - -## Non-Compliant Code Examples -```python -def db_init_users(): - - users = [ - ('admin', 'SuperSecret'), - ('elliot', '123123123'), - ('tim', '12345678') - ] - - conn = sqlite3.connect('db_users.sqlite') - c = conn.cursor() - c.execute("CREATE TABLE users (username text, password text, failures int, mfa_enabled int, mfa_secret text)") - - for u,p in users: - c.execute("INSERT INTO users (username, password, failures, mfa_enabled, mfa_secret) VALUES ('%s', '%s', '%d', '%d', '%s')" %(u, p, 0, 0, '')) - - conn.commit() - conn.close() -``` - -```python -def get_product_by_id(db_connection, product_id): - cursor = db_connection.cursor() - res = cursor.execute(f"SELECT id, title from products WHERE id={product_id}") - data = res.fetchone() - if data is not None: - return Product(data[0], data[1]) - else: - return None - -def xss_reflected_page(request, app): - search = request.args.get('search') - - products = app.db_helper.execute_read( - f"SELECT * FROM products WHERE name LIKE :search", - { 'search': f'%{search}%' } - ) - - products = list( - map( - lambda p: { - 'id': p[0], - 'name': p[1], - 'price': p[2] - }, - products - ) - ) - - return render_template( - 'xss-reflected.html', - products=products - ) -``` - -```python -stmt = "UPDATE analysis_results SET running_time_sec='{0}' WHERE id={1}".format(nsec, id) - -stmt = "UPDATE analysis_results SET running_time_sec='%s' WHERE id=%s" % (nsec, id) - -stmt = "UPDATE analysis_results SET"\ - "running_time_sec='%s' WHERE id=%s" % nsec - - - -``` - -```python -v = "UPDATE bar SET plop={0}".format(plip) -``` - -```python -v = "UPDATE bar SET plop={0}".format(plip) - -cursor.execute("UPDATE bar SET plop={0}".format(plip)) - -cursor.execute("UPDATE `bar` SET plop={0}".format(plip)) -``` - -```python -v = f"DELETE FROM bar WHERE plop={bli}" - -cursor.execute(f"DELETE FROM bar WHERE plop={bli}") - -cursor.execute("DELETE FROM bar WHERE plop=%s", bli) -``` - -```python -v = f"SELECT foo FROM bar WHERE plop={bli}" -``` - -```python -v = "SELECT foo FROM bar WHERE plop={0}".format(bli) -``` - -## Compliant Code Examples -```python -def db_init_users(): - - users = [ - ('admin', 'SuperSecret'), - ('elliot', '123123123'), - ('tim', '12345678') - ] - - conn = sqlite3.connect('db_users.sqlite') - c = conn.cursor() - - for u,p in users: - c.execute("INSERT INTO users (username, password, failures, mfa_enabled, mfa_secret) VALUES ('%s', '%s', '%d', '%d', '%s')", (u, p, 0, 0, '')) - - conn.commit() - conn.close() -``` - -```python -v = "SELECT foo FROM bar WHERE plop=%s" -cursor.execute(v, (my_valie)) - -cursor.execute("UPDATE `bar` SET foo=%s", ("baz")) -``` diff --git a/content/en/static_analysis/rules/python-security/yaml-load.md b/content/en/static_analysis/rules/python-security/yaml-load.md deleted file mode 100644 index 36aaa0b8f4554..0000000000000 --- a/content/en/static_analysis/rules/python-security/yaml-load.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: python-security/yaml-load - language: Python - severity: Warning -title: avoid deserializing untrusted YAML ---- -## Metadata -**ID:** `python-security/yaml-load` - -**Language:** Python - -**Severity:** Warning - -**Category:** Security - -## Description -Avoid deserialization of untrusted YAML data via potential unsafe `yaml.load`. - -This rule checks that the `yaml` module is used and the `load` method is used. It recommends the usage of `safe_load` that prevents unsafe deserialization. - -**See Also** - - - [CWE-502 - Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html) - -## Non-Compliant Code Examples -```python -from yaml import load - -load("string") # should use safe_load -``` - -```python -import yaml - -yaml.load("string") # should use safe_load -``` - -## Compliant Code Examples -```python -import yaml - -yaml.load("string", loader=yaml.SafeLoader) # uses SafeLoader, so load is okay -``` - -```python -yaml.load("string") -``` diff --git a/content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md b/content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md deleted file mode 100644 index 16a624f5dfaa1..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/jsx-no-comment-textnodes.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: tsx-react/jsx-no-comment-textnodes - language: TypeScript - severity: Warning -title: Avoid comments from being inserted as text nodes ---- -## Metadata -**ID:** `tsx-react/jsx-no-comment-textnodes` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -As JSX mixes HTML and JavaScript together, comments in text nodes must be in brackets to be evaluated as JavaScript instead of HTML. This rule prevents you from accidentally leaving comments as HTML text. - -## Non-Compliant Code Examples -```typescript -var Hello = createReactClass({ - render: function() { - return ( -
- asd /* empty div */ -
- ); - } -}); - -var Hello = createReactClass({ - render: function() { - return ( -
- /* empty div */ -
- ); - } -}); -``` - -## Compliant Code Examples -```typescript -var Hello = createReactClass({ - displayName: 'Hello', - render: function() { - return
{/* empty div */}
; - } -}); - -var Hello = createReactClass({ - displayName: 'Hello', - render: function() { - return
; - } -}); - -var Hello = createReactClass({ - displayName: 'Hello', - render: function() { - return
; - } -}); -``` diff --git a/content/en/static_analysis/rules/tsx-react/no-children-prop.md b/content/en/static_analysis/rules/tsx-react/no-children-prop.md deleted file mode 100644 index 3fa06c732845f..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/no-children-prop.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: tsx-react/no-children-prop - language: TypeScript - severity: Warning -title: Avoid passing children as props ---- -## Metadata -**ID:** `tsx-react/no-children-prop` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -The children of a JSX element should appear as elements between the parent's opening and closing tags, not as props in the opening tag. This rule enforces the use of children as an element. - -## Non-Compliant Code Examples -```typescript -
; - -} />; -; - -React.createElement("div", { children: 'Children' }); -``` - -## Compliant Code Examples -```typescript -
Children
; -Children; - - Child 1 - Child 2 -; -React.createElement("div", {}, 'Children'); -React.createElement("div", 'Child 1', 'Child 2'); -``` diff --git a/content/en/static_analysis/rules/tsx-react/no-danger-with-children.md b/content/en/static_analysis/rules/tsx-react/no-danger-with-children.md deleted file mode 100644 index d0585bdede83e..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/no-danger-with-children.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: tsx-react/no-danger-with-children - language: TypeScript - severity: Warning -title: Avoid using children with dangerouslySetInnerHTML ---- -## Metadata -**ID:** `tsx-react/no-danger-with-children` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -If both `children` and `dangerouslySetInnerHTML` are set, it's unclear which one should take precedence, and React will throw a warning. To prevent this mistake, this rule enforces that either children or dangerouslySetInnerHTML are used, but not both. - -## Non-Compliant Code Examples -```typescript -
{Children}
; -Children; -; -React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); -React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }, "Children"); -``` - -## Compliant Code Examples -```typescript -
; -; -
Children
; -Children; -React.createElement("div", { dangerouslySetInnerHTML: { __html: "HTML" } }); -React.createElement("Hello", { dangerouslySetInnerHTML: { __html: "HTML" } }); -React.createElement("div", {}, "Children"); -React.createElement("Hello", {}, "Children"); -``` diff --git a/content/en/static_analysis/rules/tsx-react/no-deprecated.md b/content/en/static_analysis/rules/tsx-react/no-deprecated.md deleted file mode 100644 index 7ed1cae95f933..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/no-deprecated.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: tsx-react/no-deprecated - language: TypeScript - severity: Warning -title: Avoid deprecated methods ---- -## Metadata -**ID:** `tsx-react/no-deprecated` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -As React evolves, methods are deprecated over time. This rule warns you about deprecated methods. - -## Non-Compliant Code Examples -```typescript -React.render(, root); -React.unmountComponentAtNode(root); -React.findDOMNode(this.refs.foo); -React.renderToString(); -React.renderToStaticMarkup(); -React.createClass({ /* Class object */ }); - -//Any factories under React.DOM -React.DOM.div(); - -import React, { PropTypes } from 'react'; - -// old lifecycles (since React 16.9) -componentWillMount() { } -componentWillReceiveProps() { } -componentWillUpdate() { } - -// React 18 deprecations -import { render } from 'react-dom'; -ReactDOM.render(
, container); - -import { hydrate } from 'react-dom'; -ReactDOM.hydrate(
, container); - -import { unmountComponentAtNode } from 'react-dom'; -ReactDOM.unmountComponentAtNode(container); - -import { renderToNodeStream } from 'react-dom/server'; -ReactDOMServer.renderToNodeStream(element); -``` - -## Compliant Code Examples -```typescript -import { PropTypes } from 'prop-types'; - -UNSAFE_componentWillMount() { } -UNSAFE_componentWillReceiveProps() { } -UNSAFE_componentWillUpdate() { } - -ReactDOM.createPortal(child, container); - -import { createRoot } from 'react-dom/client'; -const root = createRoot(container); -root.unmount(); - -import { hydrateRoot } from 'react-dom/client'; -const root = hydrateRoot(container, ); -``` diff --git a/content/en/static_analysis/rules/tsx-react/no-render-return-value.md b/content/en/static_analysis/rules/tsx-react/no-render-return-value.md deleted file mode 100644 index 32565c66648ba..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/no-render-return-value.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: tsx-react/no-render-return-value - language: TypeScript - severity: Warning -title: Avoid usage of the return value of ReactDOM.render ---- -## Metadata -**ID:** `tsx-react/no-render-return-value` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Using the return value of the render method is a legacy feature. If you have a valid reason to reference the root React instance, you should assign a callback ref to the root component. - -## Non-Compliant Code Examples -```typescript -const inst = ReactDOM.render(, document.body); -``` - -## Compliant Code Examples -```typescript -ReactDOM.render(, document.body); - -ReactDOM.render(, document.body, doSomethingWithInst); -``` diff --git a/content/en/static_analysis/rules/tsx-react/no-string-refs.md b/content/en/static_analysis/rules/tsx-react/no-string-refs.md deleted file mode 100644 index 8a3b58d373ca0..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/no-string-refs.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: tsx-react/no-string-refs - language: TypeScript - severity: Warning -title: Avoid using string references ---- -## Metadata -**ID:** `tsx-react/no-string-refs` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -String references are a legacy feature of React. Use a reference callback instead. - -## Non-Compliant Code Examples -```typescript -var Hello = createReactClass({ - render: function() { - return
; - } -}); -var Hello = createReactClass({ - render: function() { - return
Hello, world.
; - } -}); -var Hello = createReactClass({ - componentDidMount: function() { - var component = this.refs.hello; - // ...do something with component - }, - render: function() { - return
Hello, world.
; - } -}); -``` - -## Compliant Code Examples -```typescript -var Hello = createReactClass({ - componentDidMount: function() { - var component = this.hello; - // ...do something with component - }, - render() { - return
{ this.hello = c; }}>Hello, world.
; - } -}); -``` diff --git a/content/en/static_analysis/rules/tsx-react/require-render-return.md b/content/en/static_analysis/rules/tsx-react/require-render-return.md deleted file mode 100644 index c3c37bdb3abbc..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/require-render-return.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: tsx-react/require-render-return - language: TypeScript - severity: Error -title: Enforce class for returning value in render function ---- -## Metadata -**ID:** `tsx-react/require-render-return` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -It's easy to forget to return a value from a class component render method. This rule warns when the render method does not return a value. - -## Non-Compliant Code Examples -```typescript -var Hello = createReactClass({ - render() { -
Hello
; - } -}); - -class Hello extends React.Component { - render() { -
Hello
; - } -} -``` - -## Compliant Code Examples -```typescript -var Hello = createReactClass({ - render() { - return
Hello
; - } -}); - -class Hello extends React.Component { - render() { - return
Hello
; - } -} -``` diff --git a/content/en/static_analysis/rules/tsx-react/tsx-key.md b/content/en/static_analysis/rules/tsx-react/tsx-key.md deleted file mode 100644 index 4439171509183..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/tsx-key.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: tsx-react/tsx-key - language: TypeScript - severity: Error -title: Prevent missing key props in iterators/collection literals ---- -## Metadata -**ID:** `tsx-react/tsx-key` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -In JSX you need to specify a `key` prop for each item of a list. A missing `key` prop can lead to unexpected renders or stale UI. This rule checks for possible JSX lists and warns if the `key` prop is missing. - -## Non-Compliant Code Examples -```typescript -[<>]; -[, foo, ]; -[, foo, ]; -data.map(x => ); -data.map(x => {x}); -data.map(x => {x}); -data.map(x => { return {x}}); -data.map(x => { return {x}}); -data.map(function(x) { return {x}}); -data.map(function(x) { return {x}}); -Array.from([1, 2, 3], (x) => {x}); -``` - -## Compliant Code Examples -```typescript -[, , ]; -data.map((x) => {x}); -Array.from([1, 2, 3], (x) => {x}); - -``` diff --git a/content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md b/content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md deleted file mode 100644 index 963a8b774d745..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/tsx-no-duplicate-key.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: tsx-react/tsx-no-duplicate-key - language: TypeScript - severity: Error -title: Ensures unique key prop ---- -## Metadata -**ID:** `tsx-react/tsx-no-duplicate-key` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -Duplicate JSX element keys can lead to unexpected behavior. Keys are meant to be always unique. - -## Non-Compliant Code Examples -```typescript -[, foo, ]; -[, foo]; -[, ]; -data.map(x => ); -data.map(x => {x}); -data.map(x => {x}); -data.map(x => { return {x}}); -data.map(function(x) { return {x}}); -Array.from([1, 2, 3], (x) => {x}); -``` - -## Compliant Code Examples -```typescript -[, foo, ]; -data.map(x => { return {x}}); -``` diff --git a/content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md b/content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md deleted file mode 100644 index a20b977a171dc..0000000000000 --- a/content/en/static_analysis/rules/tsx-react/tsx-no-target-blank.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: tsx-react/tsx-no-target-blank - language: TypeScript - severity: Warning -title: Prevent target='_blank' security risks ---- -## Metadata -**ID:** `tsx-react/tsx-no-target-blank` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Using `target="_blank"` in an anchor (``) tag allows a link to be opened in a new browser tab or window. - -A malicious website opened through `target="_blank"` can change the `window.opener.location` to a phishing page, potentially misleading users. - -This rule enforces using `rel="noreferrer"` with on links that have the `target="_blank"` attribute. It might not be needed if you target modern browsers, but is still recommended to follow it as a best practice. - -#### Known Limitations - -This rule does not support custom link components without an `href`, `target` and `rel` properties. - -## Non-Compliant Code Examples -```typescript -var Hello = -var Hello = -var Nested = -var Nested = -``` - -## Compliant Code Examples -```typescript -var Hello =

-var Hello =

-var Hello = -var Hello = -var Hello = -var Hello = -var Hello = -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/ban-types.md b/content/en/static_analysis/rules/typescript-best-practices/ban-types.md deleted file mode 100644 index ebd6811a2b5c6..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/ban-types.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/ban-types - language: TypeScript - severity: Notice -title: Avoid certain types ---- -## Metadata -**ID:** `typescript-best-practices/ban-types` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Some types have several ways to be defined, and some others could be dangerous. This rule suggests a consistent use of types. - -## Non-Compliant Code Examples -```typescript -// use lower-case primitives for consistency -const str: String = 'foo'; -const bool: Boolean = true; -const num: Number = 1; -const symb: Symbol = Symbol('foo'); -const bigInt: BigInt = 1n; - -// use a proper function type -const func: Function = () => 1; - -// use safer object types -const lowerObj: Object = {}; -const capitalObj: Object = { a: 'string' }; - -const curly1: {} = 1; -const curly2: {} = { a: 'string' }; -``` - -## Compliant Code Examples -```typescript -// use lower-case primitives for consistency -const str: string = 'foo'; -const bool: boolean = true; -const num: number = 1; -const symb: symbol = Symbol('foo'); -const bigInt: bigint = 1n; - -// use a proper function type -const func: () => number = () => 1; - -// use safer object types -const lowerObj: object = {}; -const capitalObj: { a: string } = { a: 'string' }; - -const curly1: number = 1; -const curly2: Record<'a', string> = { a: 'string' }; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md b/content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md deleted file mode 100644 index ee1c6aa782de0..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/boolean-prop-naming.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-best-practices/boolean-prop-naming - language: TypeScript - severity: Notice -title: Consistent naming for boolean props ---- -## Metadata -**ID:** `typescript-best-practices/boolean-prop-naming` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Enforces a consistent naming pattern for boolean props. - -The pattern is: `"^(is|has)[A-Z]([A-Za-z0-9]?)+"` to enforce `is` and `has` prefixes. - -## Non-Compliant Code Examples -```typescript -type Props = { - enabled: boolean -} - -``` - -## Compliant Code Examples -```typescript -type Props = { - isEnabled: boolean; - hasFoo: boolean; -} - -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/for-direction.md b/content/en/static_analysis/rules/typescript-best-practices/for-direction.md deleted file mode 100644 index 013d99c73eded..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/for-direction.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/for-direction - language: TypeScript - severity: Error -title: Check for loop is moving in the right direction ---- -## Metadata -**ID:** `typescript-best-practices/for-direction` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -This rule prevents you from creating conditions in which a `for` loop might end up in an infinite loop. If you need an infinite loop, use `while` statements. - -## Non-Compliant Code Examples -```typescript -// test if '++', '--' -for(var i = 0; i < 10; i--){} -for(var i = 0; i <= 10; i--){} -for(var i = 10; i > 10; i++){} -for(var i = 10; i >= 0; i++){} - -// test if '+=', '-=' -for(var i = 0; i < 10; i-=1){} -for(var i = 0; i <= 10; i-=1){} -for(var i = 10; i > 10; i+=1){} -for(var i = 10; i >= 0; i+=1){} -for(var i = 0; i < 10; i+=-1){} -for(var i = 0; i <= 10; i+=-1){} -for(var i = 10; i > 10; i-=-1){} -for(var i = 10; i >= 0; i-=-1){} -``` - -## Compliant Code Examples -```typescript -// test if '++', '--' -for(var i = 0; i < 10; i++){} -for(var i = 0; i <= 10; i++){} -for(var i = 10; i > 0; i--){} -for(var i = 10; i >= 0; i--){} - -// test if '+=', '-=', -for(var i = 0; i < 10; i+=1){} -for(var i = 0; i <= 10; i+=1){} -for(var i = 0; i < 10; i-=-1){} -for(var i = 0; i <= 10; i-=-1){} -for(var i = 10; i > 0; i-=1){} -for(var i = 10; i >= 0; i-=1){} -for(var i = 10; i > 0; i+=-1){} -for(var i = 10; i >= 0; i+=-1){} - -// test if no update. -for(var i = 10; i > 0;){} -for(var i = 10; i >= 0;){} -for(var i = 10; i < 0;){} -for(var i = 10; i <= 0;){} -for(var i = 10; i <= 0; j++){} -for(var i = 10; i <= 0; j--){} -for(var i = 10; i >= 0; j++){} -for(var i = 10; i >= 0; j--){} -for(var i = 10; i >= 0; j += 2){} -for(var i = 10; i >= 0; j -= 2){} -for(var i = 10; i >= 0; i |= 2){} -for(var i = 10; i >= 0; i %= 2){} -for(var i = 0; i < MAX; i += STEP_SIZE); -for(var i = 0; i < MAX; i -= STEP_SIZE); -for(var i = 10; i > 0; i += STEP_SIZE); - -// other cond-expressions. -for(var i = 0; i !== 10; i+=1){} -for(var i = 0; i === 10; i+=1){} -for(var i = 0; i == 10; i+=1){} -for(var i = 0; i != 10; i+=1){} -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/new-parens.md b/content/en/static_analysis/rules/typescript-best-practices/new-parens.md deleted file mode 100644 index a4f7f0c6daf49..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/new-parens.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/new-parens - language: TypeScript - severity: Notice -title: Invoking a constructor must use parentheses ---- -## Metadata -**ID:** `typescript-best-practices/new-parens` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -This rule enforces the consistent use of parentheses in `new` statements. In JavaScript, you can omit parentheses when the constructor has no arguments, but you should always use them for consistency. - -## Non-Compliant Code Examples -```typescript -// Default (Always) -var a = new Date; -var a = new Date -var a = new (Date); -var a = new (Date) -var a = (new Date) - -// This `()` is `CallExpression`'s. This is a call of the result of `new Date`. -var a = new foo.Bar; -var a = (new Foo).bar; - -// Explicit always -var a = new Date; -var a = new foo.Bar; -var a = (new Foo).bar; -var a = new new Foo(); - -// OPTION never not supported -// Never -// var a = new Date(); -// var a = new Date() -// var a = new (Date)(); -// var a = new (Date)() -// var a = (new Date()) -// var a = (new Date())() -// var a = new foo.Bar(); -// var a = (new Foo()).bar; -// var a = new new Foo() -``` - -## Compliant Code Examples -```typescript -// Default (Always) -var a = new Date(); -var a = new Date(function() {}); -var a = new (Date)(); -var a = new ((Date))(); -var a = (new Date()); -var a = new foo.Bar(); -var a = (new Foo()).bar; - -// Explicit Always -var a = new Date(); -var a = new foo.Bar(); -var a = (new Foo()).bar; - -// OPTION never not supported -// Never -// var a = new Date; -// var a = new Date(function() {}); -// var a = new (Date); -// var a = new ((Date)); -// var a = (new Date); -// var a = new foo.Bar; -// var a = (new Foo).bar; -// var a = new Person('Name') -// var a = new Person('Name', 12) -// var a = new ((Person))('Name'); -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-alert.md b/content/en/static_analysis/rules/typescript-best-practices/no-alert.md deleted file mode 100644 index 4098aa3027b95..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-alert.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-alert - language: TypeScript - severity: Notice -title: Avoid the use of alert, confirm, and prompt ---- -## Metadata -**ID:** `typescript-best-practices/no-alert` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -JavaScript’s `alert`, `confirm`, and `prompt` functions present obtrusive UI elements that prevent further user actions by taking control of the focus. These UI elements cannot be styled. - -## Non-Compliant Code Examples -```typescript -alert(foo) -window.alert(foo) -window['alert'](foo) -confirm(foo) -window.confirm(foo) -window['confirm'](foo) -prompt(foo) -window.prompt(foo) -window['prompt'](foo) -function alert() {} window.alert(foo) -var alert = function() {}; -window.alert(foo) -function foo(alert) { window.alert(); } -function foo() { alert(); } -function foo() { var alert = function() {}; } -alert(); -this.alert(foo) -this['alert'](foo) -function foo() { var window = bar; window.alert(); } -window.alert(); -globalThis['alert'](foo) -globalThis.alert(); -function foo() { var globalThis = bar; globalThis.alert(); } -globalThis.alert(); - -// Optional chaining -window?.alert(foo); -(window?.alert)(foo); -``` - -## Compliant Code Examples -```typescript -a[o.k](1) -foo.alert(foo) -foo.confirm(foo) -foo.prompt(foo) -// global overrides are not recommened -// and wont be supported by this rule -// function alert() {} alert(); -// var alert = function() {}; alert(); -// function foo() { var alert = bar; alert(); } -// function foo(alert) { alert(); } -// var alert = function() {}; function test() { alert(); } -// function foo() { var alert = function() {}; function test() { alert(); } } -// function confirm() {} confirm(); -// function prompt() {} prompt(); -window[alert](); -// function foo() { this.alert(); } -// function foo() { var window = bar; window.alert(); } -// globalThis.alert(); -// globalThis['alert'](); -// globalThis.alert(); -// var globalThis = foo; globalThis.alert(); -// function foo() { var globalThis = foo; globalThis.alert(); } -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md b/content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md deleted file mode 100644 index b686444c32fac..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-async-promise-executor.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-async-promise-executor - language: TypeScript - severity: Error -title: Promise executor cannot be an async function ---- -## Metadata -**ID:** `typescript-best-practices/no-async-promise-executor` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -An async Promise executor won't surface exceptions if it fails. If you are already awaiting results in the executor, the Promise itself might not be required; please review your implementation. - -## Non-Compliant Code Examples -```typescript -new Promise(async function foo(resolve, reject) {}) -new Promise(async (resolve, reject) => {}) -``` - -## Compliant Code Examples -```typescript -new Promise((resolve, reject) => {}) -new Promise((resolve, reject) => {}, async function unrelated() {}) -new Foo(async (resolve, reject) => {}) -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-caller.md b/content/en/static_analysis/rules/typescript-best-practices/no-caller.md deleted file mode 100644 index 83676bb2be830..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-caller.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-caller - language: TypeScript - severity: Warning -title: Avoid the use of arguments.caller or arguments.callee ---- -## Metadata -**ID:** `typescript-best-practices/no-caller` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -`arguments.caller` and `arguments.callee` has been deprecated and forbidden in ECMAScript 5 strict mode. - -## Non-Compliant Code Examples -```typescript -var x = arguments.callee; -var x = arguments.caller; -``` - -## Compliant Code Examples -```typescript -var x = arguments.length -var x = arguments -var x = arguments[0] -var x = arguments[caller] -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md b/content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md deleted file mode 100644 index 4c02763c6f993..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-compare-neg-zero.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-compare-neg-zero - language: TypeScript - severity: Error -title: Direct comparison with -0 detected ---- -## Metadata -**ID:** `typescript-best-practices/no-compare-neg-zero` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -In JavaScript, `-0` and `+0` are considered to be equal (`(-0 === +0) // true`). However, they behave differently in some operations. For instance, `1/-0` results in `-Infinity`, while `1/+0` results in `+Infinity`. Directly comparing with `-0` can produce results that are hard to understand, and may lead to bugs. - -## Non-Compliant Code Examples -```typescript -x === -0; --0 === x; -x == -0; --0 == x; -x > -0; --0 > x; -x >= -0; --0 >= x; -x < -0; --0 < x; -x <= -0; --0 <= x; -``` - -## Compliant Code Examples -```typescript -x === 0 -0 === x -x == 0 -0 == x -x === '0' -'0' === x -x == '0' -'0' == x -x === '-0' -'-0' === x -x == '-0' -'-0' == x -x === -1 --1 === x -x < 0 -0 < x -x <= 0 -0 <= x -x > 0 -0 > x -x >= 0 -0 >= x -x != 0 -0 != x -x !== 0 -0 !== x -Object.is(x, -0) -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md b/content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md deleted file mode 100644 index 977feb648fe1f..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-cond-assign.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-cond-assign - language: TypeScript - severity: Error -title: Avoid assignment operators in conditional expressions ---- -## Metadata -**ID:** `typescript-best-practices/no-cond-assign` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -While there may be valid reasons to use an assignment operation in a condition, it is very easy to mistake `=` with `==`, which is usually what is intended. This rule prevents mistakes like these because it is easier to intentionally disable the rule than identify the error. - -## Non-Compliant Code Examples -```typescript -var x; if (x = 0) { var b = 1; } -var x; while (x = 0) { var b = 1; } -var x = 0, y; do { y = x; } while (x = x + 1); -var x; for(; x+=1 ;){}; -var x; if ((x) = (0)); -if (someNode || (someNode = parentNode)) { } -if (someNode || (someNode = parentNode)) { } -while (someNode || (someNode = parentNode)) { } -do { } while (someNode || (someNode = parentNode)); -for (; typeof l === 'undefined' ? (l = 0) : l; i++) { } -if (x = 0) { } -while (x = 0) { } -do { } while (x = x + 1); -for(; x = y; ) { } -var x; var b = (x = 0) ? 1 : 0; -var x; var b = x && (y = 0) ? 1 : 0; -(((3496.29)).bkufyydt = 2e308) ? foo : bar; - - -if ((someNode = someNode.parentNode) !== null) { } -if ((someNode = someNode.parentNode) !== null) { } -if (someNode || (someNode = parentNode)) { } -while (someNode || (someNode = parentNode)) { } -do { } while (someNode || (someNode = parentNode)); -for (;someNode || (someNode = parentNode);); -``` - -## Compliant Code Examples -```typescript -var x = 0; if (x == 0) { var b = 1; } -var x = 0; if (x == 0) { var b = 1; } -var x = 5; while (x < 5) { x = x + 1; } -if ((a = b)); -while ((a = b)); -do {} while ((a = b)); -for (;(a = b);); -for (;;) {} -if ((function(node) { return node = parentNode; })(someNode)) { } -if ((function(node) { return node = parentNode; })(someNode)) { } -if ((node => node = parentNode)(someNode)) { } -if ((node => node = parentNode)(someNode)) { } -if (function(node) { return node = parentNode; }) { } -if (function(node) { return node = parentNode; }) { } -x = 0; -var x; var b = (x === 0) ? 1 : 0; -switch (foo) { case a = b: bar(); } -switch (foo) { case a = b: bar(); } -switch (foo) { case baz + (a = b): bar(); } -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-console.md b/content/en/static_analysis/rules/typescript-best-practices/no-console.md deleted file mode 100644 index ff2cad66719c2..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-console.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-console - language: TypeScript - severity: Warning -title: Avoid leaving console debug statements ---- -## Metadata -**ID:** `typescript-best-practices/no-console` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Debugging with `console` is not considered a bad practice, but it's easy to forget about `console` statements and leave them in production code. There is no need to pollute production builds with debugging statements. - -## Non-Compliant Code Examples -```typescript -console.log(foo) -console.error(foo) -console.info(foo) -console.warn(foo) -``` - -## Compliant Code Examples -```typescript -Console.info(foo) -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-debugger.md b/content/en/static_analysis/rules/typescript-best-practices/no-debugger.md deleted file mode 100644 index bdb0df9754fdb..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-debugger.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-debugger - language: TypeScript - severity: Error -title: Disallow the use of debugger ---- -## Metadata -**ID:** `typescript-best-practices/no-debugger` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -The `debugger` statement is used to intentionally stop execution and start debugging at the point where the statement appears in the code. While it can be valuable during development and debugging, it can cause unwanted behaviors if it's present in production code. - -## Non-Compliant Code Examples -```typescript -if (foo) debugger -``` - -## Compliant Code Examples -```typescript -var test = { debugger: 1 }; test.debugger; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md b/content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md deleted file mode 100644 index e486f1868ec63..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-delete-var.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-delete-var - language: TypeScript - severity: Error -title: Avoid using delete on variables directly ---- -## Metadata -**ID:** `typescript-best-practices/no-delete-var` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -The `delete` operator is designed to remove properties from objects in JavaScript. When used correctly, it can help manage object properties. However, using the `delete` operator on anything other than object properties can lead to unpredictable behavior. - -## Non-Compliant Code Examples -```typescript -delete x -``` - -## Compliant Code Examples -```typescript -delete x.prop; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md b/content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md deleted file mode 100644 index 5328b1b4ac47f..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-dupe-keys.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-dupe-keys - language: TypeScript - severity: Error -title: Avoid duplicate keys in object literals ---- -## Metadata -**ID:** `typescript-best-practices/no-dupe-keys` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -Object literals should not have duplicate keys. If you define an object with duplicate keys, the last one will overwrite any preceding ones. - -## Non-Compliant Code Examples -```typescript -var x = { a: b, ['a']: b }; -var x = { y: 1, y: 2 }; -var x = { '': 1, '': 2 }; -var x = { '': 1, [``]: 2 }; -var foo = { 0x1: 1, 1: 2}; -// should be captured by no-octal -// var x = { 012: 1, 10: 2 }; -var x = { 0b1: 1, 1: 2 }; -var x = { 0o1: 1, 1: 2 }; -var x = { 1n: 1, 1: 2 }; -var x = { 1_0: 1, 10: 2 }; -var x = { "z": 1, z: 2 }; -var foo = { - bar: 1, - bar: 1, - bar() {} -} -var x = { a: 1, get ['a']() {} }; -var x = { a: 1, set a(value) {} }; -var x = { a: 1, b: { a: 2 }, get b() {} }; -var x = ({ '/(?0)/': 1, [/(?0)/]: 2 }) -``` - -## Compliant Code Examples -```typescript -var foo = { __proto__: 1, two: 2}; -var x = { foo: 1, bar: 2 }; -var x = { '': 1, bar: 2 }; -var x = { '': 1, ' ': 2 }; -var x = { '': 1, [null]: 2 }; -var x = { '': 1, [a]: 2 }; -var x = { [a]: 1, [a]: 2 }; -+{ get a() { }, set a(b) { } }; -var x = { a: b, [a]: b }; -var x = { a: b, ...c } -var x = { get a() {}, set a (value) {} }; -var x = { a: 1, b: { a: 2 } }; -var x = ({ null: 1, [/(?0)/]: 2 }) -var {a, a} = obj -// should be captured by no-octal -// var x = { 012: 1, 12: 2 }; -var x = { 1_0: 1, 1: 2 }; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md b/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md deleted file mode 100644 index 37508ec8fcbda..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-duplicate-enum-values - language: TypeScript - severity: Warning -title: Avoid duplicate enum member values ---- -## Metadata -**ID:** `typescript-best-practices/no-duplicate-enum-values` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -An `enum` should not have duplicate values, which are usually not expected to be present. - -## Non-Compliant Code Examples -```typescript -enum A { - A = 1, - B = 1, -} -enum B { - A = 'A', - B = 'A', -} -enum C { - A = 'A', - B = 'A', - C = 1, - D = 1, -} -enum E { - A = 'A', - B = 'A', - C = 1, - D = 1, -} - -``` - -## Compliant Code Examples -```typescript -enum A { - A, - B, -} - -enum B { - A = 1, - B, -} - -enum C { - A = 1, - B = 2, -} - -enum D { - A = 'A', - B = 'B', -} - -enum E { - A = 'A', - B = 'B', - C, -} - -enum F { - A = 'A', - B = 'B', - C = 2, - D = 1 + 1, -} - -enum G { - A = 3, - B = 2, - C, -} - -enum H { - A = 'A', - B = 'B', - C = 2, - D = foo(), -} - -enum I { - A = '', - B = 0, -} - -enum J { - A = 0, - B = -0, - C = NaN, -} - -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md b/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md deleted file mode 100644 index 055e29b8b675b..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-duplicate-type-constituents - language: TypeScript - severity: Warning -title: Avoid duplicate constituents of unions or intersections ---- -## Metadata -**ID:** `typescript-best-practices/no-duplicate-type-constituents` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Union and intersection types could duplicate each other. Duplicate values make the code harder to read and are usually not expected. - -## Non-Compliant Code Examples -```typescript -type A = 1 | 1; -type B = true & true; -type C = null | null; -type D = any | any; -type E = { a: string | string }; -type F = { a: string } | { a: string }; -type G = { a: string; b: number } | { a: string; b: number }; -type H = Set | Set; -type ActuallyDuplicated = IsArray | IsArray; -type I = Class | Class; -type J = string[] | string[]; -type K = string[][] | string[][]; -type L = [1, 2, 3] | [1, 2, 3]; -type M = () => string | string; -type N = () => null | null; -type O = (arg: string | string) => void; -type P = 'A' | 'A'; -type S = A | A; -type T = A | /* comment */ A; -type U = A | B | A; -type V = A | B | A | B; -type W = A | B | A | A; -type X = A | B | A | C; -type Y = (A | B) | (A | B); -type Z = A | (A | A); -type AA = (A | B) | (A | B) | ((C | D) & (A | B)) | (A | B); -type BB = Record; - -``` - -## Compliant Code Examples -```typescript -type A = 1 | 2; -type B = 1 | '1'; -type C = true & boolean; -type D = null | undefined; -type E = any | unknown; -type F = { a: string } | { b: string }; -type G = { a: string; b: number } | { b: number; a: string }; -type H = { a: string | number }; -type I = Set | Set; -type J = Class | Class; -type K = string[] | number[]; -type L = string[][] | string[]; -type M = [1, 2, 3] | [1, 2, 4]; -type N = [1, 2, 3] | [1, 2, 3, 4]; -type O = 'A' | string[]; -type P = (() => string) | (() => void); -type Q = () => string | void; -type R = () => null | undefined; -type S = (arg: string | number) => void; - -type T = 'A'; -type U = 'B'; -type V = A | B; - -type W = 'A'; -type X = 'B'; -const a: A | B = 'A'; - -type Y = 'A'; -type Z = 'B'; -type AA = A | /* comment */ B; - -type BB = 'A'; -type CC = 'B'; -type DD = 'A' | 'B'; - -type EE = 'A'; -type FF = 'B'; -type GG = 'C'; -type HH = A | B | C; - -type JJ = 'A'; -type KK = 'B'; -type LL = 'C'; -type MM = 'D'; -type NN = (A | B) | (C | D); - -type OO = 'A'; -type PP = 'B'; -type QQ = (A | B) | (A & B); - -type RR = 'A'; -type SS = 'B'; -type TT = Record; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md b/content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md deleted file mode 100644 index 45c430986defb..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-empty-character-class.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-empty-character-class - language: TypeScript - severity: Error -title: Avoid empty character classes in regular expressions ---- -## Metadata -**ID:** `typescript-best-practices/no-empty-character-class` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -In regular expressions, empty character classes do not match anything, and were likely used in error. - -## Non-Compliant Code Examples -```typescript -var foo = /^abc[]/; -var foo = /foo[]bar/; -if (foo.match(/^abc[]/)) {} -if (/^abc[]/.test(foo)) {} -var foo = /[]]/; -var foo = /\[[]/; -var foo = /\\[\\[\\]a-z[]/; -var foo = /[]]/d; -``` - -## Compliant Code Examples -```typescript -var foo = /^abc[a-zA-Z]/; -var regExp = new RegExp("^abc[]"); -var foo = /^abc/; -var foo = /[\\[]/; -var foo = /[\\]]/; -var foo = /[a-zA-Z\\[]/; -var foo = /[[]/; -var foo = /[\\[a-z[]]/; -var foo = /[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\^\\$\\|]/g; -var foo = /\\s*:\\s*/gim; -var foo = /[\\]]/uy; -var foo = /[\\]]/s; -var foo = /[\\]]/d; -var foo = /\[]/ -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md b/content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md deleted file mode 100644 index da58d32f8194e..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-empty-pattern.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-empty-pattern - language: TypeScript - severity: Error -title: Avoid empty destructuring patterns ---- -## Metadata -**ID:** `typescript-best-practices/no-empty-pattern` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -An empty destructuring pattern doesn't provide any value and might be confusing, as it looks similar to the default assignment. - -## Non-Compliant Code Examples -```typescript -var {} = foo -var [] = foo -var {a: {}} = foo -var {a, b: {}} = foo -var {a: []} = foo -function foo({}) {} -function foo([]) {} -function foo({a: {}}) {} -function foo({a: []}) {} -``` - -## Compliant Code Examples -```typescript -var {a = {}} = foo; -var {a, b = {}} = foo; -var {a = []} = foo; -function foo({a = {}}) {} -function foo({a = []}) {} -var [a] = foo -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-empty.md b/content/en/static_analysis/rules/typescript-best-practices/no-empty.md deleted file mode 100644 index a7ea1048599b5..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-empty.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-empty - language: TypeScript - severity: Error -title: Avoid empty block statements ---- -## Metadata -**ID:** `typescript-best-practices/no-empty` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -Empty or non-functional blocks in the code can be misleading and lead to maintenance difficulties. They can also lead to a false sense of security or functionality. While they may not directly introduce security issues, their presence can suggest that some logic or error handling is implemented when it is not. - -## Non-Compliant Code Examples -```typescript -try {} catch (ex) {throw ex} -try { foo() } catch (ex) {} -try { foo() } catch (ex) {throw ex} finally {} -if (foo) {} -while (foo) {} -for (;foo;) {} -switch(foo) {} -switch (foo) { /* empty */ } -try {} catch (ex) {} -try { foo(); } catch (ex) {} finally {} -try {} catch (ex) {} finally {} -try { foo(); } catch (ex) {} finally {} -(function() { }()) -var foo = () => {} -function foo() { } -function bla() { - -} -``` - -## Compliant Code Examples -```typescript -export async function foo() { - const test = {}; -} -if (foo) { bar() } -while (foo) { bar() } -for (;foo;) { bar() } -try { foo() } catch (ex) { foo() } -switch(foo) {case 'foo': break;} -if (foo) {/* empty */} -while (foo) {/* empty */} -for (;foo;) {/* empty */} -try { foo() } catch (ex) {/* empty */} -try { foo() } catch (ex) {// empty -} -try { foo() } finally {// empty -} -try { foo() } finally {// test -} -try { foo() } finally { - - // hi i am off no use -} -try { foo() } catch (ex) {/* test111 */} -if (foo) { bar() } else { // nothing in me -} -if (foo) { bar() } else { /**/ -} -if (foo) { bar() } else { // -} -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md b/content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md deleted file mode 100644 index 59233b530f1a1..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-ex-assign.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-ex-assign - language: TypeScript - severity: Error -title: Avoid reassigning exceptions in catch clauses ---- -## Metadata -**ID:** `typescript-best-practices/no-ex-assign` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -Catching an exception and assigning a different value to the error parameter will overwrite the reference to the original error data, which will be lost since there is no `arguments` object in a catch clause. - -## Non-Compliant Code Examples -```typescript -try { } catch (e) { e = 10; } -try { } catch (ex) { ex = 10; } -try { } catch (ex) { [ex] = []; } -try { } catch (ex) { ({x: ex = 0} = {}); } -try { } catch ({message}) { message = 10; } -``` - -## Compliant Code Examples -```typescript -try { } catch (e) { three = 2 + 1; } -try { } catch ({e}) { this.something = 2; } -function foo() { try { } catch (e) { return false; } } -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md b/content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md deleted file mode 100644 index 62a352163ae8a..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-explicit-any.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-explicit-any - language: TypeScript - severity: Notice -title: Avoid the any type ---- -## Metadata -**ID:** `typescript-best-practices/no-explicit-any` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not use the `any` type, as it is too broad and can lead to unexpected behavior. - -## Non-Compliant Code Examples -```typescript -const number: any = 1 -function generic(): any {} -function generic(): Array {} -function generic(): any[] {} -function generic(param: Array): number {} -function generic(param: any[]): number {} -function generic(param: Array): Array {} - -function generic(): Array> {} -function generic(): Array {} - -class Greeter { constructor(param: Array) {} } -class Greeter { message: any; } - -class Greeter { message: Array; } -class Greeter { message: any[]; } -class Greeter { message: Array>; } -class Greeter { message: Array; } - -interface Greeter { message: any; } -interface Greeter { message: Array; } -interface Greeter { message: any[]; } -interface Greeter { message: Array>; } -interface Greeter { message: Array; } -type obj = { message: any; } -type obj = { message: Array; } -type obj = { message: any[]; } -type obj = { message: Array>; } -type obj = { message: Array; } -type obj = { message: string | any; } -type obj = { message: string | Array; } -type obj = { message: string | any[]; } -type obj = { message: string | Array>; } -type obj = { message: string | Array; } -type obj = { message: string & any; } -type obj = { message: string & Array; } -type obj = { message: string & any[]; } -type obj = { message: string & Array>; } -type obj = { message: string & Array; } -class Foo extends Bar {} -abstract class Foo extends Bar {} -abstract class Foo implements Bar, Baz {} -new Foo() -Foo() - -// https://github.com/typescript-eslint/typescript-eslint/issues/64 -function test>() {} -const test = >() => {}; -function foo(a: number, ...rest: any[]): void { return; } -type Any = any; -function foo5(...args: any) {} - -const bar5 = function (...args: any) {} -const baz5 = (...args: any) => {} -interface Qux5 { (...args: any): void; } -function quux5(fn: (...args: any) => void): void {} -function quuz5(): ((...args: any) => void) {} -type Fred5 = (...args: any) => void; -type Corge5 = new (...args: any) => void; -interface Grault5 { new (...args: any): void; } -interface Garply5 { f(...args: any): void; } -declare function waldo5(...args: any): void; -``` - -## Compliant Code Examples -```typescript -const number: number = 1; -function greet(): string {} -function greet(): Array {} -function greet(): string[] {} -function greet(): Array> {} -function greet(): Array {} -function greet(param: Array): Array {} - -class Greeter { message: string; } -class Greeter { message: Array; } -class Greeter { message: string[]; } -class Greeter { message: Array>; } -class Greeter { message: Array; } -interface Greeter { message: string; } -interface Greeter { message: Array; } -interface Greeter { message: string[]; } -interface Greeter { message: Array>; } -interface Greeter { message: Array; } -type obj = { message: string; }; -type obj = { message: Array; }; -type obj = { message: string[]; }; -type obj = { message: Array>; }; -type obj = { message: Array; }; -type obj = { message: string | number }; -type obj = { message: string | Array; }; -type obj = { message: string | string[]; }; -type obj = { message: string | Array>; }; -type obj = { message: string & number; }; -type obj = { message: string & Array; }; -type obj = { message: string & string[]; }; -type obj = { message: string & Array>; }; - -// rest params enforces due to no options -// https://github.com/eslint/typescript-eslint-parser/issues/397 -// function foo(a: number, ...rest: any[]): void { return; } -// function foo1(...args: any[]) {} -// const bar1 = function (...args: any[]) {}; -// const baz1 = (...args: any[]) => {}; -// function foo2(...args: readonly any[]) {} -// const bar2 = function (...args: readonly any[]) {}; -// const baz2 = (...args: readonly any[]) => {}; -// function foo3(...args: Array) {} -// const bar3 = function (...args: Array) {}; -// const baz3 = (...args: Array) => {}; -// function foo4(...args: ReadonlyArray) {} -// const bar4 = function (...args: ReadonlyArray) {}; -// const baz4 = (...args: ReadonlyArray) => {}; - -// interface Qux1 { (...args: any[]): void; } -// interface Qux2 { (...args: readonly any[]): void; } -// interface Qux3 { (...args: Array): void; } -// interface Qux4 { (...args: ReadonlyArray): void; } - -// function quux1(fn: (...args: any[]) => void): void {} -// function quux2(fn: (...args: readonly any[]) => void): void {} -// function quux3(fn: (...args: Array) => void): void {} -// function quux4(fn: (...args: ReadonlyArray) => void): void {} -// function quuz1(): (...args: any[]) => void {} -// function quuz2(): (...args: readonly any[]) => void {} -// function quuz3(): (...args: Array) => void {} -// function quuz4(): (...args: ReadonlyArray) => void {} -// type Fred1 = (...args: any[]) => void; -// type Fred2 = (...args: readonly any[]) => void; -// type Fred3 = (...args: Array) => void; -// type Fred4 = (...args: ReadonlyArray) => void; -// type Corge1 = new (...args: any[]) => void; -// type Corge2 = new (...args: readonly any[]) => void; -// type Corge3 = new (...args: Array) => void; -// type Corge4 = new (...args: ReadonlyArray) => void; - -// interface Grault1 { new (...args: any[]): void; } -// interface Grault2 { new (...args: readonly any[]): void; } -// interface Grault3 { new (...args: Array): void; } -// interface Grault4 { new (...args: ReadonlyArray): void; } -// interface Garply1 { f(...args: any[]): void; } -// interface Garply2 { f(...args: readonly any[]): void; } -// interface Garply3 { f(...args: Array): void; } -// interface Garply4 { f(...args: ReadonlyArray): void; } - -// declare function waldo1(...args: any[]): void; -// declare function waldo2(...args: readonly any[]): void; -// declare function waldo3(...args: Array): void; -// declare function waldo4(...args: ReadonlyArray): void; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md b/content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md deleted file mode 100644 index a5a34d5c0d9ed..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-extra-non-null-assertion - language: TypeScript - severity: Error -title: Avoid extra non-null assertions ---- -## Metadata -**ID:** `typescript-best-practices/no-extra-non-null-assertion` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -The non `null` or `undefined` assertion operation should not be used twice in a single expression. - -## Non-Compliant Code Examples -```typescript -const bar = foo!!.bar; -function foo(bar: number | undefined) { const bar: number = bar!!; } -function foo(bar?: { n: number }) { return bar!?.n; } -function foo(bar?: { n: number }) { return bar!?.(); } - -// parentheses -const foo: { bar: number } | null = null; const bar = (foo!)!.bar; -function foo(bar?: { n: number }) { return (bar!)?.n; } -function foo(bar?: { n: number }) { return (bar)!?.n; } -function foo(bar?: { n: number }) { return (bar!)?.(); } -``` - -## Compliant Code Examples -```typescript -const bar = foo!.bar; - -function foo(bar: number | undefined) { - const bar: number = bar!; -} - -function foo(bar?: { n: number }) { - return bar?.n; -} - -// https://github.com/typescript-eslint/typescript-eslint/issues/2166 -checksCounter?.textContent!.trim(); - -// https://github.com/typescript-eslint/typescript-eslint/issues/2732 -function foo(key: string | null) { - const obj = {}; - return obj?.[key!]; -} -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md b/content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md deleted file mode 100644 index cb33644ff17d7..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-implied-eval.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-best-practices/no-implied-eval - language: TypeScript - severity: Warning -title: Prevent the use methods similar to eval() ---- -## Metadata -**ID:** `typescript-best-practices/no-implied-eval` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -JavaScript methods like `setTimeout()`, `setInterval()`, or `execScript()` can accept a string of code as their first argument. This code will be executed at runtime, opening a vector for potential attacks. - -It is generally considered a bad practice to execute code at runtime. This rule considers these methods as implied evaluations when their parameter is a piece of code. - -## Non-Compliant Code Examples -```typescript -setTimeout("x = 1;"); -setTimeout("x = 1;", 100); -setInterval("x = 1;"); -execScript("x = 1;"); -// const s = 'x=1'; setTimeout(s, 100); -setTimeout(String('x=1'), 100); - -// member expressions -window.setTimeout('foo'); -window.setInterval('foo'); -window['setTimeout']('foo'); -window['setInterval']('foo'); -window[`setInterval`]('foo'); -window.window['setInterval']('foo'); -global.setTimeout('foo'); -global.setInterval('foo'); -global['setTimeout']('foo'); -global['setInterval']('foo'); -global[`setInterval`]('foo'); -global.global['setInterval']('foo'); -globalThis.setTimeout('foo'); -globalThis.setInterval('foo'); - -// template literals -setTimeout(`foo${bar}`); -window.setTimeout(`foo${bar}`); -window.window.setTimeout(`foo${bar}`); -global.global.setTimeout(`foo${bar}`); - -// string concatenation -setTimeout('foo' + bar); -setTimeout(foo + 'bar'); -setTimeout(`foo` + bar); -setTimeout(1 + ';' + 1); -window.setTimeout('foo' + bar); -window.setTimeout(foo + 'bar'); -window.setTimeout(`foo` + bar); -window.setTimeout(1 + ';' + 1); -window.window.setTimeout(1 + ';' + 1); -global.setTimeout('foo' + bar); -global.setTimeout(foo + 'bar'); -global.setTimeout(`foo` + bar); -global.setTimeout(1 + ';' + 1); -global.global.setTimeout(1 + ';' + 1); -globalThis.setTimeout('foo' + bar); - -// gives the correct node when dealing with nesting -setTimeout('foo' + (function() { - setTimeout(helper); - execScript('str'); - return 'bar'; -})()); - -window.setTimeout('foo' + (function() { - setTimeout(helper); - window.execScript('str'); - return 'bar'; -})()); - -global.setTimeout('foo' + (function() { - setTimeout(helper); - global.execScript('str'); - return 'bar'; -})()); - -// Optional chaining -window?.setTimeout('code', 0); -(window?.setTimeout)('code', 0); -``` - -## Compliant Code Examples -```typescript -setTimeout(); - -setTimeout; -setTimeout = foo; -window.setTimeout; -window.setTimeout = foo; -window['setTimeout']; -window['setTimeout'] = foo; -global.setTimeout; -global.setTimeout = foo; -global['setTimeout']; -global['setTimeout'] = foo; -globalThis['setTimeout'] = foo; - -window[`SetTimeOut`]('foo', 100); -global[`SetTimeOut`]('foo', 100); -global[`setTimeout${foo}`]('foo', 100); -global[`setTimeout${foo}`]('foo', 100); -globalThis[`setTimeout${foo}`]('foo', 100); - -// normal usage -setTimeout(function() { x = 1; }, 100); -setInterval(function() { x = 1; }, 100) -execScript(function() { x = 1; }, 100) -window.setTimeout(function() { x = 1; }, 100); -window.setInterval(function() { x = 1; }, 100); -window.execScript(function() { x = 1; }, 100); -window.setTimeout(foo, 100); -window.setInterval(foo, 100); -window.execScript(foo, 100); -global.setTimeout(function() { x = 1; }, 100); -global.setInterval(function() { x = 1; }, 100); -global.execScript(function() { x = 1; }, 100); -global.setTimeout(foo, 100); -global.setInterval(foo, 100); -global.execScript(foo, 100); -globalThis.setTimeout(foo, 100); - -// only checks on top-level statements or window.* -foo.setTimeout('hi') - -// identifiers are fine -setTimeout(foo, 10) -setInterval(1, 10) -execScript(2) - -// as are function expressions -setTimeout(function() {}, 10) - -// setInterval -foo.setInterval('hi') -setInterval(foo, 10) -setInterval(function() {}, 10) - -// execScript -foo.execScript('hi') -execScript(foo) -execScript(function() {}) - -// a binary plus on non-strings doesn't guarantee a string -// setTimeout(foo + bar, 10) - -// doesn't check anything but the first argument -setTimeout(foobar, 'buzz') -setTimeout(foobar, foo + 'bar') - -// only checks immediate subtrees of the argument -setTimeout(function() { return 'foobar'; }, 10) - -// https://github.com/eslint/eslint/issues/7821 -setTimeoutFooBar('Foo Bar') - -foo.window.setTimeout('foo', 100); -foo.global.setTimeout('foo', 100); -// var window; window.setTimeout('foo', 100); -// var global; global.setTimeout('foo', 100); -// function foo(window) { window.setTimeout('foo', 100); } -// function foo(global) { global.setTimeout('foo', 100); } -foo('', window.setTimeout); -foo('', global.setTimeout); -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md b/content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md deleted file mode 100644 index 378c9351911a9..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-inner-declarations.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-inner-declarations - language: TypeScript - severity: Warning -title: Avoid variable or function declaration in nested blocks ---- -## Metadata -**ID:** `typescript-best-practices/no-inner-declarations` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Function declarations in JavaScript are generally not block scoped. This rule prevents function declarations inside nested blocks like `if` statements. Move your declarations to the root of your program, body, or class. - -## Non-Compliant Code Examples -```typescript -if (test) { function doSomething() { } } -if (foo) var a; -if (foo) /* some comments */ var a; -if (foo){ function f(){ if(bar){ var a; } } } -if (foo) function f(){ if(bar) var a; } -if (foo) { var fn = function(){} } -if (foo) function f(){} -function bar() { if (foo) var a; } -if (foo){ var a; } -class C { method() { if(test) { var foo; } } } -class C { static { if (test) { function foo() {} } } } -class C { static { if (test) { var foo; } } } -class C { static { if (test) { if (anotherTest) { var foo; } } } } -``` - -## Compliant Code Examples -```typescript -function doSomething() { } -function doSomething() { function somethingElse() { } } -(function() { function doSomething() { } }()); -function decl() { var fn = function expr() { }; } -function decl(arg) { var fn; if (arg) { fn = function() { }; } } -var x = {doSomething() {function doSomethingElse() {}}} -function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } -function decl(arg) { var fn; if (arg) { fn = function expr() { }; } } -if (test) { let x = 1; } -if (test) { const x = 1; } -function doSomething() { while (test) { var foo; } } -var foo; -var foo = 42; -function doSomething() { var foo; } -(function() { var foo; }()); -foo(() => { function bar() { } }); -var fn = () => {var foo;} -var x = {doSomething() {var foo;}} -export var foo; -export function bar() {} -export default function baz() {} -exports.foo = () => {} -exports.foo = function(){} -module.exports = function foo(){} -class C { method() { function foo() {} } } -class C { method() { var x; } } -class C { static { function foo() {} } } -class C { static { var x; } } -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-iterator.md b/content/en/static_analysis/rules/typescript-best-practices/no-iterator.md deleted file mode 100644 index 036a57533274f..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-iterator.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-iterator - language: TypeScript - severity: Warning -title: Avoid the use of the __iterator__ property ---- -## Metadata -**ID:** `typescript-best-practices/no-iterator` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -The `__iterator__` property was exclusive to the SpiderMonkey engine. Avoid using it as other JavaScript engines do not implement it. - -## Non-Compliant Code Examples -```typescript -var a = test.__iterator__; -Foo.prototype.__iterator__ = function() {}; -var a = test['__iterator__']; -var a = test[`__iterator__`]; -test[`__iterator__`] = function () {}; -``` - -## Compliant Code Examples -```typescript -var a = test[__iterator__]; -var __iterator__ = null; -foo[`__iterator`] = null; -foo[`__iterator__ -`] = null; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md b/content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md deleted file mode 100644 index 1b84ebcec6404..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-loss-of-precision.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-loss-of-precision - language: TypeScript - severity: Error -title: Avoid numbers that lose precision ---- -## Metadata -**ID:** `typescript-best-practices/no-loss-of-precision` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -JavaScript uses double-precision, floating-point numbers in accordance with the [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754). This means numbers are only accurate until a certain amount of digits. Adding more digits will make the number lose precision, as the added digits will be lost in the conversion to the `Number` type, causing unexpected behavior. - -## Non-Compliant Code Examples -```typescript -var x = 9007199254740993 -var x = 9007199254740.993e3 -var x = 9.007199254740993e15 -var x = -9007199254740993 -var x = 900719.9254740994 -var x = -900719.9254740994 -var x = 900719925474099_3 -var x = 90_0719925_4740.9_93e3 -var x = 9.0_0719925_474099_3e15 -var x = -9_00719_9254_740993 -var x = 900_719.92_54740_994 -var x = -900_719.92_5474_0994 -var x = 5123000000000000000000000000001 -var x = -5123000000000000000000000000001 -var x = 1230000000000000000000000.0 -var x = 1.0000000000000000000000123var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 -var x = 2e999 -var x = .1230000000000000000000000 -var x = 0b100000000000000000000000000000000000000000000000000001 -var x = 0B100000000000000000000000000000000000000000000000000001 -var x = 0o400000000000000001 -var x = 0O400000000000000001 -var x = 0400000000000000001 -var x = 0x20000000000001 -var x = 0X20000000000001 -var x = 5123_00000000000000000000000000_1 -var x = -5_12300000000000000000000_0000001 -var x = 123_00000000000000000000_00.0_0 -var x = 1.0_00000000000000000_0000123 -var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 -var x = 2e9_99 -var x = .1_23000000000000_00000_0000_0 -var x = 0b1_0000000000000000000000000000000000000000000000000000_1 -var x = 0B10000000000_0000000000000000000000000000_000000000000001 -var x = 0o4_00000000000000_001 -var x = 0O4_0000000000000000_1 -var x = 0x2_0000000000001 -var x = 0X200000_0000000_1 -``` - -## Compliant Code Examples -```typescript -var x = 12345 -var x = 123.456 -var x = -123.456 -var x = -123456 -var x = 123e34 -var x = 123.0e34 -var x = 123e-34 -var x = -123e34 -var x = -123e-34 -var x = 12.3e34 -var x = 12.3e-34 -var x = -12.3e34 -var x = -12.3e-34 -var x = 12300000000000000000000000 -var x = -12300000000000000000000000 -var x = 0.00000000000000000000000123 -var x = -0.00000000000000000000000123 -var x = 9007199254740991 -var x = 0 -var x = 0.0 -var x = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000 -var x = -0 -var x = 123.0000000000000000000000 -var x = 0e5 -var x = 12_34_56 -var x = 12_3.4_56 -var x = -12_3.4_56 -var x = -12_34_56 -var x = 12_3e3_4 -var x = 123.0e3_4 -var x = 12_3e-3_4 -var x = 12_3.0e-3_4 -var x = -1_23e-3_4 -var x = -1_23.8e-3_4 -var x = 1_230000000_00000000_00000_000 -var x = -1_230000000_00000000_00000_000 -var x = 0.0_00_000000000_000000000_00123 -var x = -0.0_00_000000000_000000000_00123 -var x = 0e5_3 - -var x = 0b11111111111111111111111111111111111111111111111111111 -var x = 0b111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 -var x = 0B11111111111111111111111111111111111111111111111111111 -var x = 0B111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111 -var x = 0o377777777777777777 -var x = 0o3_77_777_777_777_777_777 -var x = 0O377777777777777777 - -var x = 0377777777777777777 -var x = 0x1FFFFFFFFFFFFF -var x = 0X1FFFFFFFFFFFFF -var x = true -var x = 'abc' -var x = '' -var x = null -var x = undefined -var x = {} -var x = ['a', 'b'] -var x = new Date() -var x = '9007199254740993' - -var x = 0x1FFF_FFFF_FFF_FFF -var x = 0X1_FFF_FFFF_FFF_FFF -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-namespace.md b/content/en/static_analysis/rules/typescript-best-practices/no-namespace.md deleted file mode 100644 index b29de7a2733ab..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-namespace.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-namespace - language: TypeScript - severity: Notice -title: Avoid TypeScript namespaces ---- -## Metadata -**ID:** `typescript-best-practices/no-namespace` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Namespaces should be avoided as an outdated feature of TypeScript. Use module syntax instead. - -## Non-Compliant Code Examples -```typescript -module foo {} -namespace foo {} -module foo {} -namespace foo {} -module foo {} -namespace foo {} -declare module foo {} -declare namespace foo {} -declare module foo {} -declare namespace foo {} -namespace foo {} -module foo {} -declare module foo {} -declare namespace foo {} -namespace Foo.Bar {} -namespace Foo.Bar { namespace Baz.Bas { interface X {} } } -namespace A { namespace B { declare namespace C {} } -namespace A { namespace B { export declare namespace C {} } } -namespace A { declare namespace B { namespace C {} } } -namespace A { export declare namespace B { namespace C {} } } -namespace A { export declare namespace B { declare namespace C {} } } -namespace A { export declare namespace B { export declare namespace C {} } } -namespace A { declare namespace B { export declare namespace C {} } } -namespace A { export namespace B { export declare namespace C {} } } -export namespace A { namespace B { declare namespace C {} } } -export namespace A { namespace B { export declare namespace C {} } } -export namespace A { declare namespace B { namespace C {} } } -export namespace A { export declare namespace B { namespace C {} } } -export namespace A { export declare namespace B { declare namespace C {} } } -export namespace A { export declare namespace B { export declare namespace C {} } } -export namespace A { declare namespace B { export declare namespace C {} } } -export namespace A { export namespace B { export declare namespace C {} } } -``` - -## Compliant Code Examples -```typescript -declare global {} -declare module 'foo' {} -declare module foo {} -declare namespace foo {} -declare global { namespace foo {} } -declare module foo { namespace bar {} } -declare global { namespace foo { namespace bar {} } } -declare namespace foo { namespace bar { namespace baz {} } } -export declare namespace foo { export namespace bar { namespace baz {} } } -namespace foo {} -module foo {} -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md b/content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md deleted file mode 100644 index a55d8adccaa00..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-non-null-optional-chain - language: TypeScript - severity: Warning -title: Avoid non-null assertions after an optional chain ---- -## Metadata -**ID:** `typescript-best-practices/no-non-null-optional-chain` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Using a non-null assertion after an optional chain expression indicates bad type safety. - -## Non-Compliant Code Examples -```typescript -foo?.bar!; -foo?.['bar']!; -foo?.bar()!; -foo.bar?.()!; -(foo?.bar)!.baz; -(foo?.bar)!().baz; -(foo?.bar)!; -(foo?.bar)!(); -(foo?.bar!); -(foo?.bar!)(); -``` - -## Compliant Code Examples -```typescript -foo.bar!; -foo.bar!.baz; -foo.bar!.baz(); -foo.bar()!; -foo.bar()!(); -foo.bar()!.baz; -foo?.bar; -foo?.bar(); -(foo?.bar).baz!; -(foo?.bar()).baz!; -foo?.bar!.baz; -foo?.bar!(); -foo?.['bar']!.baz; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-proto.md b/content/en/static_analysis/rules/typescript-best-practices/no-proto.md deleted file mode 100644 index 557185e061623..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-proto.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-proto - language: TypeScript - severity: Warning -title: Avoid the use of the __proto__ property ---- -## Metadata -**ID:** `typescript-best-practices/no-proto` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -The `__proto__` property has been deprecated as of ECMAScript 3.1. - -Use a suitable alternative to `__proto__` like `Object.getPrototypeOf` and `Object.setPrototypeOf` instead. - -## Non-Compliant Code Examples -```typescript -var a = test.__proto__; -var a = test['__proto__']; -var a = test[`__proto__`]; -test[`__proto__`] = function () {}; -``` - -## Compliant Code Examples -```typescript -var a = test[__proto__]; -var __proto__ = null; -foo[`__proto`] = null; -foo[`__proto__\n`] = null; -class C { #__proto__; foo() { this.#__proto__; } } -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-script-url.md b/content/en/static_analysis/rules/typescript-best-practices/no-script-url.md deleted file mode 100644 index 87e97ee1f0365..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-script-url.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-script-url - language: TypeScript - severity: Notice -title: Avoid using Javascript in URLs ---- -## Metadata -**ID:** `typescript-best-practices/no-script-url` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -JavaScript URLs are evaluated the same way `eval` is executed. This can lead to arbitrary code execution. - -## Non-Compliant Code Examples -```typescript -var a = 'javascript:void(0);'; -var a = 'javascript:'; -var a = `javascript:`; -var a = `JavaScript:`; -``` - -## Compliant Code Examples -```typescript -var a = 'Hello World!'; -var a = 10; -var url = 'xjavascript:' -var url = `xjavascript:` -var url = `${foo}javascript:` -var a = foo`javaScript:`; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md b/content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md deleted file mode 100644 index 95ec2d5306e6e..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-unnecessary-type-constraint - language: TypeScript - severity: Notice -title: Avoid unnecessary constraints on generic types ---- -## Metadata -**ID:** `typescript-best-practices/no-unnecessary-type-constraint` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -It is redundant to `extend` from `any` or `unknown`. - -## Non-Compliant Code Examples -```typescript -function data() {} -function data() {} -function data() {} -function data() {} -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -function data() {} -const data = () => {}; -const data = () => {}; -class Data {} -const Data = class {}; - -class Data { - member() {} -} - -const Data = class { - member() {} -}; - -interface Data {} -type Data = {}; -``` - -## Compliant Code Examples -```typescript -function data() {} -function data() {} -function data() {} -function data() {} -function data() {} -function data() {} - -type TODO = any; -function data() {} - -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -const data = () => {}; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md deleted file mode 100644 index 06b497d47c7b8..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-assignment.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-unsafe-assignment - language: TypeScript - severity: Warning -title: Avoid assigning a value with type any ---- -## Metadata -**ID:** `typescript-best-practices/no-unsafe-assignment` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -The `any` type in TypeScript is dangerously broad, leading to unexpected behavior. Using `any` should be avoided. - -## Non-Compliant Code Examples -```typescript -const x = 1 as any; -const x = 1 as any, -function foo(a = 1 as any) {} -class Foo { constructor(private a = 1 as any) {} } -class Foo { private a = 1 as any; } -const [x] = 1 as any; -const [x] = [] as any[]; - -// TS treats the assignment pattern weirdly in this case -[[[[x]]]] = [1 as any]; -const x = [...(1 as any)]; -const x = [...([] as any[])]; - -const x = { y: 1 as any }; -const x = { y: { z: 1 as any } }; -const x = { ...(1 as any) }; -; -``` - -## Compliant Code Examples -```typescript -const x = 1; -const x: number = 1; -const x = 1, y = 1; -let x; -let x = 1, y; -function foo(a = 1) {} -class Foo { constructor(private a = 1) {} } -class Foo { private a = 1; } -const x: Set = new Set(); -const x: Set = new Set(); -const [x] = [1]; -const [x, y] = [1, 2] as number[]; -const [x, ...y] = [1, 2, 3, 4, 5]; -const [x, ...y] = [1]; -const [{ ...x }] = [{ x: 1 }] as [{ x: any }]; -function foo(x = 1) {} -function foo([x] = [1]) {} -function foo([x, ...y] = [1, 2, 3, 4, 5]) {} -function foo([x, ...y] = [1]) {} -// this is not checked, because there's no annotation to compare it with -const x = new Set(); -const x = { y: 1 }; -const x = { y = 1 }; -const x = { y(){} }; -const x: { y: number } = { y: 1 }; -const x = [...[1, 2, 3]]; -const [{ [`x${1}`]: x }] = [{ [`x`]: 1 }] as [{ [`x`]: any }]; -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md deleted file mode 100644 index 723cdbf33a83f..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-best-practices/no-unsafe-declaration-merging - language: TypeScript - severity: Error -title: Avoid unsafe declaration merging ---- -## Metadata -**ID:** `typescript-best-practices/no-unsafe-declaration-merging` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Error Prone - -## Description -Do not merge class and interface declarations. The compiler won't check property initialization, which might lead to runtime errors. - -## Non-Compliant Code Examples -```typescript -interface Foo {} -class Foo {} -``` - -## Compliant Code Examples -```typescript -interface Foo {} -class Bar implements Foo {} - -namespace Baz {} -namespace Baz {} -enum Baz {} - -namespace Qux {} -function Qux() {} -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md b/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md deleted file mode 100644 index bf26ed59237f5..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-unsafe-negation.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-unsafe-negation - language: TypeScript - severity: Warning -title: Avoid negating the left operand of relational operators ---- -## Metadata -**ID:** `typescript-best-practices/no-unsafe-negation` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Negation of the left-hand side of an expression is often unintended. - -## Non-Compliant Code Examples -```typescript -!a in b -(!a in b) -!(a) in b -!a instanceof b -(!a instanceof b) -!(a) instanceof b -``` - -## Compliant Code Examples -```typescript -a in b -a in b === false -!(a in b); -(!a) in b -a instanceof b -a instanceof b === false; -!(a instanceof b); -(!a) instanceof b; - -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md b/content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md deleted file mode 100644 index 3dbd083914b25..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/no-var-requires.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/no-var-requires - language: TypeScript - severity: Warning -title: Avoid require statements ---- -## Metadata -**ID:** `typescript-best-practices/no-var-requires` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Use ESM instead of CommonJS imports. - -## Non-Compliant Code Examples -```typescript -var foo = require('foo'); -const foo = require('foo'); -let foo = require('foo'); -let foo = trick(require('foo')); -var foo = require?.('foo'); -const foo = require?.('foo'); -let foo = require?.('foo'); -let foo = trick(require?.('foo')); -let foo = trick?.(require('foo')); -const foo = require('./foo.json') as Foo; -const foo: Foo = require('./foo.json').default; - -// const foo = require('./foo.json'); - -// https://github.com/typescript-eslint/typescript-eslint/issues/3883 -// const configValidator = new Validator(require('./a.json')); -// configValidator.addSchema(require('./a.json')); -``` - -## Compliant Code Examples -```typescript -import foo = require('foo'); -require('foo'); -require?.('foo'); - -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/require-yield.md b/content/en/static_analysis/rules/typescript-best-practices/require-yield.md deleted file mode 100644 index 7a4f26d12bcb6..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/require-yield.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/require-yield - language: TypeScript - severity: Error -title: Require yield in generator functions ---- -## Metadata -**ID:** `typescript-best-practices/require-yield` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Best Practices - -## Description -Generator functions must yield at some point. Otherwise, use a normal function. - -## Non-Compliant Code Examples -```typescript -function* foo() { return 0; } -(function* foo() { return 0; })(); -var obj = { *foo() { return 0; } } -class A { *foo() { return 0; } } -function* foo() { function* bar() { yield 0; } } -function* foo() { function* bar() { return 0; } yield 0; } -``` - -## Compliant Code Examples -```typescript -function foo() { return 0; } -function* foo() { yield 0; } -function* foo() { } -(function* foo() { yield 0; })(); -(function* foo() { })(); -var obj = { *foo() { yield 0; } }; -var obj = { *foo() { } }; -class A { *foo() { yield 0; } }; -class A { *foo() { } } -``` diff --git a/content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md b/content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md deleted file mode 100644 index b48da0f6336c6..0000000000000 --- a/content/en/static_analysis/rules/typescript-best-practices/triple-slash-reference.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-best-practices/triple-slash-reference - language: TypeScript - severity: Notice -title: Avoid triple slash in favor of ES6 import declarations ---- -## Metadata -**ID:** `typescript-best-practices/triple-slash-reference` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Use ESM instead of references. - -## Non-Compliant Code Examples -```typescript -/// -/// -/// -``` - -## Compliant Code Examples -```typescript -import * as foo from 'foo'; -import * as bar from 'bar'; -import * as baz from 'baz'; -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md b/content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md deleted file mode 100644 index f83ce4271fd99..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/event-check-origin.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/event-check-origin - language: TypeScript - severity: Warning -title: Check origin of events ---- -## Metadata -**ID:** `typescript-browser-security/event-check-origin` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Not checking the rule origin can lead to XSS attacks. Always check the event origin. - -#### Learn More - - - [XSS and CSS Cheat Sheet from OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) - -## Non-Compliant Code Examples -```typescript -window.addEventListener('message', (event: Event) => { - processing(); -}) -``` - -## Compliant Code Examples -```typescript -window.addEventListener('message', (event: Event) => { - if (event.origin != 'https://app.domain.tld') { - throw new Error('invalid origin') - } - - processing(); -}) -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md b/content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md deleted file mode 100644 index 1c16b8eb4ae3d..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/inner-outer-html.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/inner-outer-html - language: TypeScript - severity: Warning -title: Do not modify innerHTML or outerHTML ---- -## Metadata -**ID:** `typescript-browser-security/inner-outer-html` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Properties like `innerHTML` and `outerHTML` should not be modified directly unless such modifications are clearly reviewed. Modifying `innerHTML` or `outerHTML` using user inputs that has not been validated can lead to XSS injection. - -#### Learn More - - - [Why InnerHTML Is a Bad Idea and How to Avoid It?](https://www.dhairyashah.dev/posts/why-innerhtml-is-a-bad-idea-and-how-to-avoid-it/) - - [CWE-79 - Improper Neutralization of Input During Web Page Generation](https://cwe.mitre.org/data/definitions/79.html) - - -## Non-Compliant Code Examples -```typescript -function nonCompliant(argument) { - const content = '
' + argument + '
'; - document.write(content); -} -``` - -```typescript -function nonCompliant(myArgument) { - document.body.outerHTML = myArgument; -} -``` - -```typescript -if (typeof(SERVER_DOMAIN) === 'undefined') { - window.location.replace("/unconfigured.html"); -} - -const RECEIVE_URL = SERVER_DOMAIN + "/challenge_scoreboard.html" + "?origin=" + get_domain(); - -var window_ref = null; - -document.getElementById("username").focus(); - -function store_username() { - var username; - var username_obj; - - username_obj = document.getElementById("username"); - username = username_obj.value - - var welcome; - welcome = document.getElementById("welcome"); - welcome.innerHTML = "Welcome " + html_encode (username); - - var set_username; - set_username = document.getElementById("set_username"); - set_username.style.display="none"; - - var game; - game = document.getElementById("game"); - game.style.display="inline"; - - start_game(); - // have to do time out so the window can open - setTimeout (function () {send_username(username);}, 1000); - - return false; -} - -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md b/content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md deleted file mode 100644 index 01f534915eb50..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/insecure-websocket.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/insecure-websocket - language: TypeScript - severity: Warning -title: Websockets must use SSL connections ---- -## Metadata -**ID:** `typescript-browser-security/insecure-websocket` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always use secure websocket communication. When using websocket, use addresses that are SSL-enabled. - - - -## Non-Compliant Code Examples -```typescript -const client = new WebSocket('ws://app.domain.tld') -``` - -## Compliant Code Examples -```typescript -const client = new WebSocket('wss://app.domain.tld') -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md b/content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md deleted file mode 100644 index 4215b600a5a1c..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/local-storage-sensitive-data - language: TypeScript - severity: Warning -title: Do not store sensitive data to local storage ---- -## Metadata -**ID:** `typescript-browser-security/local-storage-sensitive-data` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not store sensitive data in `localStorage` and keep the data safe from any malicious software that could read this data. - -#### Learn More - - [CWE-312 - Cleartext Storage of Sensitive Information](https://cwe.mitre.org/data/definitions/312.html) - -## Non-Compliant Code Examples -```typescript -localStorage.setItem('user', email) - -localStorage.setItem('user', user.email) -``` - -## Compliant Code Examples -```typescript -localStorage.setItem('user', uuid) - -localStorage.setItem('user', user.id) -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md b/content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md deleted file mode 100644 index 37578e2cbe5fb..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/manual-sanitization.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/manual-sanitization - language: TypeScript - severity: Warning -title: Avoid manual sanitization of inputs ---- -## Metadata -**ID:** `typescript-browser-security/manual-sanitization` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Never sanitize HTML input manually. This can lead to vulnerabilities. Use dedicated modules such as `sanitize-html` to sanitize user inputs. - -## Non-Compliant Code Examples -```typescript -const sanitizedInput = input - .replaceAll('<', '<') - .replaceAll('>', '>'); -const html = `${sanitizedInput}`; - -const sanitizedInput2 = input - .replaceAll('bla', '<') - .replaceAll('foo', '>'); - -const sanitizedInput3 = input - .replaceAll('<', '<') - .replaceAll('>', 'gt;'); -``` - -## Compliant Code Examples -```typescript -import sanitizeHtml from 'sanitize-html'; - -const html = sanitizeHtml(`${input}`); -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md b/content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md deleted file mode 100644 index 33c8cadf86a08..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/postmessage-permissive-origin - language: TypeScript - severity: Warning -title: Specify origin in postMessage ---- -## Metadata -**ID:** `typescript-browser-security/postmessage-permissive-origin` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always specify the origin of the message for security reasons and to avoid spoofing attacks. Always specify an exact target origin, not `*`, when you use `postMessage` to send data to other windows. - -#### Learn More - - - [window.postMessage documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) - -## Non-Compliant Code Examples -```typescript -window.postMessage(message, '*') - -``` - -## Compliant Code Examples -```typescript -window.postMessage(message, 'https://app.domain.tld') - -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md b/content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md deleted file mode 100644 index 1a8b13ef75f22..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/react-dangerously-inner-html - language: TypeScript - severity: Warning -title: Do not inject unsanitized HTML ---- -## Metadata -**ID:** `typescript-browser-security/react-dangerously-inner-html` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always sanitize HTML data before injecting it in the DOM. Use libraries such as [DOMPurify](https://github.com/cure53/DOMPurify) before using it. - -## Non-Compliant Code Examples -```typescript -const App = () => { - const data = `lorem ipsum`; - - return ( -
-
- ); -} -``` - -## Compliant Code Examples -```typescript -const App = () => { - const data = `lorem ipsum`; - - return ( -
- ); -} -``` diff --git a/content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md b/content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md deleted file mode 100644 index e7fe811dea61a..0000000000000 --- a/content/en/static_analysis/rules/typescript-browser-security/regexp-non-literal.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-browser-security/regexp-non-literal - language: TypeScript - severity: Warning -title: Do not use variable for regular expressions ---- -## Metadata -**ID:** `typescript-browser-security/regexp-non-literal` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Regular expressions should not use a variable as an argument since an attacker may inject values and cause a regular expression denial of service (ReDoS). Instead, use a library like [recheck](https://www.npmjs.com/package/recheck) to check that no DoS can be triggered by regular expression. - -## Non-Compliant Code Examples -```typescript -const foo = new RegExp(req.something); -const bar = new RegExp(variable); -``` - -## Compliant Code Examples -```typescript -const foo = new RegExp(`^\\d+-${topicId}$`); -const foo = new RegExp(/something/); -const foo = new RegExp("weofiwje"); -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/array-type.md b/content/en/static_analysis/rules/typescript-code-style/array-type.md deleted file mode 100644 index 7d01ecfdc5553..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/array-type.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/array-type - language: TypeScript - severity: Notice -title: Require consistently using either T[] or Array for arrays ---- -## Metadata -**ID:** `typescript-code-style/array-type` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Chose between: `T[]` and `Array`. These types are equivalent and it should be consistent across the code base. - -## Non-Compliant Code Examples -```typescript -// Base cases from https://github.com/typescript-eslint/typescript-eslint/issues/2323#issuecomment-663977655 -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: ReadonlyArray = []; -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: ReadonlyArray = []; -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: Array = []; -let a: Array = []; -let a: Array = []; -let a: Array = []; -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: ReadonlyArray = []; -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: ReadonlyArray = []; -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: Array = []; -let a: Array = []; -let a: ReadonlyArray = []; -let a: ReadonlyArray = []; - -// End of base cases -type Arr = Array; -let a: Array<{ foo: Array }> = []; -let a: Array<{ foo: Foo | Array }> = []; -let ya = [[1, '2']] as Array<[number, string]>; -// Ignore user-defined aliases -let yyyy: Arr>>> = [[[['2']]]]; -interface ArrayClass { - foo: T[]; - bar: T[]; - baz: Arr; - xyz: this[]; -} -function barFunction(bar: Array>) { - return bar.map(e => e.bar); -} -let barVar: Array<(c: number) => number> = []; -type barUnion = Array; -type barIntersection = Array; -let w: Array> = [['baz']]; -type Unwrap = T extends Array ? E : T; -``` - -## Compliant Code Examples -```typescript -// Base cases from https://github.com/typescript-eslint/typescript-eslint/issues/2323#issuecomment-663977655 -let a: number[] = []; -let a: (string | number)[] = []; -let a: readonly number[] = []; -let a: readonly (string | number)[] = []; -let a: number[] = []; -let a: (string | number)[] = []; -let a: readonly number[] = []; -let a: readonly (string | number)[] = []; -let a: number[] = []; -let a: (string | number)[] = []; -let a: readonly number[] = []; -let a: number[] = []; -let a: (string | number)[] = []; -let a: number[] = []; -let a: readonly number[] = []; -let a: number[] = []; -let a: readonly number[] = []; -let a: readonly (string | number)[] = []; -let a: number[] = []; -let a: readonly number[] = []; -let a: readonly number[] = []; -let a: readonly (string | number)[] = []; -let a: readonly bigint[] = []; - -// End of base cases -let a = new Array(); -let a: { foo: Bar[] }[] = []; -let yy: number[][] = [[4, 5], [6]]; -function bazFunction(baz: Arr>) { return baz.map(e => e.baz); } -namespace fooName { type BarType = { bar: string }; type BazType = Arr; } -interface FooInterface { '.bar': { baz: string[] }; } -let yy: number[][] = [[4, 5], [6]]; -let ya = [[1, '2']] as [number, string][]; -function barFunction(bar: ArrayClass[]) { return bar.map(e => e.bar); } -function bazFunction(baz: Arr>) { return baz.map(e => e.baz); } -let barVar: ((c: number) => number)[]; -type barUnion = (string | number | boolean)[]; -type barIntersection = (string & number)[]; -interface FooInterface { '.bar': { baz: string[] }; } -type Unwrap = T extends (infer E)[] ? E : T; -function bazFunction(baz: Arr>) { return baz.map(e => e.baz); } - -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/assignment-name.md b/content/en/static_analysis/rules/typescript-code-style/assignment-name.md deleted file mode 100644 index ccaa1a75125b4..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/assignment-name.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/assignment-name - language: TypeScript - severity: Notice -title: Assigment name should use camelCase ---- -## Metadata -**ID:** `typescript-code-style/assignment-name` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that variables and properties names use `camelCase` and not `snake_case` or `PascalCase`. - -## Non-Compliant Code Examples -```typescript -var a = { - MyProp: "should be camelCase", - #Priv: 2, -}; -const my_var = {}; -let FooBar = {}; -const { a_b, ...Bla } = c; -const [a_b, ...Bla] = c; - -``` - -## Compliant Code Examples -```typescript -/* The BenefitsDAO must be constructed with a connected database object */ -function BenefitsDAO(db) { - - "use strict"; - - /* If this constructor is called without the "new" operator, "this" points - * to the global object. Log a warning and call it correctly. */ - if (false === (this instanceof BenefitsDAO)) { - console.log("Warning: BenefitsDAO constructor called without 'new' operator"); - return new BenefitsDAO(db); - } - - const usersCol = db.collection("users"); - const UsersCol = db.collection("users"); - const {foo_bar} = bla; - this.getAllNonAdminUsers = callback => { - usersCol.find({ - "isAdmin": { - $ne: true - } - }).toArray((err, users) => callback(null, users)); - }; - - this.updateBenefits = (userId, startDate, callback) => { - usersCol.update({ - _id: parseInt(userId) - }, { - $set: { - benefitStartDate: startDate - } - }, - (err, result) => { - if (!err) { - console.log("Updated benefits"); - return callback(null, result); - } - - return callback(err, null); - } - ); - }; -} - -module.exports = { BenefitsDAO }; -``` - -```typescript -const a = { myProp: "", #priv: 1 }; -const myVar = {}; -const { a } = c; -const { a, ...b } = c; -const [a, ...b] = c; -process.env.PCKG_OS_NAME; -const md5 = 'foo'; -const PCKG_OS_NAME = 'foo'; -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md b/content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md deleted file mode 100644 index b8796dbdcceac..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/ban-ts-comment.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/ban-ts-comment - language: TypeScript - severity: Notice -title: Avoid @ts- comments ---- -## Metadata -**ID:** `typescript-code-style/ban-ts-comment` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Correct your types instead of disabling TypeScript. - -## Non-Compliant Code Examples -```typescript -// @ts-expect-error -// @ts-ignore -// @ts-nocheck -// @ts-check -``` - -## Compliant Code Examples -```typescript -// just a comment containing @ts-expect-error somewhere -// just a comment containing @ts-ignore somewhere -// just a comment containing @ts-nocheck somewhere -// just a comment containing @ts-check somewhere - -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md b/content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md deleted file mode 100644 index fa6aa7c643754..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/ban-tslint-comment.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-code-style/ban-tslint-comment - language: TypeScript - severity: Warning -title: Avoid using TSLint comments ---- -## Metadata -**ID:** `typescript-code-style/ban-tslint-comment` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Do not disable TypeScript checks. - -## Non-Compliant Code Examples -```typescript -/* tslint:disable */ -/* tslint:enable */ -/* tslint:disable:rule1 rule2 rule3... */ -/* tslint:enable:rule1 rule2 rule3... */ -// tslint:disable-next-line -someCode(); // tslint:disable-line -// tslint:disable-next-line:rule1 rule2 rule3... -``` - -## Compliant Code Examples -```typescript -// This is a comment that just happens to mention tslint -/* This is a multiline comment that just happens to mention tslint */ -someCode(); // This is a comment that just happens to mention tslint -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/class-name.md b/content/en/static_analysis/rules/typescript-code-style/class-name.md deleted file mode 100644 index 630cca82b39f0..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/class-name.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/class-name - language: TypeScript - severity: Warning -title: Class name should be PascalCase ---- -## Metadata -**ID:** `typescript-code-style/class-name` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Code Style - -## Description -Class names should be `PascalCase` and not `camelCase` or `snake_case`. - -## Non-Compliant Code Examples -```typescript -class _runtimeMetricsStatus {} -class runtimeMetricsStatus {} -``` - -## Compliant Code Examples -```typescript -class MyClass {} -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/eqeqeq.md b/content/en/static_analysis/rules/typescript-code-style/eqeqeq.md deleted file mode 100644 index f926e70804e57..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/eqeqeq.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/eqeqeq - language: TypeScript - severity: Notice -title: Enforce the use of === and !== ---- -## Metadata -**ID:** `typescript-code-style/eqeqeq` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -In JavaScript, `==` and `!=` comparisons do type coercion, which can be confusing and may introduce potential errors. Use the type-safe equality operators `===` and `!==` instead. - -## Non-Compliant Code Examples -```typescript -a == b -a != b -typeof a == 'number' -typeof a == 'number' -'string' != typeof a -true == true -2 == 3 -2 == 3 -'hello' != 'world' -'hello' != 'world' -a == null -a == null -null != a -true == 1 -0 != '1' -'wee' == /wee/ -typeof a == 'number' -'string' != typeof a -'hello' != 'world' -2 == 3 -true == true -true == null -true != null -null == null -null != null -a -== -b -(a) == b -(a) != b -a == (b) -a != (b) -(a) == (b) -(a == b) == (c) -(a != b) != (c) -a == b; -a!=b; -(a + b) == c; -(a + b) != c; -((1) ) == (2); - -``` - -## Compliant Code Examples -```typescript -a === b -a !== b -a === b -a !== null -a === null -a !== null -null === null -null !== null - -// https://github.com/eslint/eslint/issues/8020 -foo === /abc/u - -// bigint -foo === 1n -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/func-name-matching.md b/content/en/static_analysis/rules/typescript-code-style/func-name-matching.md deleted file mode 100644 index ddd4947767bc7..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/func-name-matching.md +++ /dev/null @@ -1,195 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/func-name-matching - language: TypeScript - severity: Notice -title: Function names must match the name of the assignation ---- -## Metadata -**ID:** `typescript-code-style/func-name-matching` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Use the same name between your function declaration and the variable or property to which it is assigned. - -## Non-Compliant Code Examples -```typescript -let foo = function bar() {}; -let foo = function bar() {}; -foo = function bar() {}; -foo &&= function bar() {}; -obj.foo ||= function bar() {}; -obj['foo'] ??= function bar() {}; -obj.foo = function bar() {}; -obj.bar.foo = function bar() {}; -obj['foo'] = function bar() {}; -let obj = {foo: function bar() {}}; -let obj = {'foo': function bar() {}}; -({['foo']: function bar() {}}); -// NOT SUPPORTED -// module.exports = function foo(name) {}; -// module.exports = function foo(name) {}; -// module.exports = function exports(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function exports(name) {}; -// Object.defineProperty(foo, 'bar', { value: function baz() {} }); -// Object.defineProperties(foo, { bar: { value: function baz() {} } }); -// Object.create(proto, { bar: { value: function baz() {} } }); -// var obj = { value: function foo(name) {} }; -// Object.defineProperty(foo, 'bar', { value: function bar() {} }); -// Object.defineProperties(foo, { bar: { value: function bar() {} } }); -// Object.create(proto, { bar: { value: function bar() {} } }); -// Reflect.defineProperty(foo, 'bar', { value: function baz() {} }); -// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }); -foo({ value: function bar() {} }); -(obj?.aaa).foo = function bar() {}; -// Object?.defineProperty(foo, 'bar', { value: function baz() {} }); -// (Object?.defineProperty)(foo, 'bar', { value: function baz() {} }); -// Object?.defineProperty(foo, 'bar', { value: function bar() {} }); -// (Object?.defineProperty)(foo, 'bar', { value: function bar() {} }); -// Object?.defineProperties(foo, { bar: { value: function baz() {} } }); -// (Object?.defineProperties)(foo, { bar: { value: function baz() {} } }); -// Object?.defineProperties(foo, { bar: { value: function bar() {} } }); -// (Object?.defineProperties)(foo, { bar: { value: function bar() {} } }); -class C { x = function y() {}; } -class C { 'x' = function y() {}; } -class C { ['x'] = function y() {}; } -class C { static x = function y() {}; } -(class { x = function y() {}; }) -var obj = { '\u1885': function foo() {} }; - -``` - -## Compliant Code Examples -```typescript -var foo; -var foo = function foo() {}; -var foo = function foo() {}; -var foo = function() {} -var foo = () => {} -foo = function foo() {}; -foo = function foo() {}; -foo &&= function foo() {}; -obj.foo ||= function foo() {}; -obj['foo'] ??= function foo() {}; -obj.foo = function foo() {}; -obj.foo = function foo() {}; -obj.foo = function() {}; -obj.foo = function() {}; -obj.bar.foo = function foo() {}; -obj.bar.foo = function foo() {}; -obj['foo'] = function foo() {}; -obj['foo'] = function foo() {}; -// This are not equal not sure why eslint skips them -// obj['foo//bar'] = function foo() {}; -// obj['foo//bar'] = function foo() {}; -// obj['foo//bar'] = function foo() {}; -obj[foo] = function bar() {}; -obj[foo] = function bar() {}; -var obj = {foo: function foo() {}}; -var obj = {foo: function foo() {}}; -var obj = {'foo': function foo() {}}; -var obj = {'foo': function foo() {}}; -var obj = {foo: function() {}}; -var obj = {foo: function() {}}; -var obj = {foo: function() {}}; -var obj = {[foo]: function bar() {}} -var obj = {['x' + 2]: function bar() {}}; -obj['x' + 2] = function bar(){}; -var [ bar ] = [ function bar(){} ]; -function a(foo = function bar() {}) {} -// NOT SUPPORTED -// module.exports = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module.exports = function foo(name) {}; -// module.exports = function foo(name) {}; -// module.exports = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function foo(name) {}; -// module['exports'] = function foo(name) {}; -({['foo']: function foo() {}}) -({['foo']: function foo() {}}) -({[foo]: function bar() {}}) -({[null]: function foo() {}}) -({[1]: function foo() {}}) -({[true]: function foo() {}}) -({[`x`]: function foo() {}}) -({[/abc/]: function foo() {}}) -({[[1, 2, 3]]: function foo() {}}) -({[{x: 1}]: function foo() {}}) -[] = function foo() {} -({} = function foo() {}) -[a] = function foo() {} -({a} = function foo() {}) -var [] = function foo() {} -var {} = function foo() {} -var [a] = function foo() {} -var {a} = function foo() {} -({ value: function value() {} }) -obj.foo = function foo() {}; -obj.bar.foo = function foo() {}; -var obj = {foo: function foo() {}}; -var obj = {foo: function() {}}; -var obj = { value: function value() {} } -// NOT SUPPORTED -// Object.defineProperty(foo, 'bar', { value: function bar() {} }) -// Object.defineProperties(foo, { bar: { value: function bar() {} } }) -// Object.create(proto, { bar: { value: function bar() {} } }) -// Object.defineProperty(foo, 'b' + 'ar', { value: function bar() {} }) -// Object.defineProperties(foo, { ['bar']: { value: function bar() {} } }) -// Object.create(proto, { ['bar']: { value: function bar() {} } }) -// Object.defineProperty(foo, 'bar', { value() {} }) -// Object.defineProperties(foo, { bar: { value() {} } }) -// Object.create(proto, { bar: { value() {} } }) -// Reflect.defineProperty(foo, 'bar', { value: function bar() {} }) -// Reflect.defineProperty(foo, 'b' + 'ar', { value: function baz() {} }) -// Reflect.defineProperty(foo, 'bar', { value() {} }) -foo({ value: function value() {} }) -class C { x = function () {}; } -class C { x = function () {}; } -class C { 'x' = function () {}; } -class C { #x = function () {}; } -class C { #x = function () {}; } -class C { [x] = function () {}; } -class C { [x] = function () {}; } -class C { ['x'] = function () {}; } -class C { x = function x() {}; } -class C { 'x' = function x() {}; } -class C { #x = function x() {}; } -class C { #x = function x() {}; } -class C { #x = function y() {}; } -class C { #x = function y() {}; } -class C { [x] = function x() {}; } -class C { [x] = function x() {}; } -class C { [x] = function y() {}; } -class C { [x] = function y() {}; } -class C { ['x'] = function x() {}; } -class C { 1 = function x0() {}; } -class C { 1 = function x1() {}; } -class C { [1] = function x0() {}; } -class C { [1] = function x1() {}; } -class C { [f()] = function g() {}; } -class C { [f()] = function f() {}; } -class C { static x = function x() {}; } -class C { x = (function y() {})(); } -class C { x = (function x() {})(); } -(class { x = function x() {}; }) -class C { #x; foo() { this.#x = function x() {}; } } -class C { #x; foo() { this.#x = function x() {}; } } -class C { #x; foo() { this.#x = function y() {}; } } -class C { #x; foo() { this.#x = function y() {}; } } -class C { #x; foo() { a.b.#x = function x() {}; } } -class C { #x; foo() { a.b.#x = function x() {}; } } -class C { #x; foo() { a.b.#x = function y() {}; } } -class C { #x; foo() { a.b.#x = function y() {}; } } -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/func-names.md b/content/en/static_analysis/rules/typescript-code-style/func-names.md deleted file mode 100644 index 0bd5b0759b5fc..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/func-names.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/func-names - language: TypeScript - severity: Notice -title: Enforce named function expressions ---- -## Metadata -**ID:** `typescript-code-style/func-names` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -It is easier to debug your application code when you avoid anonymous functions so that the stack trace can show you meaningful error messages. This rule enforces all your function to be consistently declared with a name. - -## Non-Compliant Code Examples -```typescript -Foo.prototype.bar = function() {}; -(function(){}()) -f(function(){}) -var a = new Date(function() {}); -var test = function(d, e, f) {}; -new function() {} -Foo.prototype.bar = function() {}; -(function(){}()) -f(function(){}) -var a = new Date(function() {}); -new function() {} -var {foo} = function(){}; -({ a: obj.prop = function(){} } = foo); -[obj.prop = function(){}] = foo; -var { a: [b] = function(){} } = foo; -function foo({ a } = function(){}) {}; -export default function() {} -export default function() {} -export default (function(){}); -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -(function*() {}()) -var foo = bar(function *() {}); -(function*() {}()) -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -var foo = bar(function *() {}); -var foo = function*() {}; -(function*() {}()) -class C { foo = function() {} } -class C { [foo] = function() {} } -class C { #foo = function() {} } -``` - -## Compliant Code Examples -```typescript -Foo.prototype.bar = function bar(){}; -Foo.prototype.bar = () => {}; -function foo(){} -function test(d, e, f) {} -new function bar(){} -exports = { get foo() { return 1; }, set bar(val) { return val; } }; -({ foo() { return 1; } }); -class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} -function foo() {} -var a = function foo() {}; -class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} -({ foo() {} }); -function foo() {} -var a = function foo() { foo(); }; -class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}} -({ foo() {} }); -export default function foo() {} -export default function foo() {} -export default function foo() {} -var foo = bar(function *baz() {}); -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/function-naming.md b/content/en/static_analysis/rules/typescript-code-style/function-naming.md deleted file mode 100644 index be79541677604..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/function-naming.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/function-naming - language: TypeScript - severity: Notice -title: Function name should use camelCase or PascalCase ---- -## Metadata -**ID:** `typescript-code-style/function-naming` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that the function uses `camelCase` or `PascalCase` in case it is an `Object`. Generator functions should always be `camelCase`. - -## Non-Compliant Code Examples -```typescript -function My_Class() {} -function get_value() {} -function* GetValue() {} -function *get_value() {} -``` - -## Compliant Code Examples -```typescript -function MyClass() {} -function getValue() {} -function* getValue() {} -function *getValue() {} -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/max-class-lines.md b/content/en/static_analysis/rules/typescript-code-style/max-class-lines.md deleted file mode 100644 index 93dca19089094..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/max-class-lines.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/max-class-lines - language: TypeScript - severity: Warning -title: Classes must be less than 100 lines ---- -## Metadata -**ID:** `typescript-code-style/max-class-lines` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Code Style - -## Description -A class must stay short (less than 100 lines) to be easy to understand. If your class or function is more than 100 lines, you should refactor your code and ensure that your class is less than 100 lines. - -## Non-Compliant Code Examples -```typescript -class DummyClass { - constructor() { - this.name = "John"; - this.age = 30; - this.email = "john@example.com"; - this.address = "123 Main St"; - this.phone = "555-1234"; - this.salary = 50000; - this.skills = ["JavaScript", "HTML", "CSS"]; - this.projects = [ - { name: "Project 1", duration: 6 }, - { name: "Project 2", duration: 4 }, - { name: "Project 3", duration: 8 } - ]; - this.status = "active"; - - // Initialize more properties... - // ... - // ... - } - - sayHello() { - console.log(`Hello, my name is ${this.name}.`); - } - - calculateSalary() { - let total = this.salary; - for (let project of this.projects) { - total += project.duration * 1000; - } - return total; - } - - updateEmail(newEmail) { - if (newEmail.includes("@")) { - this.email = newEmail; - console.log("Email updated successfully."); - } else { - console.log("Invalid email format."); - } - } - - addSkill(skill) { - this.skills.push(skill); - console.log("Skill added."); - } - - removeSkill(skill) { - const index = this.skills.indexOf(skill); - if (index !== -1) { - this.skills.splice(index, 1); - console.log("Skill removed."); - } else { - console.log("Skill not found."); - } - } - - promote() { - if (this.status === "active") { - this.salary *= 1.1; - console.log("Promoted successfully."); - } else { - console.log("Cannot promote an inactive employee."); - } - } - - resign() { - if (this.status === "active") { - this.status = "inactive"; - console.log("Resigned successfully."); - } else { - console.log("Already inactive."); - } - } - - // More methods... - // ... - // ... - - // Long method 1 - longMethod1() { - // Implementation goes here... - // ... - // ... - } - - // Long method 2 - longMethod2() { - // Implementation goes here... - // ... - // ... - } - - // Long method 3 - longMethod3() { - // Implementation goes here... - // ... - // ... - } - - // Long method 4 - longMethod4() { - // Implementation goes here... - // ... - // ... - } - - // Long method 5 - longMethod5() { - // Implementation goes here... - // ... - // ... - } - - // More long methods... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final method - finalMethod() { - // Implementation goes here... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - } -} - -``` - -## Compliant Code Examples -```typescript -class DummyClass { - constructor() { - this.name = "John"; - this.age = 30; - this.email = "john@example.com"; - this.address = "123 Main St"; - this.phone = "555-1234"; - this.salary = 50000; - this.skills = ["JavaScript", "HTML", "CSS"]; - this.projects = [ - { name: "Project 1", duration: 6 }, - { name: "Project 2", duration: 4 }, - { name: "Project 3", duration: 8 } - ]; - this.status = "active"; - } - - sayHello() { - console.log(`Hello, my name is ${this.name}.`); - } - - calculateSalary() { - let total = this.salary; - for (let project of this.projects) { - total += project.duration * 1000; - } - return total; - } -} - -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/max-function-lines.md b/content/en/static_analysis/rules/typescript-code-style/max-function-lines.md deleted file mode 100644 index e0da01747fdaa..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/max-function-lines.md +++ /dev/null @@ -1,952 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/max-function-lines - language: TypeScript - severity: Warning -title: Functions must be less than 200 lines ---- -## Metadata -**ID:** `typescript-code-style/max-function-lines` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Code Style - -## Description -This rule ensures that a function is not too long. A function should be less than 200 lines, or it will be hard to understand. - -## Non-Compliant Code Examples -```typescript -function dummyFunction() { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; -} - -() => { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; -} - -const dummyFunction = function() { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; -} - -class A { - dummyFunction() { - var x = 0; - var y = 1; - var z = 2; - var arr = [1, 2, 3, 4, 5]; - var obj = { name: "John", age: 30 }; - - // Start of dummy code - for (var i = 0; i < 10; i++) { - x += i; - y *= i; - z -= i; - - if (x > y && y < z) { - x--; - z++; - } else { - y++; - } - } - - if (x > 100) { - arr.push(6); - } else if (x < 0) { - arr.pop(); - } else { - arr.splice(2, 1, 7); - } - - for (var j = 0; j < arr.length; j++) { - if (arr[j] % 2 === 0) { - arr[j] *= 2; - } else { - arr[j] += 2; - } - } - - var sum = 0; - arr.forEach(function(num) { - sum += num; - }); - - if (sum > 20) { - obj.name = "Jane"; - obj.age = 25; - } else { - obj.name = "Alice"; - obj.age = 40; - } - - // End of dummy code - - // More dummy code... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - // ... - - // Final dummy code - var result = "Result: "; - if (obj.age < 30) { - result += "Young "; - } else if (obj.age > 30) { - result += "Old "; - } else { - result += "Middle-aged "; - } - - result += obj.name; - - return result; - } -} -``` - -## Compliant Code Examples -```typescript -function myTest() { - // less than 200 lines -} - -() => { - // less than 200 lines -} - -class A { - foo() { - // less than 200 lines - } -} -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/max-params.md b/content/en/static_analysis/rules/typescript-code-style/max-params.md deleted file mode 100644 index 08877f119d92b..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/max-params.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/max-params - language: TypeScript - severity: Notice -title: Enforce a maximum number of parameters in a function ---- -## Metadata -**ID:** `typescript-code-style/max-params` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Having too many parameters can make your code hard to read. The parameters must be used in appropriate order. Forgetting the order of parameters can cause mistakes. - -Too many parameters is a code smell. You should refactor your code in smaller reusable bits. While it may be valid to require more than four parameters, you should use object destructuring. - -## Non-Compliant Code Examples -```typescript -function test(a, b, c, d) {} -var test = function(a, b, c, d, e) {}; -var test = (a, b, c, d) => {}; -(function(a, b, c, d) {}); - -// object property options -function test(a, b, c, d) {} -``` - -## Compliant Code Examples -```typescript -function test(d, e, f) {} -var test = function(a, b, c) {}; -var test = (a, b, c) => {}; -var test = function test(a, b, c) {}; - -// object property options -var test = function(a, b, c) {}; -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/method-name.md b/content/en/static_analysis/rules/typescript-code-style/method-name.md deleted file mode 100644 index 985954959526a..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/method-name.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/method-name - language: TypeScript - severity: Notice -title: Method name should use camelCase ---- -## Metadata -**ID:** `typescript-code-style/method-name` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that method names use `camelCase` and not `snake_case` or `PascalCase`. - -## Non-Compliant Code Examples -```typescript -const a = { GetValue() {} } -class A { set_value() {} } -class A { *set_value() {} } -class A { #set_value() {} } -class A { #SetValue() {} } -``` - -## Compliant Code Examples -```typescript -const a = { getValue() {} } -class A { setValue() {} } -class A { #fooBla() {} } -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md b/content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md deleted file mode 100644 index c128bee9731bf..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-array-constructor.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-code-style/no-array-constructor - language: TypeScript - severity: Warning -title: Avoid Array constructors ---- -## Metadata -**ID:** `typescript-code-style/no-array-constructor` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Array literal notation cannot be redefined. It is preferred over the Array constructor. - -The Array constructor is a common source of errors as it might behave unexpectedly when used with a single parameter. It creates an array with of N length instead of initializing an Array with the provided param. - - -## Non-Compliant Code Examples -```typescript -new Array(); -new Array; -new Array(x, y); -new Array(0, 1, 2); -``` - -## Compliant Code Examples -```typescript -new Array(x) -Array(x) -new Array(9) -Array(9) -new foo.Array() -foo.Array() -new Array.foo -Array.foo() -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md b/content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md deleted file mode 100644 index fa6d62dcb12b2..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-code-style/no-confusing-non-null-assertion - language: TypeScript - severity: Warning -title: Avoid non-null assertion in confusing locations ---- -## Metadata -**ID:** `typescript-code-style/no-confusing-non-null-assertion` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Using a non-null assertion (`!`) next to an assign or equals check (`=` or `==` or `===`) could be confusing. - -## Non-Compliant Code Examples -```typescript -a! == b; -a! === b; -a + b! == c; -(obj = new new OuterObj().InnerObj).Name! == c; -(a==b)! ==c; -a! = b; -(obj = new new OuterObj().InnerObj).Name! = c; -(a=b)! =c; -``` - -## Compliant Code Examples -```typescript -a == b!; -a = b!; -a !== b; -a != b; -(a + b!) == c; -(a + b!) = c; -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-div-regex.md b/content/en/static_analysis/rules/typescript-code-style/no-div-regex.md deleted file mode 100644 index 297110e33364e..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-div-regex.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-code-style/no-div-regex - language: TypeScript - severity: Notice -title: Avoid equal signs explicitly at the beginning of regex ---- -## Metadata -**ID:** `typescript-code-style/no-div-regex` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Error Prone - -## Description -At the start of a regular expression literal, the characters `/=` can be mistaken for a division assignment operator. - -## Non-Compliant Code Examples -```typescript -var f = function() { return /=foo/; }; -``` - -## Compliant Code Examples -```typescript -var f = function() { return /foo/ig.test('bar'); }; -var f = function() { return /\\=foo/; }; -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md b/content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md deleted file mode 100644 index 601c6fe06e934..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-duplicate-imports.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-duplicate-imports - language: TypeScript - severity: Warning -title: Avoid duplicate module imports ---- -## Metadata -**ID:** `typescript-code-style/no-duplicate-imports` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -Single imports are easier to read and maintain you can see everything being imported from a module in one line. - -## Non-Compliant Code Examples -```typescript -import { merge } from 'module'; -import something from 'another-module'; -import { find } from 'module'; - -import something from 'something'; -import { find } from 'something'; -``` - -## Compliant Code Examples -```typescript -import { merge, find } from 'module'; -import something from 'another-module'; - -// not mergeable -import { merge } from 'something'; -import * as something from 'something'; -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md b/content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md deleted file mode 100644 index fa13985556388..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-empty-interface.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-empty-interface - language: TypeScript - severity: Notice -title: Avoid the declaration of empty interfaces ---- -## Metadata -**ID:** `typescript-code-style/no-empty-interface` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not use empty interfaces. - -## Non-Compliant Code Examples -```typescript -interface Foo {} -interface Foo extends {} -interface Bar extends Foo {} -interface Foo extends Array {} -interface Foo extends Array {} -interface Foo extends Array {} -interface Foo extends R {} -interface Foo extends Bar {} -declare module FooBar { type Baz = typeof baz; export interface Bar extends Baz {} } -interface Foo { - -} -``` - -## Compliant Code Examples -```typescript -interface Foo { name: string; } -interface Foo { name: string; } -interface Bar { age: number; } - -// valid because extending multiple interfaces can be used instead of a union type -interface Baz extends Foo, Bar {} -interface Foo { name: string; } -interface Foo { props: string; } -class Bar {} -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md b/content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md deleted file mode 100644 index 2ed67f5d1c293..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-floating-decimal.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/no-floating-decimal - language: TypeScript - severity: Notice -title: Avoid leading or trailing decimal points in numbers ---- -## Metadata -**ID:** `typescript-code-style/no-floating-decimal` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -To prevent confusion between the dot operator and the decimal point, always use a leading number when writing floating point numbers. - -## Non-Compliant Code Examples -```typescript -var x = .5; -var x = -.5; -var x = 2.; -var x = -2.; -typeof.2 -for(foo of.2); -``` - -## Compliant Code Examples -```typescript -var x = 2.5; -var x = "2.5"; -var t = { - ecmaVersion: 2018, -} -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md b/content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md deleted file mode 100644 index d616fbb3ad86c..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-inferrable-types.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-inferrable-types - language: TypeScript - severity: Notice -title: Avoid explicit type declarations for variables and params ---- -## Metadata -**ID:** `typescript-code-style/no-inferrable-types` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When you set an initial primitive value to a TypeScript parameter, property, or variable their respective type can be inferred. Explicitly adding type annotations in some cases can make your code more verbose and prevent TypeScript from inferring a more specific literal type. - -## Non-Compliant Code Examples -```typescript -const a: bigint = 10n; -const a: bigint = -10n; -const a: bigint = BigInt(10); -const a: bigint = -BigInt(10); -const a: bigint = BigInt?.(10); -const a: bigint = -BigInt?.(10); -const a: boolean = false; -const a: boolean = true; -const a: boolean = Boolean(null); -const a: boolean = Boolean?.(null); -const a: boolean = !0; -const a: number = 10; -const a: number = +10; -const a: number = -10; -const a: number = Number("1"); -const a: number = +Number("1"); -const a: number = -Number("1"); -const a: number = Number?.("1"); -const a: number = +Number?.("1"); -const a: number = -Number?.("1"); -const a: number = Infinity; -const a: number = +Infinity; -const a: number = -Infinity; -const a: number = NaN; -const a: number = +NaN; -const a: number = -NaN; -const a: null = null; -const a: RegExp = /a/; -const a: RegExp = RegExp("a"); -const a: RegExp = RegExp?.("a"); -const a: RegExp = new RegExp("a"); -const a: string = "str"; -const a: string = 'str'; -const a: string = `str`; -const a: string = String(1); -const a: string = String?.(1); -const a: symbol = Symbol("a"); -const a: symbol = Symbol?.("a"); -const a: undefined = undefined; -const a: undefined = void someValue; - -``` - -## Compliant Code Examples -```typescript -const a = 10n; -const a = -10n; -const a = BigInt(10); -const a = -BigInt(10); -const a = BigInt?.(10); -const a = -BigInt?.(10); -const a = false; -const a = true; -const a = Boolean(null); -const a = Boolean?.(null); -const a = !0; -const a = 10; -const a = +10; -const a = -10; -const a = Number("1"); -const a = +Number("1"); -const a = -Number("1"); -const a = Number?.("1"); -const a = +Number?.("1"); -const a = -Number?.("1"); -const a = Infinity; -const a = +Infinity; -const a = -Infinity; -const a = NaN; -const a = +NaN; -const a = -NaN; -const a = null; -const a = /a/; -const a = RegExp("a"); -const a = RegExp?.("a"); -const a = new RegExp("a"); -const a = "str"; -const a = 'str'; -const a = `str`; -const a = String(1); -const a = String?.(1); -const a = Symbol("a"); -const a = Symbol?.("a"); -const a = undefined; -const a = void someValue; -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md b/content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md deleted file mode 100644 index c3005f45bc662..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-lonely-if.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-lonely-if - language: TypeScript - severity: Notice -title: Avoid if statements as the only statement in else blocks ---- -## Metadata -**ID:** `typescript-code-style/no-lonely-if` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Prefer else if statement instead of an lonely if statement, it is considered cleaner code. - -## Non-Compliant Code Examples -```typescript -if (a) {;} else { if (b) {;} } - -if (a) { - foo(); -} else { - if (b) { - bar(); - } -} - -if (a) { - foo(); -} else /* comment */ { - if (b) { - bar(); - } -} - - -if (a) { - foo(); -} else { - /* otherwise, do the other thing */ if (b) { - bar(); - } -} - -if (a) { - foo(); -} else { - if /* this comment is ok */ (b) { - bar(); - } -} - -if (a) { - foo(); -} else { - if (b) { - bar(); - } /* this comment will prevent this test case from being autofixed. */ -} -if (foo) {} else { if (bar) baz(); } - -// Not fixed; removing the braces would cause a SyntaxError. -if (foo) {} else { if (bar) baz() } qux(); - -// This is fixed because there is a semicolon after baz(). -if (foo) {} else { if (bar) baz(); } qux(); - -// Not fixed; removing the braces would change the semantics due to ASI. -if (foo) { -} else { - if (bar) baz() -} -[1, 2, 3].forEach(foo); - -// Not fixed; removing the braces would change the semantics due to ASI. -if (foo) { -} else { - if (bar) baz++ -} -foo; - -// This is fixed because there is a semicolon after baz++ -if (foo) { -} else { - if (bar) baz++; -} -foo; - -// Not fixed; bar() would be interpreted as a template literal tag -if (a) { - foo(); -} else { - if (b) bar() -} -`template literal`; - -if (a) { - foo(); -} else { - if (b) { - bar(); - } else if (c) { - baz(); - } else { - qux(); - } -} -``` - -## Compliant Code Examples -```typescript -if (a) {;} else if (b) {;} -if (a) {;} else { if (b) {;} ; } -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md b/content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md deleted file mode 100644 index ae4ea76772076..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-multi-assign.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-multi-assign - language: TypeScript - severity: Notice -title: Avoid the use of chained assignment expressions ---- -## Metadata -**ID:** `typescript-code-style/no-multi-assign` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Assigning multiple variables at once can be hard to understand. Make one expression per assignment instead. - -## Non-Compliant Code Examples -```typescript -var a = b = c; -var a = b = c = d; -let foo = bar = cee = 100; -a=b=c=d=e; -a=b=c; -a -=b -=c; -var a = (b) = (((c))); -var a = ((b)) = (c); -var a = b = ( (c * 12) + 2); -var a = -((b)) - = (c); -a = b = '=' + c + 'foo'; -a = b = 7 * 12 + 5; -const x = {}; -const y = x.one = 1; -let a, b;a = b = 1; -let x, y;x = y = 'baz'; -const a = b = 1; -class C { field = foo = 0 } -class C { field = foo = 0 } -``` - -## Compliant Code Examples -```typescript -var a, b, c, -d = 0; -var a = 1; var b = 2; var c = 3; -var d = 0; -var a = 1 + (b === 10 ? 5 : 4); -const a = 1, b = 2, c = 3; -const a = 1; -const b = 2; -const c = 3; -for(var a = 0, b = 0;;){} -for(let a = 0, b = 0;;){} -for(const a = 0, b = 0;;){} -export let a, b; -export let a, - b = 0; -// ignore non declaration option not supported -// const x = {};const y = {};x.one = y.one = 1; -// let a, b;a = b = 1 -class C { [foo = 0] = 0 } -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-new-func.md b/content/en/static_analysis/rules/typescript-code-style/no-new-func.md deleted file mode 100644 index 056ca6a37f560..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-new-func.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-new-func - language: TypeScript - severity: Warning -title: Avoid new operators with the Function object ---- -## Metadata -**ID:** `typescript-code-style/no-new-func` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Best Practices - -## Description -The Function constructor can lead to code similar to `eval` executions. Use function declarations instead of the Function constructor. - -## Non-Compliant Code Examples -```typescript -var a = new Function("b", "c", "return b+c"); -var a = Function("b", "c", "return b+c"); -var a = Function.call(null, "b", "c", "return b+c"); -var a = Function.apply(null, ["b", "c", "return b+c"]); -var a = Function.bind(null, "b", "c", "return b+c")(); -var a = Function.bind(null, "b", "c", "return b+c"); -var a = Function["call"](null, "b", "c", "return b+c"); -var a = (Function?.call)(null, "b", "c", "return b+c"); -const fn = () => { class Function {} }; new Function('', ''); -var fn = function () { function Function() {} }; Function('', ''); -``` - -## Compliant Code Examples -```typescript -var a = new _function("b", "c", "return b+c"); -var a = _function("b", "c", "return b+c"); -// Scoped re assign not supported -// class Function {}; new Function() -// const fn = () => { class Function {}; new Function() } -// function Function() {}; Function() -// var fn = function () { function Function() {}; Function() } -// var x = function Function() { Function(); } -call(Function) -new Class(Function) -foo[Function]() -foo(Function.bind) -Function.toString() -Function[call]() -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-new-object.md b/content/en/static_analysis/rules/typescript-code-style/no-new-object.md deleted file mode 100644 index e01ae38876eaf..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-new-object.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-new-object - language: TypeScript - severity: Notice -title: Avoid Object constructors ---- -## Metadata -**ID:** `typescript-code-style/no-new-object` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -For consistency, always use the shorter object literal notation `{}`. - -## Non-Compliant Code Examples -```typescript -var foo = new Object() -new Object(); -const a = new Object() -``` - -## Compliant Code Examples -```typescript -// Scoped re declare not supported -var myObject = {}; -var myObject = new CustomObject(); -var foo = new foo.Object() -// var Object = function Object() {}; -// new Object(); -var x = something ? MyClass : Object; -var y = new x(); - -// class Object { -// constructor(){ - -// } -// } -// new Object(); - -// import { Object } from './' -// new Object(); - -const init = (canvas, context, t) => - drawDoughnutChart( - canvas, - t('Chats'), - context, - labels.map((l) => t(l)), - Object.values(initialData), - ); -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-new.md b/content/en/static_analysis/rules/typescript-code-style/no-new.md deleted file mode 100644 index ee1bb5953d24b..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-new.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-new - language: TypeScript - severity: Notice -title: Avoid new operators outside of assignments or comparisons ---- -## Metadata -**ID:** `typescript-code-style/no-new` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -A lonely instance is almost always useless. Do not create objects without assigning them to a variable that you will use later. - -## Non-Compliant Code Examples -```typescript -new Date() -``` - -## Compliant Code Examples -```typescript -var a = new Date() -var a; if (a === new Date()) { a = false; } -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-return-assign.md b/content/en/static_analysis/rules/typescript-code-style/no-return-assign.md deleted file mode 100644 index 72e9b42aa5af8..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-return-assign.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-code-style/no-return-assign - language: TypeScript - severity: Notice -title: Avoid assignment operators in return statements ---- -## Metadata -**ID:** `typescript-code-style/no-return-assign` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Error Prone - -## Description -JavaScript allows return statements to do assignment operations. Because it is hard to differentiate between an assignment and a comparison when written as part of the return statement, avoid using return statements. - -## Non-Compliant Code Examples -```typescript -function x() { return result = a * b; }; -function x() { return (result) = (a * b); }; -function x() { return result = a * b; }; -function x() { return (result) = (a * b); }; -() => { return result = a * b; }; -() => result = a * b; -function x() { return result = a * b; }; -// Allow parens option not supported -// function x() { return (result = a * b); }; -// function x() { return result || (result = a * b); }; -function foo(){ - return a = b -} -function doSomething() { - return foo = bar && foo > 0; -} -function doSomething() { - return foo = function(){ - return (bar = bar1) - } -} -function doSomething() { - return foo = () => a -} -function doSomething() { - return () => a = () => b -} -function foo(a){ - return function bar(b){ - return a = b - } -} -const foo = (a) => (b) => a = b; - -``` - -## Compliant Code Examples -```typescript -module.exports = {'a': 1}; -var result = a * b; -function x() { var result = a * b; return result; } -function x() { return (result = a * b); } -function x() { var result = a * b; return result; } -function x() { return (result = a * b); } -function x() { var result = a * b; return result; } -function x() { return function y() { result = a * b }; } -() => { return (result = a * b); } -() => (result = a * b) -const foo = (a,b,c) => ((a = b), c) -function foo(){ - return (a = b) -} -function bar(){ - return function foo(){ - return (a = b) && c - } -} -const foo = (a) => (b) => (a = b) -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-self-compare.md b/content/en/static_analysis/rules/typescript-code-style/no-self-compare.md deleted file mode 100644 index ad871eff4e6d3..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-self-compare.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-code-style/no-self-compare - language: TypeScript - severity: Warning -title: Avoid comparisons where both sides are exactly the same ---- -## Metadata -**ID:** `typescript-code-style/no-self-compare` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -Comparing a variable to itself is most likely a mistake. - -## Non-Compliant Code Examples -```typescript -if (x === x) { } -if (x !== x) { } -if (x > x) { } -if ('x' > 'x') { } -do {} while (x === x) -x === x -x !== x -x == x -x != x -x > x -x < x -x >= x -x <= x -foo.bar().baz.qux >= foo.bar().baz.qux -class C { #field; foo() { this.#field === this.#field; } } -``` - -## Compliant Code Examples -```typescript -if (x === y) { } -if (1 === 2) { } -y=x*x -foo.bar.baz === foo.bar.qux -class C { #field; foo() { this.#field === this['#field']; } } -class C { #field; foo() { this['#field'] === this.#field; } } -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md b/content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md deleted file mode 100644 index f2ec1c8a7d6d9..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-useless-empty-export.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-useless-empty-export - language: TypeScript - severity: Notice -title: Avoid empty exports that don't change anything ---- -## Metadata -**ID:** `typescript-code-style/no-useless-empty-export` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Do not use empty exports. - -## Non-Compliant Code Examples -```typescript -export const value = 'Hello, world!'; -export {}; - -import 'some-other-module'; -export {}; - -``` - -## Compliant Code Examples -```typescript -declare module '_'; -import {} from '_'; -import * as _ from '_'; -export = {}; -export = 3; -export const _ = {}; - -const _ = {}; -export default _; - -export * from '_'; -export = {}; - -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/no-var.md b/content/en/static_analysis/rules/typescript-code-style/no-var.md deleted file mode 100644 index 64480c358e5d8..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/no-var.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/no-var - language: TypeScript - severity: Notice -title: Require let or const instead of var ---- -## Metadata -**ID:** `typescript-code-style/no-var` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -Block scoped lexical declarations like `let` and `const` are preferred over `var`. Block scope is common in many other programming languages and helps programmers avoid mistakes. - -## Non-Compliant Code Examples -```typescript -var foo = bar; -var foo = bar, toast = most; -var foo = bar; let toast = most; -for (var a of b) { console.log(a); } -for (var a in b) { console.log(a); } -for (let a of b) { var c = 1; console.log(c); } -for (var i = 0; i < list.length; ++i) { foo(i) } -for (var i = 0; i < 10; ++i) {}; -for (var a of b) { arr.push(() => a); } -for (let a of b) { var c; console.log(c); c = 'hello'; } -var a = a; -var {a = a} = {}; -var {a = b, b} = {}; -let {a, b = a} = {}; -var a = b, b = 1; -let a = b; var b = 1; -function foo() { a } var a = 1; foo(); -if (foo) var bar = 1; -var foo = 1; -{ var foo = 1 } -if (true) { var foo = 1 } -var foo = 1; -declare var foo = 2; -function foo() { var let; } -function foo() { var { let } = {}; } -function foo() { a } -var a = 1; foo(); - -``` - -## Compliant Code Examples -```typescript -const JOE = 'schmoe'; -let moo = 'car'; -const JOE = 'schmoe'; -let moo = 'car'; -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/parameter-name.md b/content/en/static_analysis/rules/typescript-code-style/parameter-name.md deleted file mode 100644 index 38c969946b3a6..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/parameter-name.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-code-style/parameter-name - language: TypeScript - severity: Notice -title: Parameter name should use camelCase ---- -## Metadata -**ID:** `typescript-code-style/parameter-name` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that parameter names use `camelCase` and not `snake_case` or `PascalCase`. - -## Non-Compliant Code Examples -```typescript -const a = { setValue(NewValue, event_info?) {} } -class A { setValue(NewValue, event_info) {} } -function setValue(NewValue, event_info) {} -const a = function(NewValue, event_info) {} -``` - -## Compliant Code Examples -```typescript -const a = { getValue() {} } -class A { setValue(newValue) {} } -class B { setValue(md5, valid5String) {} } -``` diff --git a/content/en/static_analysis/rules/typescript-code-style/radix.md b/content/en/static_analysis/rules/typescript-code-style/radix.md deleted file mode 100644 index 4c5108e87a945..0000000000000 --- a/content/en/static_analysis/rules/typescript-code-style/radix.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Best Practices - id: typescript-code-style/radix - language: TypeScript - severity: Notice -title: Consistent use of the radix argument using parseInt ---- -## Metadata -**ID:** `typescript-code-style/radix` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Best Practices - -## Description -When utilizing the `parseInt()` function, many often skip the second parameter (the radix), allowing the function to deduce the number type based on the initial argument. By default, `parseInt()` can recognize both decimal and hexadecimal numbers, the latter through the `0x` prefix. However, before ECMAScript 5, the function also mistakenly recognized octal numbers, leading to issues as many developers presumed a starting `0` would be disregarded. - -## Non-Compliant Code Examples -```typescript -parseInt(); -parseInt(); -parseInt("10"); -parseInt("10",); -parseInt((0, "10")); -parseInt((0, "10"),); -parseInt("10", null); -parseInt("10", undefined); -parseInt("10", true); -parseInt("10", "foo"); -parseInt("10", "123"); -parseInt("10", 1); -parseInt("10", 37); -parseInt("10", 10.5); -Number.parseInt(); -Number.parseInt(); -Number.parseInt("10"); -Number.parseInt("10", 1); -Number.parseInt("10", 37); -Number.parseInt("10", 10.5); -parseInt?.("10"); -Number.parseInt?.("10"); -Number?.parseInt("10"); -(Number?.parseInt)("10"); - -``` - -## Compliant Code Examples -```typescript -parseInt("10", 10); -parseInt("10", 2); -parseInt("10", 36); -parseInt("10", 0x10); -parseInt("10", 1.6e1); -parseInt("10", 10.0); -parseInt("10", foo); -Number.parseInt("10", foo); -parseInt("10", 10); -parseInt("10", 8); -parseInt("10", foo); -parseInt -Number.foo(); -Number[parseInt](); -class C { #parseInt; foo() { Number.#parseInt(); } } -class C { #parseInt; foo() { Number.#parseInt(foo); } } -class C { #parseInt; foo() { Number.#parseInt(foo, 'bar'); } } -class C { #parseInt; foo() { Number.#parseInt(foo, 10); } } - -// shadowed not supported -// Ignores if it's shadowed or disabled. -// var parseInt; parseInt(); -// var parseInt; parseInt(foo); -// var parseInt; parseInt(foo, 10); -// var Number; Number.parseInt(); -// var Number; Number.parseInt(foo); -// var Number; Number.parseInt(foo, 10); -// /* globals parseInt:off */ parseInt(foo); -// Number.parseInt(foo, 10); -``` diff --git a/content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md b/content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md deleted file mode 100644 index 4cdf8e3c24db8..0000000000000 --- a/content/en/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-common-security/axios-avoid-insecure-http - language: TypeScript - severity: Warning -title: Avoid insecure HTTP requests with Axios ---- -## Metadata -**ID:** `typescript-common-security/axios-avoid-insecure-http` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Avoid connecting to `http` services. Use `https` services for security reasons. - -## Non-Compliant Code Examples -```typescript -const dataFromBackend = axios.get('http://backend.my.app') - -``` - -## Compliant Code Examples -```typescript -const dataFromBackend = axios.get('https://backend.my.app') - -``` diff --git a/content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md b/content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md deleted file mode 100644 index 0f56b932ba7c2..0000000000000 --- a/content/en/static_analysis/rules/typescript-common-security/unique-function-arguments.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-common-security/unique-function-arguments - language: TypeScript - severity: Warning -title: Function argument names should be unique ---- -## Metadata -**ID:** `typescript-common-security/unique-function-arguments` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -A function's parameter names should all be unique. Otherwise, a latter parameter will overwrite the former parameter. This behavior can lead to unintended bugs and it difficult to debug in the future. - -## Non-Compliant Code Examples -```typescript -function addition(foo: number, bar: number, foo: number) { - console.log(foo + bar + foo); -} - -addition(1, 2, 3); // outputs 8 -``` - -## Compliant Code Examples -```typescript -function addition(foo: number, bar: number, baz: number) { - console.log(foo + bar + baz); -} - -addition(1, 2, 3); // outputs 6 -``` diff --git a/content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md b/content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md deleted file mode 100644 index 1397cae017c5d..0000000000000 --- a/content/en/static_analysis/rules/typescript-common-security/xml-no-external-entities.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-common-security/xml-no-external-entities - language: TypeScript - severity: Warning -title: Do not use external XML entities ---- -## Metadata -**ID:** `typescript-common-security/xml-no-external-entities` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Process external entities in XML files may lead to XXE attack. Do not load external entities unless they have been explicitly checked. - -## Non-Compliant Code Examples -```typescript -import libxmljs from 'libxmljs'; -import fs from 'fs'; - -const xml = fs.readFileSync('file.xml', 'utf8'); -libxmljs.parseXmlString(xml, { - noent: true, -}); -``` - -## Compliant Code Examples -```typescript -import libxmljs from 'libxmljs'; -import fs from 'fs'; - -const xml = fs.readFileSync('file.xml', 'utf8'); -libxmljs.parseXmlString(xml); - -``` diff --git a/content/en/static_analysis/rules/typescript-express/access-restriction.md b/content/en/static_analysis/rules/typescript-express/access-restriction.md deleted file mode 100644 index d3b3b7150e5b6..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/access-restriction.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/access-restriction - language: TypeScript - severity: Warning -title: Limit exposure to sensitive directories and files ---- -## Metadata -**ID:** `typescript-express/access-restriction` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Exposing a directory listing could present an attacker an opportunity to access source code or other sensitive data through a file structure exploit. Restricting access to non-sensitive directories and files is strongly suggested. - -#### Learn More -- [Express Serve index middleware](https://expressjs.com/en/resources/middleware/serve-index.html) - - -## Non-Compliant Code Examples -```typescript -import express, { Express } from 'express'; -import serveIndex from "serve-index"; - -const app: Express = express(); - -app.use(serveIndex()) -``` - -## Compliant Code Examples -```typescript -import express, { Express } from 'express'; -import serveIndex from "serve-index"; - -const app: Express = express(); - -app.use(serveIndex("/public")) -``` diff --git a/content/en/static_analysis/rules/typescript-express/default-session-config.md b/content/en/static_analysis/rules/typescript-express/default-session-config.md deleted file mode 100644 index 6fc6e29b8221a..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/default-session-config.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/default-session-config - language: TypeScript - severity: Warning -title: Enforce overriding default config ---- -## Metadata -**ID:** `typescript-express/default-session-config` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Avoid leaving your session cookies open to exploits or unauthorized access, by overriding default values. - -Setting the `name` value to something generic is better than using the default value. - -#### Learn More -- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) - -## Non-Compliant Code Examples -```typescript -import session from "express-session" - -app.use( - session({ - secret: "secret" - }) -) -``` - -## Compliant Code Examples -```typescript -import session from "express-session" - -app.use( - session({ - secret: "secret", - name: 'sessionId' - }) -) -``` diff --git a/content/en/static_analysis/rules/typescript-express/external-filename-upload.md b/content/en/static_analysis/rules/typescript-express/external-filename-upload.md deleted file mode 100644 index b6ba024b7616d..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/external-filename-upload.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/external-filename-upload - language: TypeScript - severity: Warning -title: Avoid using unsanitized user input with sendFile ---- -## Metadata -**ID:** `typescript-express/external-filename-upload` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Using unsanitized user input in a `sendFile` method can allow attackers to access unintended resources. - -Set the `root` option directly in your `sendFile` options will make this rule not report a violation. - -#### Learn More -- [Express sendFile API reference](http://expressjs.com/en/5x/api.html#res.sendFile) - -## Non-Compliant Code Examples -```typescript -app.post("/upload", (req: Request, res: Response) => { - res.sendFile(req.params.filename) - - res.sendFile(req.params.filename, { maxAge: 0 }) - - res.sendFile(req.params.filename, { maxAge: 0 }, (err) => console.log(err)) -}) -``` - -## Compliant Code Examples -```typescript -app.post("/upload", (req: Request, res: Response) => { - res.sendFile("foo") - - const options = { maxAge: 0, root: path.join(__dirname, "upload") } - - res.sendFile(req.params.filename, options) - res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }) - - res.sendFile(req.params.filename, options, (err) => console.log(err)) - res.sendFile(req.params.filename, { maxAge: 0, root: path.join(__dirname, "upload") }, (err) => console.log(err)) -}) -``` diff --git a/content/en/static_analysis/rules/typescript-express/external-resource.md b/content/en/static_analysis/rules/typescript-express/external-resource.md deleted file mode 100644 index af9e85e82ce63..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/external-resource.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/external-resource - language: TypeScript - severity: Warning -title: Avoid rendering resource based on unsanitized user input ---- -## Metadata -**ID:** `typescript-express/external-resource` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Rendering resources based on unsanitized user input should be avoided. At a minimum, one should use a safelist to restrict the potential resources that are exposed. - -## Non-Compliant Code Examples -```typescript -app.get("/", (req: Request, res: Response) => { - res.render(req.body.path) - res.render(req.cookies.path) - res.render(req.headers.path) - res.render(req.params.path) - res.render(req.query.path) -}) -``` - -## Compliant Code Examples -```typescript -app.get("/", (req: Request, res: Response) => { - const path = req.body.path - if (["posts", "pages"].includes(path)) { - return res.render(`${path}/success`) - } - res.render("error-page") -}) -``` diff --git a/content/en/static_analysis/rules/typescript-express/hardcoded-secret.md b/content/en/static_analysis/rules/typescript-express/hardcoded-secret.md deleted file mode 100644 index c41ad3df24eb7..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/hardcoded-secret.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/hardcoded-secret - language: TypeScript - severity: Warning -title: Avoid using a hard-coded secret ---- -## Metadata -**ID:** `typescript-express/hardcoded-secret` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not store secrets in plaintext where they are used. Instead use environment variables (`process.env.`) or better yet, use a key management service (KMS) linked below that includes encryption. - -#### Learn More -- [OWASP hardcoded passwords](https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password) -- [Google Cloud Key Management Service](https://cloud.google.com/kms/docs) -- [AWS Key Management Service](https://aws.amazon.com/kms/) - -## Non-Compliant Code Examples -```typescript -import session from "express-session" -import { expressjwt } from "express-jwt" - -app.use( - session({ - name: "session-name", - secret: "not-secret-secret", - secret: `${isProd ? "prod-secret" : "dev-secret"}`, - }) -) - -app.use( - expressjwt({ - name: "session-name", - secret: "not-secret-secret", - secret: `${isProd ? "prod-secret" : "dev-secret"}`, - }) -) -``` - -## Compliant Code Examples -```typescript -import session from "express-session" -import { expressjwt } from "express-jwt" - -app.use( - session({ - name: "session-name", - secret: process.env.SECRET - }) -) - -app.use( - expressjwt({ - name: "session-name", - secret: process.env.SECRET - }) -) -``` diff --git a/content/en/static_analysis/rules/typescript-express/https-protocol-missing.md b/content/en/static_analysis/rules/typescript-express/https-protocol-missing.md deleted file mode 100644 index a7e00bae78b69..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/https-protocol-missing.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/https-protocol-missing - language: TypeScript - severity: Warning -title: Use `https` protocol over `http` ---- -## Metadata -**ID:** `typescript-express/https-protocol-missing` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-tls): - -> If your app deals with or transmits sensitive data, use [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS) to secure the connection and the data. This technology encrypts data before it is sent from the client to the server, thus preventing some common (and easy) hacks. - -This rule will detect the usage of non `https.createServer()` usage. - -## Non-Compliant Code Examples -```typescript -import https from 'https'; -import express, { Express } from 'express'; - -const app: Express = express(); - -var httpServer = http.createServer(app) -httpServer.listen(8080); -``` - -## Compliant Code Examples -```typescript -import https from 'https'; -import express, { Express } from 'express'; - -const app: Express = express(); - -var httpsServer = https.createServer(app) -httpsServer.listen(8080); -``` diff --git a/content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md b/content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md deleted file mode 100644 index 3570bb1f019d4..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/insecure-allow-origin.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/insecure-allow-origin - language: TypeScript - severity: Warning -title: Avoid using an insecure Access-Control-Allow-Origin header ---- -## Metadata -**ID:** `typescript-express/insecure-allow-origin` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Setting an Access-Control-Allow-Origin header with an unverified user-defined input can lead to sharing sensitive data with an unintended user. - -If this is unavoidable, consider comparing the input against a safe-list. - -#### Learn More - -- [OWASP Origin & Access-Control-Allow-Origin](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing) - - -## Non-Compliant Code Examples -```typescript -app.get('/', function (req: Request, res: Response) { - res.set('Access-Control-Allow-Origin', req.headers.foo) - res.set({ "foo": "bar", 'Access-Control-Allow-Origin': req.query.foo }) - res.header('Access-Control-Allow-Origin', req.params.foo) - res.setHeader('Access-Control-Allow-Origin', req.body.foo); - res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': req.cookies.foo }) -}); -``` - -## Compliant Code Examples -```typescript -app.get('/', function (req: Request, res: Response) { - res.set('Access-Control-Allow-Origin', "foo_url") - res.set({ "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) - res.header('Access-Control-Allow-Origin', "foo_url") - res.setHeader('Access-Control-Allow-Origin', "foo_url"); - res.writeHead(200, { "foo": "bar", 'Access-Control-Allow-Origin': "foo_url" }) -}); -``` diff --git a/content/en/static_analysis/rules/typescript-express/insecure-cookie.md b/content/en/static_analysis/rules/typescript-express/insecure-cookie.md deleted file mode 100644 index 027d964464c43..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/insecure-cookie.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/insecure-cookie - language: TypeScript - severity: Warning -title: Avoid setting insecure cookie settings ---- -## Metadata -**ID:** `typescript-express/insecure-cookie` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -When using cookies in your application, one should ensure appropriate security options are set to lessen the risk of exploits and unauthorized users. - -This rule will detect when `secure` and `httpOnly` are set to `false` in a multitude of ways. - -#### Learn More -- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html#use-cookies-securely) - -## Non-Compliant Code Examples -```typescript -const cookie = { - secure: false, - httpOnly: false, -} - -const options = { - cookie: { - secure: false, - httpOnly: false, - } -} - -cookieSession({ secure: false }) -``` - -## Compliant Code Examples -```typescript -const cookie = { - secure: true, - httpOnly: true, -} - -const options = { - cookie: { - secure: true, - httpOnly: true, - } -} - -cookieSession({ secure: true }) -``` diff --git a/content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md b/content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md deleted file mode 100644 index ff3ef9e0f8db0..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/jwt-not-revoked.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/jwt-not-revoked - language: TypeScript - severity: Warning -title: Ensure an isRevoked method is used for tokens ---- -## Metadata -**ID:** `typescript-express/jwt-not-revoked` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Consider a method to revoke JWTs, especially when they contain sensitive information, to ensure they remain short-lived. - -#### Learn More -- [ExpressJWT revoking documentation](https://github.com/auth0/express-jwt#revoked-tokens) - -## Non-Compliant Code Examples -```typescript -import { expressjwt } from "express-jwt"; - -app.get( - "/protected", - expressjwt({ - secret: "shhhhhhared-secret", - algorithms: ["HS256"], - }), - function (req, res) { - if (!req.auth.admin) return res.sendStatus(401); - res.sendStatus(200); - } -); -``` - -## Compliant Code Examples -```typescript -import { expressjwt as jwt } from "express-jwt"; - -app.get( - "/protected", - jwt({ - secret: "shhhhhhared-secret", - algorithms: ["HS256"], - isRevoked: isRevokedCallback, - }), - function (req, res) { - if (!req.auth.admin) return res.sendStatus(401); - res.sendStatus(200); - } -); -``` diff --git a/content/en/static_analysis/rules/typescript-express/missing-helmet.md b/content/en/static_analysis/rules/typescript-express/missing-helmet.md deleted file mode 100644 index f0fc5a12e1913..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/missing-helmet.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/missing-helmet - language: TypeScript - severity: Warning -title: Express application should use Helmet ---- -## Metadata -**ID:** `typescript-express/missing-helmet` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Per [Express documentation](https://expressjs.com/en/advanced/best-practice-security.html#use-helmet): - -> [Helmet](https://helmetjs.github.io/) can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately. - -This rule will check whether you've set `app.use(helmet())` within the file that you've called `express()` - -## Non-Compliant Code Examples -```typescript -import express, { Express, Request, Response } from 'express'; - -const app: Express = express(); - -// no `app.use(helmet())` helmet detected in the file - -app.get("/foo", (req: Request, res: Response) => res.send("foo")); - -app.listen(8000); -``` - -## Compliant Code Examples -```typescript -import express, { Express, Request, Response } from 'express'; -import helmet from "helmet"; - -const app: Express = express(); - -app.use(helmet()); // helmet detected - -app.get("/foo", (req: Request, res: Response) => res.send("foo")); - -app.listen(8000); -``` diff --git a/content/en/static_analysis/rules/typescript-express/path-traversal.md b/content/en/static_analysis/rules/typescript-express/path-traversal.md deleted file mode 100644 index dd0e7a69cb57e..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/path-traversal.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/path-traversal - language: TypeScript - severity: Warning -title: Avoid allowing access to unintended directories or files ---- -## Metadata -**ID:** `typescript-express/path-traversal` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -By not sanitizing user input prior to using it in path resolution methods you open your application's access to unintended directories and files. - -> If you're using `replace` on a user input, this rule will assume you've done so correctly and will not report a violation - -#### Learn More -- [OWASP path traversal](https://owasp.org/www-community/attacks/Path_Traversal) - -## Non-Compliant Code Examples -```typescript -import path from "path"; - -app.get("/", (req: Request, res: Response) => { - path.join("/user/", req.params.path) - - const pathname = path.join("/public/", req.body.foo) - path.resolve(pathname) - - path.resolve(__dirname, req.body.foo) - path.resolve(__dirname, `${req.body.foo}`) -}) -``` - -## Compliant Code Examples -```typescript -import path from "path"; - -app.get("/", (req: Request, res: Response) => { - path.join("/user/", req.params.path.replace(/^(\.\.(\/|\\|$))+/, '')) - - const pathname = path.join("/public/", req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) - path.resolve(pathname) - - path.resolve(__dirname, req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')) - path.resolve(__dirname, `${req.body.foo.replace(/^(\.\.(\/|\\|$))+/, '')}`) -}) -``` diff --git a/content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md b/content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md deleted file mode 100644 index 32e230e84d84a..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/reduce-server-fingerprinting.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/reduce-server-fingerprinting - language: TypeScript - severity: Warning -title: Server fingerprinting misconfiguration ---- -## Metadata -**ID:** `typescript-express/reduce-server-fingerprinting` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Improve your overall server security by taking the step to reduce the likelihood of server fingerprinting the software being used on the server. - -By default, Express.js sends the `X-Powered-By` response header banner which can be disabled with `app.disable('X-Powered-By')`. - -If you're using `helmet`, you can use either of these methods too: -- `app.use(hidePoweredBy())` -- `app.use(helmet.hidePoweredBy())` - -#### Learn More -- [Express Security Best Practices](https://expressjs.com/en/advanced/best-practice-security.html) - -## Non-Compliant Code Examples -```typescript -const app: Express = express(); - -// express() is called but none of the following were detected afterwards -// app.disable('x-powered-by') -// app.use(hidePoweredBy()) -// app.use(helmet.hidePoweredBy()) -``` - -## Compliant Code Examples -```typescript -const app: Express = express(); - -app.use(helmet.hidePoweredBy()); - -// rest of your config -``` - -```typescript -const app: Express = express(); - -app.use(hidePoweredBy()) - -// rest of your config -``` - -```typescript -const app: Express = express(); - -app.disable('x-powered-by') - -// rest of your config -``` diff --git a/content/en/static_analysis/rules/typescript-express/xss-vulnerability.md b/content/en/static_analysis/rules/typescript-express/xss-vulnerability.md deleted file mode 100644 index d2eeeade51167..0000000000000 --- a/content/en/static_analysis/rules/typescript-express/xss-vulnerability.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-express/xss-vulnerability - language: TypeScript - severity: Warning -title: Avoid sending unsanitized user input in response ---- -## Metadata -**ID:** `typescript-express/xss-vulnerability` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Returning unsanitized user input in a `send` or `write` method can increase your application's risk of cross-site scripting attacks. - -#### Learn More -- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) - -## Non-Compliant Code Examples -```typescript -app.get("/", (req: Request, res: Response) => { - res.send(req.body.foo); - res.send({ title: "foo", message: req.body.foo }); - res.write(req.body.foo); - res.write({ title: "foo", message: req.body.foo }); -}) -``` - -## Compliant Code Examples -```typescript -app.get("/", (req: Request, res: Response) => { - res.send("foo"); - res.send({ title: "foo", message: 'foo' }); - res.write("foo"); - res.write({ title: "foo", message: 'foo' }); -}) -``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/comments.md b/content/en/static_analysis/rules/typescript-inclusive/comments.md deleted file mode 100644 index 2346a8bb24ead..0000000000000 --- a/content/en/static_analysis/rules/typescript-inclusive/comments.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-inclusive/comments - language: TypeScript - severity: Notice -title: Check comments for wording issues ---- -## Metadata -**ID:** `typescript-inclusive/comments` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Check the variable names and suggest better names. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```typescript -/** - * whitelist names to prevent unauthorized usage - */ - -// she SHE should check her code - -// he should check his -``` - -## Compliant Code Examples -```typescript -// allowlist names to prevent unauthorized usage - -/* the comments do not have a history of issues */ -``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/declarations.md b/content/en/static_analysis/rules/typescript-inclusive/declarations.md deleted file mode 100644 index a735ba5f7a303..0000000000000 --- a/content/en/static_analysis/rules/typescript-inclusive/declarations.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-inclusive/declarations - language: TypeScript - severity: Notice -title: Check declaration names for wording issues ---- -## Metadata -**ID:** `typescript-inclusive/declarations` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that some words are not used in the codebase and suggest a replacement when appropriate. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```typescript -function foo_blacklist() {} -a(function *blackList() {}); -function *whItEList() {} -function blacklist_names() {} -function whiteList() {} -class WhiteList {} -const slave = 0; -let master = ""; -var slave = b; -``` - -## Compliant Code Examples -```typescript -function foo_denyList() {} -a(function *allowedList() {}); -class primary {} -const secondary = 0; -``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md b/content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md deleted file mode 100644 index 6bc99bd00f3f5..0000000000000 --- a/content/en/static_analysis/rules/typescript-inclusive/formal-parameters.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-inclusive/formal-parameters - language: TypeScript - severity: Notice -title: Check parameter names for wording issues ---- -## Metadata -**ID:** `typescript-inclusive/formal-parameters` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that some words are not used in the codebase and suggest a replacement when appropriate. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```typescript -function a(master, slave) {} -function a(blacklist, whitelist?: boolean) {} -class A { foo(master: string, slave = 1) {} } - -``` - -## Compliant Code Examples -```typescript -function denyList(primary, secondary) {} -``` diff --git a/content/en/static_analysis/rules/typescript-inclusive/identifiers.md b/content/en/static_analysis/rules/typescript-inclusive/identifiers.md deleted file mode 100644 index 311cc56bf5049..0000000000000 --- a/content/en/static_analysis/rules/typescript-inclusive/identifiers.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Code Style - id: typescript-inclusive/identifiers - language: TypeScript - severity: Notice -title: Check identifier names for wording issues ---- -## Metadata -**ID:** `typescript-inclusive/identifiers` - -**Language:** TypeScript - -**Severity:** Notice - -**Category:** Code Style - -## Description -Ensure that some words are not used in the codebase and suggest a replacement when appropriate. - -Examples of replacement suggestions: - -- `blacklist` with `denylist` -- `whitelist` with `allowlist` -- `master` with `primary` -- `slave` with `secondary` - -## Non-Compliant Code Examples -```typescript -{ slave: false } -const a = { 'master': false, }; -const a = { ['master']: false, }; -const a = { c, ...blacklist } = b; -const { whitelist } = b; -const a = { whitelist }; -const { whitelist: slave } = b; -[slave, ...master] = blacklist; -``` - -## Compliant Code Examples -```typescript -{ secondary: false } -const a = { 'primary': false, }; -const a = { c, ...denylist } = b; -const { AllowedList } = b; -[primary, ...secondary] = b; -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/argon2.md b/content/en/static_analysis/rules/typescript-node-security/argon2.md deleted file mode 100644 index 76880feeeed1b..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/argon2.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/argon2 - language: TypeScript - severity: Error -title: Use strong security mechanisms with argon2 ---- -## Metadata -**ID:** `typescript-node-security/argon2` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Security - -## Description -Use secure and fast security mechanisms when using `argon2`. - -#### Learn More - - - [argon2 types](https://github.com/ranisalt/node-argon2/wiki/Options#type) - -## Non-Compliant Code Examples -```typescript -await argon2.hash('password', {type: argon2.argon2d}) -await argon2.hash('password', {type: argon2.argon2i}) -``` - -## Compliant Code Examples -```typescript -await argon2.hash('password', {type: argon2.argon2id}) -await argon2.hash('password', {}) -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md b/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md deleted file mode 100644 index 6d2d71d3d87c7..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-rc4.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/avoid-crypto-rc4 - language: TypeScript - severity: Warning -title: Avoid RC4 ---- -## Metadata -**ID:** `typescript-node-security/avoid-crypto-rc4` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of the RC4 security protocol exposes your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library, RC4](https://cryptojs.gitbook.io/docs/#ciphers) - -## Non-Compliant Code Examples -```typescript -const encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase"); -const decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase"); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md b/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md deleted file mode 100644 index 62410f011887a..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/avoid-crypto-sha1.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/avoid-crypto-sha1 - language: TypeScript - severity: Warning -title: Avoid SHA1 security protocol ---- -## Metadata -**ID:** `typescript-node-security/avoid-crypto-sha1` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of insecure encryption or hashing protocols expose your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hmac) - -## Non-Compliant Code Examples -```typescript -const hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase"); -const hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase", anotherargument); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/avoid-des.md b/content/en/static_analysis/rules/typescript-node-security/avoid-des.md deleted file mode 100644 index e5f84ce4bc194..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/avoid-des.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/avoid-des - language: TypeScript - severity: Warning -title: Avoid DES and 3DES ---- -## Metadata -**ID:** `typescript-node-security/avoid-des` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of insecure encryption or hashing protocols expose your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library, DES and TripleDES](https://cryptojs.gitbook.io/docs/#ciphers) - -## Non-Compliant Code Examples -```typescript -const encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase"); -const decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase"); -const encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase"); -const decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase"); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md b/content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md deleted file mode 100644 index ed8e633b8fcbd..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/chmod-permissions.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/chmod-permissions - language: TypeScript - severity: Warning -title: Do not give 777 permissions to a file ---- -## Metadata -**ID:** `typescript-node-security/chmod-permissions` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Always make sure you restrict the permissions of your application files. Applications should not allow write and execution for other users, as it may leak data and information. Always restrict the number of users and applications that can access your application data. - -## Non-Compliant Code Examples -```typescript -const fs = require('fs'); -const fsPromises = fs.promises; - -fs.chmodSync("/tmp/myfile", 0o777); -fsPromises.chmod("/tmp/fsPromises", 0o777); - -``` - -## Compliant Code Examples -```typescript -const fs = require('fs'); -const fsPromises = fs.promises; - -fs.chmodSync(myPath, 0o770); -fsPromises.chmod("/tmp/fsPromises", 0o770); - -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/command-injection.md b/content/en/static_analysis/rules/typescript-node-security/command-injection.md deleted file mode 100644 index 3a5b8b51cf554..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/command-injection.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/command-injection - language: TypeScript - severity: Warning -title: Avoid command injection ---- -## Metadata -**ID:** `typescript-node-security/command-injection` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -When executing a command, never use unchecked variables. Make sure that each variable of the command has been checked. - -## Non-Compliant Code Examples -```typescript -childprocess.exec(`mv ${src} ${dst}`, (error, stdout, stderr) => {}); -childprocess.exec('mv ' + src + " " + dst, (error, stdout, stderr) => {}); -``` - -## Compliant Code Examples -```typescript -childprocess.exec('mv /tmp/src /tmp/dst', (error, stdout, stderr) => {}); - -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md b/content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md deleted file mode 100644 index 42b26dd6f3fd7..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/crypto-avoid-weak-hash - language: TypeScript - severity: Warning -title: Avoid weak hash algorithm from CryptoJS ---- -## Metadata -**ID:** `typescript-node-security/crypto-avoid-weak-hash` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Use of insecure hash functions like MD5 or SHA1 can expose your application to vulnerabilities. - -#### Learn More - - - [JS Crypto Library](https://cryptojs.gitbook.io/docs/#hashing) - -## Non-Compliant Code Examples -```typescript -const hash = CryptoJS.MD5("Message", "Secret Passphrase"); -const hash = CryptoJS.SHA1("Message", "Secret Passphrase"); -const hash = CryptoJS.HmacMD5("Message", "Secret Passphrase"); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md b/content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md deleted file mode 100644 index 630154ecfbf00..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detect-buffer-noassert.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/detect-buffer-noassert - language: TypeScript - severity: Error -title: Avoid calls to 'buffer' with 'noAssert' flag set ---- -## Metadata -**ID:** `typescript-node-security/detect-buffer-noassert` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Security - -## Description -Avoid calls to [`buffer`](https://nodejs.org/api/buffer.html) with `noAssert`. If you skip the `offset` validation it can go beyond the end of the `Buffer`. - -## Non-Compliant Code Examples -```typescript -a.readUInt8(0, true) -a.readUInt16LE(0, true) -a.readUInt16BE(0, true) -a.readUInt32LE(0, true) -a.readUInt32BE(0, true) -a.readInt8(0, true) -a.readInt16LE(0, true) -a.readInt16BE(0, true) -a.readInt32LE(0, true) -a.readInt32BE(0, true) -a.readFloatLE(0, true) -a.readFloatBE(0, true) -a.readDoubleLE(0, true) -a.readDoubleBE(0, true) -a.writeUInt8(0, 0, true) -a.writeUInt16LE(0, 0, true) -a.writeUInt16BE(0, 0, true) -a.writeUInt32LE(0, 0, true) -a.writeUInt32BE(0, 0, true) -a.writeInt8(0, 0, true) -a.writeInt16LE(0, 0, true) -a.writeInt16BE(0, 0, true) -a.writeInt32LE(0, 0, true) -a.writeInt32BE(0, 0, true) -a.writeFloatLE(0, 0, true) -a.writeFloatBE(0, 0, true) -a.writeDoubleLE(0, 0, true) -a.writeDoubleBE(0, 0, true) - -``` - -## Compliant Code Examples -```typescript -a.readUInt8(0) -a.readUInt16LE(0) -a.readUInt16BE(0) -a.readUInt32LE(0) -a.readUInt32BE(0) -a.readInt8(0) -a.readInt16LE(0) -a.readInt16BE(0) -a.readInt32LE(0) -a.readInt32BE(0) -a.readFloatLE(0) -a.readFloatBE(0) -a.readDoubleLE(0) -a.readDoubleBE(0) -a.writeUInt8(0) -a.writeUInt16LE(0) -a.writeUInt16BE(0) -a.writeUInt32LE(0) -a.writeUInt32BE(0) -a.writeInt8(0) -a.writeInt16LE(0) -a.writeInt16BE(0) -a.writeInt32LE(0) -a.writeInt32BE(0) -a.writeFloatLE(0) -a.writeFloatBE(0) -a.writeDoubleLE(0) -a.writeDoubleBE(0) -a.readUInt8(0, false) -a.readUInt16LE(0, false) -a.readUInt16BE(0, false) -a.readUInt32LE(0, false) -a.readUInt32BE(0, false) -a.readInt8(0, false) -a.readInt16LE(0, false) -a.readInt16BE(0, false) -a.readInt32LE(0, false) -a.readInt32BE(0, false) -a.readFloatLE(0, false) -a.readFloatBE(0, false) -a.readDoubleLE(0, false) -a.readDoubleBE(0, false) -a.writeUInt8(0, false) -a.writeUInt16LE(0, false) -a.writeUInt16BE(0, false) -a.writeUInt32LE(0, false) -a.writeUInt32BE(0, false) -a.writeInt8(0, false) -a.writeInt16LE(0, false) -a.writeInt16BE(0, false) -a.writeInt32LE(0, false) -a.writeInt32BE(0, false) -a.writeFloatLE(0, false) -a.writeFloatBE(0, false) -a.writeDoubleLE(0, false) -a.writeDoubleBE(0, false) -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-child-process.md b/content/en/static_analysis/rules/typescript-node-security/detect-child-process.md deleted file mode 100644 index 15ffb3ed5771a..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detect-child-process.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Error Prone - id: typescript-node-security/detect-child-process - language: TypeScript - severity: Warning -title: Avoid instances of 'child_process' and non-literal 'exec()' ---- -## Metadata -**ID:** `typescript-node-security/detect-child-process` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Error Prone - -## Description -In Node.js, the "child_process" module provides capabilities to execute shell commands directly. While this might seem beneficial, it comes with significant security risks. If the input to this module isn't properly sanitized, it can pave the way for command injection attacks. In such attacks, malicious actors could introduce harmful commands, which, when executed, could compromise system integrity or lead to data breaches. - -Additionally, using non-literal arguments with "exec()" presents another challenge. When arguments to "exec()" are dynamic or derived from untrusted sources, there's a risk that attackers could manipulate this input. This makes the system vulnerable to unauthorized actions, potentially causing significant damage. Therefore, for a more secure Node.js application, it's advised to tread cautiously with these features, employing rigorous input validation and considering safer alternatives. - -## Non-Compliant Code Examples -```typescript -require('child_process') -require('node:child_process') -var child = require('child_process'); child.exec(com) -var nodeChild = require('node:child_process'); nodeChild.exec(com) -import childImport from 'child_process'; childImport.exec(com) -import nodeChildImport from 'node:child_process'; nodeChildImport.exec(com) - -// not supported -// var child = sinon.stub(require('child_process')); child.exec.returns({}); -// var child = sinon.stub(require('node:child_process')); child.exec.returns({}); - -function fn () { - var result = child.exec(str); -} - -function fn () { - var result = childImport.exec(str); -} - -function fn () { - var result = nodeChildImport.exec(str); -} - -require('child_process').exec(str) - -function fn () { - require('child_process').exec(str) -} - -const {exec} = require('child_process'); -exec(str) - -const {exec: nodeExec} = require('node:child_process'); -nodeExec(str) - -import {exec as foo} from 'child_process'; -foo(com); -``` - -## Compliant Code Examples -```typescript -child_process.exec('ls') - -var {} = require('child_process'); -var result = /hello/.exec(str); - -var {} = require('node:child_process'); -var result = /hello/.exec(str); - -import {} from 'child_process'; -var result = /hello/.exec(str); - -import {} from 'node:child_process'; -var result = /hello/.exec(str); - -var { spawn } = require('child_process'); spawn(str); -var { spawn } = require('node:child_process'); spawn(str); -import { spawn } from 'child_process'; spawn(str); -import { spawn } from 'node:child_process'; spawn(str); - -// import redeclare not covered -// var foo = require('child_process'); -// function fn () { -// var foo = /hello/; -// var result = foo.exec(str); -// } - -var child = require('child_process'); child.spawn(str) -var child = require('node:child_process'); child.spawn(str) -import child from 'child_process'; child.spawn(str) -import child from 'node:child_process'; child.spawn(str) - -var foo = require('child_process'); -function fn () { - var result = foo.spawn(str); -} - -require('child_process').spawn(str) - -function fn () { - require('child_process').spawn(str) -} - -// constant assigment static analysis not covered -// var child_process = require('child_process'); -// var FOO = 'ls'; -// child_process.exec(FOO); - -// import child_process from 'child_process'; -// const FOO = 'ls'; -// child_process.exec(FOO); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md b/content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md deleted file mode 100644 index 81ba250e36e5c..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detect-eval-with-expression.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/detect-eval-with-expression - language: TypeScript - severity: Warning -title: Avoid `eval` with expressions ---- -## Metadata -**ID:** `typescript-node-security/detect-eval-with-expression` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -The `eval` function could execute malicious code if used with non-literal values. The argument provided to the `eval` method could be use to execute malicious code, if an attacker manage to control the `eval` argument they can execute arbitrary code. - -In JavaScript, the `eval()` function evaluates or executes an argument if it's a string of JavaScript code. If this argument is influenced by user input or other external sources, it can lead to security vulnerabilities. Specifically, if an attacker can control or manipulate the value of the `variable` in `eval(variable)`, they can execute arbitrary code. - -It is recommended to avoid `eval` at all cost, but if you face an advance use case make sure to use literal values that are under you control or take actions to sanitize the input, even then it is still recommended to avoid the use of `eval` as it has lead to security breaches before. - -## Non-Compliant Code Examples -```typescript -eval(a); -global.eval(a); -globalThis.eval(a); - -const answer = eval(expression) -``` - -## Compliant Code Examples -```typescript -eval('alert()') -global.eval('a'); -globalThis.eval('a'); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md b/content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md deleted file mode 100644 index 1034acfb0da2a..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detect-new-buffer.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/detect-new-buffer - language: TypeScript - severity: Warning -title: Avoid Buffer(argument) with non-literal values ---- -## Metadata -**ID:** `typescript-node-security/detect-new-buffer` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Dealing with binary data can achieved with Node.js Buffer class, however if used with non literal params it could lead to an attack as the attacker might control the value of the provided parameter. - -For example a large number could allocate a large amount of memory leading to a denial of service attack. It is recommended to use literal values you can control to prevent attacks. - -## Non-Compliant Code Examples -```typescript -var a = new Buffer(c) -``` - -## Compliant Code Examples -```typescript -var a = new Buffer('test') -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md deleted file mode 100644 index b72b970e79d10..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/detect-non-literal-fs-filename - language: TypeScript - severity: Warning -title: Avoid variables in 'fs' calls filename argument ---- -## Metadata -**ID:** `typescript-node-security/detect-non-literal-fs-filename` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -An attacker could manipulate the file system call argument leading to a path traversal attack where the attacker get access to files and directories within your server file system. - -## Non-Compliant Code Examples -```typescript -/// requires -var something = require('fs'); -var a = something.open(c); - -var one = require('fs').readFile; -one(filename); - -var one = require('node:fs').readFile; -one(filename); - -var one = require('fs/promises').readFile; -one(filename); - -var something = require('fs/promises'); -something.readFile(filename); - -var something = require('node:fs/promises'); -something.readFile(filename); - -var something = require('fs-extra'); -something.readFile(filename); - -var { readFile: something } = require('fs'); -something(filename) - -//// imports -import { readFile as something } from 'fs'; -something(filename); - -import { readFile as something } from 'node:fs'; -something(filename); - -import { readFile as something } from 'fs-extra'; -something(filename); - -import { readFile as something } from 'fs/promises' -something(filename) - -import { readFile as something } from 'node:fs/promises' -something(filename) - -import { readFile } from 'node:fs/promises' -something(readFile) - -import * as something from 'fs'; -something.readFile(filename); -import * as something from 'node:fs'; -something.readFile(filename); - -/// promises -var something = require('fs').promises; -something.readFile(filename) - -var something = require('node:fs').promises; -something.readFile(filename) - -var something = require('fs'); -something.promises.readFile(filename) - -var something = require('node:fs'); -something.promises.readFile(filename) - -var fs = require('fs'); -fs.readFile(`template with ${filename}`); - -// inline -function foo () { - var fs = require('fs'); - fs.readFile(filename); -} - -function foo () { - var { readFile: something } = require('fs'); - something(filename); -} - -var fs = require('fs'); -function foo () { - var { readFile: something } = fs.promises; - something(filename); -} - -import fs from 'fs'; -import path from 'path'; -const key = fs.readFileSync(path.resolve(__dirname, foo)); -``` - -## Compliant Code Examples -```typescript -var fs = require('fs'); -var a = fs.open('test') - -var something = require('some'); -var a = something.readFile(c); - -var something = require('fs').readFile, readFile = require('foo').readFile; -readFile(c); - - -// TODO: allow path with constant arguments -import { promises as fsp } from 'fs'; -import fs from 'fs'; -import path from 'path'; -// const index = await fsp.readFile(path.resolve(__dirname, './index.html'), 'utf-8'); -// const key = fs.readFileSync(path.join(__dirname, './ssl.key')); -await fsp.writeFile(path.resolve(__dirname, './sitemap.xml'), sitemap); - -import fs from 'fs'; -import path from 'path'; -const dirname = path.dirname(__filename) -// const key = fs.readFileSync(path.resolve(dirname, './index.html')); - -import fs from 'fs'; -// const key = fs.readFileSync(`${process.cwd()}/path/to/foo.json`); - -import fs from 'fs'; -import path from 'path'; -import url from 'url'; -// const dirname = path.dirname(url.fileURLToPath(import.meta.url)); -// const html = fs.readFileSync(path.resolve(dirname, './index.html'), 'utf-8'); - -import fs from 'fs'; -// const pkg = fs.readFileSync(require.resolve('eslint/package.json'), 'utf-8'); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md deleted file mode 100644 index 60affbdb0b185..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-regexp.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/detect-non-literal-regexp - language: TypeScript - severity: Warning -title: Detects non-literal values in regular expressions ---- -## Metadata -**ID:** `typescript-node-security/detect-non-literal-regexp` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Creating a regular expression with user input is a security vulnerability as it could lead to a Regular Expression Denial of Service attack. In this type of attack a user could submit a very complex regular expression that takes too long to execute. - -If you have an advanced use case that requires regex evaluation with user input always make sure to sanitize the data and provide a safe timeout environment. - -## Non-Compliant Code Examples -```typescript -var a = new RegExp(c, 'i'); - -``` - -## Compliant Code Examples -```typescript -var a = new RegExp('ab+c', 'i'); - -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md b/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md deleted file mode 100644 index ac328cb2a7b6f..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detect-non-literal-require.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/detect-non-literal-require - language: TypeScript - severity: Warning -title: Avoid require with non-literal values ---- -## Metadata -**ID:** `typescript-node-security/detect-non-literal-require` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Importing packages from dynamic paths can be a security vulnerability. An attacker might provide an undesired path that leads to running arbitrary code or reading sensitive information from your file system. - -In Node.js, the `require()` function is a built-in function that allows modules to be loaded. You can use it to include various types of files (like .js, .json, .node, etc) in your project. - -If the argument to `require()` is a variable instead of a static string, and if that variable's value can be influenced by user input, then an attacker might be able to exploit this to run arbitrary code or read sensitive files from your server's disk. This is a serious security issue often referred to as arbitrary code execution. - -Dynamic imports are a common source of arbitrary file read and code execution vulnerabilities. Avoid using variables with `require` or `import` statements. If you have an advanced use case that requires the use of dynamic imports, make sure to sanitize the input and have an allowed list of paths you can import code from. Always set the proper access control to your file system. - -## Non-Compliant Code Examples -```typescript -const a = require(c); -const a = require(`${c}`); - -``` - -## Compliant Code Examples -```typescript -var a = require('b'); -var a = require(`b`); - -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md b/content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md deleted file mode 100644 index 4a5d3fcb90e60..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/detected-jwt-token.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/detected-jwt-token - language: TypeScript - severity: Error -title: Detects hardcoded JWT tokens within the codebase ---- -## Metadata -**ID:** `typescript-node-security/detected-jwt-token` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Security - -## Description -JSON Web Tokens (JWT) are commonly used for authentication and information exchange in web applications. While they are a powerful tool, they must be handled with care. - -## Non-Compliant Code Examples -```typescript -"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" -"eyJ0eXAiOiJKV1QiLA0KImFsZyI6IkhTMjU2In0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" -"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9lIiwKInN0YXR1cyI6ImVtcGxveWVlIgp9" -'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IsWww6HFkcOtIMOWxZHDqcOoIiwiaWF0IjoxNTE2MjM5MDIyfQ.k5HibI_uLn_RTuPcaCNkaVaQH2y5q6GvJg8GPpGMRwQ' -`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ` -``` - -## Compliant Code Examples -```typescript -"eyfoo" -`eybaz` -'eybla' -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md b/content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md deleted file mode 100644 index d86ae0cc81458..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/hardcoded-hmac-key.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/hardcoded-hmac-key - language: TypeScript - severity: Warning -title: Detects hardcoded HMAC keys ---- -## Metadata -**ID:** `typescript-node-security/hardcoded-hmac-key` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Hardcoding cryptographic keys, secrets, or other sensitive information within the code is a common but dangerous practice. This rule aims to detect and prevent this kind of code pattern. - -## Non-Compliant Code Examples -```typescript -import crypto from "crypto"; - -crypto.createHmac('sha256', 'pa4qacea4VK9t9nGv7yZtwmj').update(data).digest('hex'); - -const rsa_key = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' -const hmac = crypto.createHmac('sha256', rsa_key) - -const key = 'private'; -const secret = key; -const fail = crypto.createHmac('sha256', secret); -``` - -## Compliant Code Examples -```typescript -import crypto from "crypto"; -import config from "./config"; - -const safely_stored_key = config.get('AWS_KEY') -const safe_hmac = crypto.createHmac('sha256', safely_stored_key) - -crypto.createHmac('sha256', process.env.KEY); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/insecure-hash.md b/content/en/static_analysis/rules/typescript-node-security/insecure-hash.md deleted file mode 100644 index c162b720a3720..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/insecure-hash.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/insecure-hash - language: TypeScript - severity: Warning -title: Do not use weah hash functions ---- -## Metadata -**ID:** `typescript-node-security/insecure-hash` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not use weak hash algorithms such as MD5 or SHA1. - -#### Learn More - - - [CWE-328: Use of Weak Hash](https://cwe.mitre.org/data/definitions/328.html) - -## Non-Compliant Code Examples -```typescript -crypto.createHash("md5") -crypto.createHash("sha1") -``` - -## Compliant Code Examples -```typescript -crypto.createHash("sha256") - -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md b/content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md deleted file mode 100644 index 1a349344e999e..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/insecure-jwt-secret-usage - language: TypeScript - severity: Error -title: Insecure Usage of a Static Secret in JWT Signing ---- -## Metadata -**ID:** `typescript-node-security/insecure-jwt-secret-usage` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Security - -## Description -Using a static secret for signing JSON Web Tokens (JWT) poses several security risks: - -1. **Static Secrets**: Static secrets embedded in the code can be easily discovered by attackers. This is particularly dangerous if the code becomes publicly available or is leaked. -2. **Weak Secrets**: A simple, static secret might be weak and easily guessable, rendering the security controls it supports ineffective. -3. **Lack of Key Rotation**: A static secret doesn't allow for key rotation, a recommended practice to mitigate the risk if a secret is compromised. - -## Non-Compliant Code Examples -```typescript -import jwt from 'jsonwebtoken'; - -const privateKey = '-----BEGIN RSA PRIVATE KEY-----\r\nMIICXAIBAAKBgQDNwqLEe9wgTXCbC7+RPdDbBbeqjdbs4kOPOIGzqLpXvJXlxxW8iMz0EaM4BKUqYsIa+ndv3NAn2RxCd5ubVdJJcX43zO6Ko0TFEZx/65gY3BE0O6syCEmUP4qbSd6exou/F+WTISzbQ5FBVPVmhnYhG/kpwt/cIxK5iUn5hm+4tQIDAQABAoGBAI+8xiPoOrA+KMnG/T4jJsG6TsHQcDHvJi7o1IKC/hnIXha0atTX5AUkRRce95qSfvKFweXdJXSQ0JMGJyfuXgU6dI0TcseFRfewXAa/ssxAC+iUVR6KUMh1PE2wXLitfeI6JLvVtrBYswm2I7CtY0q8n5AGimHWVXJPLfGV7m0BAkEA+fqFt2LXbLtyg6wZyxMA/cnmt5Nt3U2dAu77MzFJvibANUNHE4HPLZxjGNXN+a6m0K6TD4kDdh5HfUYLWWRBYQJBANK3carmulBwqzcDBjsJ0YrIONBpCAsXxk8idXb8jL9aNIg15Wumm2enqqObahDHB5jnGOLmbasizvSVqypfM9UCQCQl8xIqy+YgURXzXCN+kwUgHinrutZms87Jyi+D8Br8NY0+Nlf+zHvXAomD2W5CsEK7C+8SLBr3k/TsnRWHJuECQHFE9RA2OP8WoaLPuGCyFXaxzICThSRZYluVnWkZtxsBhW2W8z1b8PvWUE7kMy7TnkzeJS2LSnaNHoyxi7IaPQUCQCwWU4U+v4lD7uYBw00Ga/xt+7+UqFPlPVdz1yyr4q24Zxaw0LgmuEvgU5dycq8N7JxjTubX0MIRR+G9fmDBBl8=\r\n-----END RSA PRIVATE KEY-----' -export const authorize = (user = {}) => jwt.sign(user, privateKey, { expiresIn: '6h', algorithm: 'RS256' }); - -jwt.sign({ user: 'foo' }, 'secret'); - -const key = 'shhh'; -const secret = key; -jwt.sign({ user: 'foo' }, secret); -``` - -## Compliant Code Examples -```typescript -import jwt from "jsonwebtoken"; -import config from './config'; - -const payload = {foo: 'bar'}; -const secret3 = process.env.SECRET -const token5 = jwt.sign(payload, secret3) - -jwt.sign(payload, process.env.KEY); -jwt.sign(payload, config.secret); - -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md b/content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md deleted file mode 100644 index 99f3642ab53fa..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/jwt-hardcoded-secret - language: TypeScript - severity: Error -title: Do not use hardcoded secret with a JWT ---- -## Metadata -**ID:** `typescript-node-security/jwt-hardcoded-secret` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Security - -## Description -Never hardcode secrets. Instead, use secrets from environment variables or a secret vault. - -## Non-Compliant Code Examples -```typescript -import jwt from "jsonwebtoken"; - -const token = jwt.sign({ foo: "bar" }, "secret"); - -const token = jwt.sign({ foo: "bar" }, 'secret'); - -const token = jwt.sign({ foo: "bar" }, `secret`); -``` - -## Compliant Code Examples -```typescript -import jwt from "jsonwebtoken"; - -const token = jwt.sign({ foo: "bar" }, process.env.JWT_SECRET); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md b/content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md deleted file mode 100644 index 2b87b2add2635..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/jwt-sensitive-data.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/jwt-sensitive-data - language: TypeScript - severity: Warning -title: Do not put sensitive data in objects ---- -## Metadata -**ID:** `typescript-node-security/jwt-sensitive-data` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Never include sensitive information in a JWT. Instead, only use non-personal information to identify the end-user. - -## Non-Compliant Code Examples -```typescript -jwt.sign( - { user: { email: 'foo@bar.com' }} -) - -jwt.sign( - { user: { lastname: 'babar' }} -) -``` - -## Compliant Code Examples -```typescript -jwt.sign( - {user: { id: 42 }} -) -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md b/content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md deleted file mode 100644 index 66f6ab586a364..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/jwt-weak-encryption.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/jwt-weak-encryption - language: TypeScript - severity: Warning -title: Use default encryption from the JWT library ---- -## Metadata -**ID:** `typescript-node-security/jwt-weak-encryption` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not use `none` as a validation algorithm for a JWT token. The none algorithm assumes that the token has been verified, which would allow attacker to create a token that would be automatically validated. - -Never use the `none` algorithm, always use a valid algorithm as directed by [the documentation](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback). - -## Non-Compliant Code Examples -```typescript -jwt.verify(token, secret, { algorithms: ['RS256', 'none'] }, func); -jwt.verify(token, secret, { algorithms: ['none', 'RS256'] }, func); -``` - -## Compliant Code Examples -```typescript -jwt.verify(token, secret, { algorithms: ['RS256', 'HS256'] }, func); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md b/content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md deleted file mode 100644 index 2f521d7c13ddc..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/log-sensitive-data.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/log-sensitive-data - language: TypeScript - severity: Warning -title: Avoid logging sensitive data ---- -## Metadata -**ID:** `typescript-node-security/log-sensitive-data` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not log sensitive data such as user id, email or other personal data (first name, last name, etc). - -## Non-Compliant Code Examples -```typescript -console.log("email from user" + user.email); -console.log(`email from user ${user.email}`); -logger.info(`email from user ${user.email}`); -logger.info(`email from user ${user.name}: ${user.email}`); -logger.info(`email from user ${username}: ${user.email}`); -logger.warn(email); -logger.error(`email from user ${email}`); - -foobar.error(`email from user ${email}`); - -logger.foobar(`email from user ${email}`); - -``` - -## Compliant Code Examples -```typescript -console.log("email from user" + user.id); -console.log(`email from user ${user.uuid}`); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md b/content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md deleted file mode 100644 index e3e3d640dc4be..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/oauth2-hardcoded-secret - language: TypeScript - severity: Warning -title: Do not use hardcoded secret for OAuth2 providers ---- -## Metadata -**ID:** `typescript-node-security/oauth2-hardcoded-secret` - -**Language:** TypeScript - -**Severity:** Warning - -**Category:** Security - -## Description -Do not put hardcoded credentials in code. Instead, put secrets in environment variables or a vault. - -## Non-Compliant Code Examples -```typescript -passport.use(new OAuth2Strategy({ - authorizationURL: 'https://www.example.com/oauth2/authorize', - tokenURL: 'https://www.example.com/oauth2/token', - clientID: `client_id`, - clientSecret: 'secret_id', - callbackURL: "http://localhost:3000/auth/example/callback" - }, - function(accessToken, refreshToken, profile, cb) { - User.findOrCreate({ exampleId: profile.id }, function (err, user) { - return cb(err, user); - }); - } -)); -``` - -## Compliant Code Examples -```typescript -passport.use(new OAuth2Strategy({ - authorizationURL: 'https://www.example.com/oauth2/authorize', - tokenURL: 'https://www.example.com/oauth2/token', - clientID: process.env.EXAMPLE_CLIENT_ID, - clientSecret: process.env.EXAMPLE_CLIENT_SECRET, - callbackURL: "http://localhost:3000/auth/example/callback" - }, - function(accessToken, refreshToken, profile, cb) { - User.findOrCreate({ exampleId: profile.id }, function (err, user) { - return cb(err, user); - }); - } -)); -``` diff --git a/content/en/static_analysis/rules/typescript-node-security/sql-injection.md b/content/en/static_analysis/rules/typescript-node-security/sql-injection.md deleted file mode 100644 index d6a64e610055a..0000000000000 --- a/content/en/static_analysis/rules/typescript-node-security/sql-injection.md +++ /dev/null @@ -1,276 +0,0 @@ ---- -dependencies: [] -disable_edit: true -kind: documentation -meta: - category: Security - id: typescript-node-security/sql-injection - language: TypeScript - severity: Error -title: Avoid SQL injection ---- -## Metadata -**ID:** `typescript-node-security/sql-injection` - -**Language:** TypeScript - -**Severity:** Error - -**Category:** Security - -## Description -Check for variable declarations in a SQL statement where there is potential for SQL injections. - -#### Learn More - - - [CWE-89: Improper Neutralization of Special Elements used in an SQL Command](https://cwe.mitre.org/data/definitions/89.html) - -## Non-Compliant Code Examples -```typescript -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - // only allow apple or orange related searches - if (!criteria.startsWith("apple") || !criteria.startsWith("orange")) { - res.status(400).send() - return - } - models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```typescript -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - criteria.replace(/"|'|;|and|or/i, "") - models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```typescript -const injectionChars = /"|'|;|and|or|;|#/i; - -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - if (criteria.match(injectionChars)) { - res.status(400).send() - return - } - models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```typescript -module.exports = function searchProducts () { - return (req: Request, res: Response, next: NextFunction) => { - let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' - criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - models.sequelize.query("SELECT * FROM Products WHERE ((name LIKE '%"+criteria+"%' OR description LIKE '%"+criteria+"%') AND deletedAt IS NULL) ORDER BY name") - .then(([products]: any) => { - const dataString = JSON.stringify(products) - for (let i = 0; i < products.length; i++) { - products[i].name = req.__(products[i].name) - products[i].description = req.__(products[i].description) - } - res.json(utils.queryResultToJson(products)) - }).catch((error: ErrorWithParent) => { - next(error.parent) - }) - } -} -``` - -```typescript -var express = require('express') - -var app = express() -const Sequelize = require('sequelize'); -const sequelize = new Sequelize('database', 'username', 'password', { - dialect: 'sqlite', - storage: 'data/juiceshop.sqlite' -}); - -app.post('/login', function (req, res) { - sequelize.query('SELECT * FROM Products WHERE name LIKE ' + req.body.username); - }) - - -app.post('/update', function (req, res) { - sequelize.query('UPDATE products SET bla=bli WHERE name LIKE ' + req.body.username); - }) - - - -app.post('/remove', function (req, res) { - sequelize.query('DELETE FROM product WHERE name LIKE ' + req.body.username); - }) -``` - -```typescript -const express = require('express'); -const router = express.Router() - -const config = require('../../config') -const mysql = require('mysql'); -const connection = mysql.createConnection({ - host : config.MYSQL_HOST, - port : config.MYSQL_PORT, - user : config.MYSQL_USER, - password : config.MYSQL_PASSWORD, - database : config.MYSQL_DB_NAME, -}); - -connection.connect(); - -router.get('/example1/user/:id', (req,res) => { - let userId = req.params.id; - let query = { - sql : "SELECT * FROM users WHERE id=" + userId - } - connection.query(query,(err, result) => { - res.json(result); - }); -}) - -router.get('/example2/user/:id', (req,res) => { - let userId = req.params.id; - connection.query("SELECT * FROM users WHERE id=" + userId,(err, result) => { - res.json(result); - }); -}) - -router.get('/example3/user/:id', (req,res) => { - let userId = req.params.id; - connection.query({ - sql : "SELECT * FROM users WHERE id=" +userId - },(err, result) => { - res.json(result); - }); -}) - - -module.exports = router -``` - -## Compliant Code Examples -```typescript -import {BasketModel} from "../../../models/basket"; - -module.exports = function login () { - function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { - BasketModel.findOrCreate({ where: { UserId: user.data.id } }) - .then(([basket]: [BasketModel, boolean]) => { - const token = security.authorize(user) - user.bid = basket.id // keep track of original basket - security.authenticatedUsers.put(token, user) - res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) - }).catch((error: Error) => { - next(error) - }) - } - - return (req: Request, res: Response, next: NextFunction) => { - models.sequelize.query(`SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL`, - { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) - .then((authenticatedUser: { data: User }) => { - const user = utils.queryResultToJson(authenticatedUser) - if (user.data?.id && user.data.totpSecret !== '') { - res.status(401).json({ - status: 'totp_token_required', - data: { - tmpToken: security.authorize({ - userId: user.data.id, - type: 'password_valid_needs_second_factor_token' - }) - } - }) - } else if (user.data?.id) { - afterLogin(user, res, next) - } else { - res.status(401).send(res.__('Invalid email or password.')) - } - }).catch((error: Error) => { - next(error) - }) - } -``` - -```typescript -import {BasketModel} from "../../../models/basket"; - -module.exports = function login () { - function afterLogin (user: { data: User, bid: number }, res: Response, next: NextFunction) { - BasketModel.findOrCreate({ where: { UserId: user.data.id } }) - .then(([basket]: [BasketModel, boolean]) => { - const token = security.authorize(user) - user.bid = basket.id // keep track of original basket - security.authenticatedUsers.put(token, user) - res.json({ authentication: { token, bid: basket.id, umail: user.data.email } }) - }).catch((error: Error) => { - next(error) - }) - } - - return (req: Request, res: Response, next: NextFunction) => { - models.sequelize.query('SELECT * FROM Users WHERE email = $1 AND password = $2 AND deletedAt IS NULL', - { bind: [ req.body.email, req.body.password ], model: models.User, plain: true }) - .then((authenticatedUser: { data: User }) => { - const user = utils.queryResultToJson(authenticatedUser) - if (user.data?.id && user.data.totpSecret !== '') { - res.status(401).json({ - status: 'totp_token_required', - data: { - tmpToken: security.authorize({ - userId: user.data.id, - type: 'password_valid_needs_second_factor_token' - }) - } - }) - } else if (user.data?.id) { - afterLogin(user, res, next) - } else { - res.status(401).send(res.__('Invalid email or password.')) - } - }).catch((error: Error) => { - next(error) - }) - } -``` diff --git a/local/bin/py/build/configurations/pull_config.yaml b/local/bin/py/build/configurations/pull_config.yaml index 51cba83ee0ad4..006e138e8b4ad 100644 --- a/local/bin/py/build/configurations/pull_config.yaml +++ b/local/bin/py/build/configurations/pull_config.yaml @@ -343,15 +343,13 @@ globs: - 'README.md' options: - dest_path: '/static_analysis/' + dest_path: '/continuous_integration/static_analysis/' file_name: 'circleci_orbs.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md"] title: Static Analysis and CircleCI Orbs kind: documentation description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. - aliases: - - /continuous_integration/static_analysis/circleci_orbs - repo_name: datadog-static-analyzer-github-action contents: @@ -360,15 +358,13 @@ globs: - 'README.md' options: - dest_path: '/static_analysis/' + dest_path: '/continuous_integration/static_analysis/' file_name: 'github_actions.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md"] title: Static Analysis and GitHub Actions kind: documentation description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. - aliases: - - /continuous_integration/static_analysis/github_actions - repo_name: datadog-static-analyzer-rule-docs contents: @@ -377,7 +373,7 @@ globs: - rulesets/**/*.md options: - dest_dir: '/static_analysis/rules/' + dest_dir: '/continuous_integration/static_analysis/rules/' path_to_remove: 'rulesets/' front_matters: disable_edit: true diff --git a/local/bin/py/build/configurations/pull_config_preview.yaml b/local/bin/py/build/configurations/pull_config_preview.yaml index 90d444307c516..4e01a7f401c27 100644 --- a/local/bin/py/build/configurations/pull_config_preview.yaml +++ b/local/bin/py/build/configurations/pull_config_preview.yaml @@ -1,6 +1,6 @@ --- - config: - cache_enabled: false + cache_enabled: true - data: - org_name: jenkinsci @@ -344,15 +344,13 @@ globs: - 'README.md' options: - dest_path: '/static_analysis/' + dest_path: '/continuous_integration/static_analysis/' file_name: 'circleci_orbs.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md"] title: Static Analysis and CircleCI Orbs kind: documentation description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. - aliases: - - /continuous_integration/static_analysis/circleci_orbs - repo_name: datadog-static-analyzer-github-action contents: @@ -361,15 +359,13 @@ globs: - 'README.md' options: - dest_path: '/static_analysis/' + dest_path: '/continuous_integration/static_analysis/' file_name: 'github_actions.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md"] title: Static Analysis and GitHub Actions kind: documentation description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. - aliases: - - /continuous_integration/static_analysis/github_actions - repo_name: datadog-static-analyzer-rule-docs contents: @@ -378,7 +374,7 @@ globs: - rulesets/**/*.md options: - dest_dir: '/static_analysis/rules/' + dest_dir: '/continuous_integration/static_analysis/rules/' path_to_remove: 'rulesets/' front_matters: disable_edit: true From 0df72b6cc7bce63e3979a3e42c6c659b5c000ecb Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:36:20 -0800 Subject: [PATCH 07/12] Cleanup Slugs + Add Aliases --- config/_default/menus/menus.en.yaml | 30 +- .../static_analysis/rules/_index.md | 1521 ----------------- .../dora_metrics/_index.md | 2 + .../quality_gates/_index.md | 2 + .../static_analysis/_index.md | 2 + .../py/build/configurations/pull_config.yaml | 10 +- .../configurations/pull_config_preview.yaml | 10 +- 7 files changed, 35 insertions(+), 1542 deletions(-) delete mode 100644 content/en/continuous_integration/static_analysis/rules/_index.md rename content/en/{continuous_integration => }/dora_metrics/_index.md (99%) rename content/en/{continuous_integration => }/quality_gates/_index.md (99%) rename content/en/{continuous_integration => }/static_analysis/_index.md (99%) diff --git a/config/_default/menus/menus.en.yaml b/config/_default/menus/menus.en.yaml index 4d3311bec3fea..dea51276097e8 100644 --- a/config/_default/menus/menus.en.yaml +++ b/config/_default/menus/menus.en.yaml @@ -2617,37 +2617,37 @@ main: parent: cd_explorer weight: 303 - name: DORA Metrics - url: continuous_integration/dora_metrics/ + url: dora_metrics/ pre: ci parent: software_delivery_heading - identifier: ci_explorer_dora_metrics + identifier: dora_metrics weight: 170000 - name: Static Analysis - url: continuous_integration/static_analysis/ + url: static_analysis/ pre: ci parent: software_delivery_heading - identifier: ci_static_analysis + identifier: static_analysis weight: 180000 - name: Rules - url: continuous_integration/static_analysis/rules - parent: ci_static_analysis - identifier: ci_static_analysis_rules + url: static_analysis/rules + parent: static_analysis + identifier: static_analysis_rules weight: 101 - name: CircleCI Orbs - url: continuous_integration/static_analysis/circleci_orbs - parent: ci_static_analysis - identifier: ci_static_analysis_circleci_orbs + url: static_analysis/circleci_orbs + parent: static_analysis + identifier: static_analysis_circleci_orbs weight: 102 - name: GitHub Actions - url: continuous_integration/static_analysis/github_actions - parent: ci_static_analysis - identifier: ci_static_analysis_github_actions + url: static_analysis/github_actions + parent: static_analysis + identifier: static_analysis_github_actions weight: 103 - name: Quality Gates - url: continuous_integration/quality_gates/ + url: quality_gates/ pre: ci parent: software_delivery_heading - identifier: ci_quality_gates + identifier: quality_gates weight: 190000 - name: Database Monitoring url: database_monitoring/ diff --git a/content/en/continuous_integration/static_analysis/rules/_index.md b/content/en/continuous_integration/static_analysis/rules/_index.md deleted file mode 100644 index ccfc294a23faa..0000000000000 --- a/content/en/continuous_integration/static_analysis/rules/_index.md +++ /dev/null @@ -1,1521 +0,0 @@ ---- -title: Static Analysis Rules -kind: documentation -description: View rules for multiple languages for Static Analysis. -is_beta: true -docker_best_practices_data: - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/absolute-workdir" - tag: "absolute-workdir" - text: "Use absolute workdir" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/alias-must-be-unique" - tag: "alias-must-be-unique" - text: "FROM aliases must be unique" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/apt-get-yes" - tag: "apt-get-yes" - text: "Always use -y with apt-get install" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/apt-pin-version" - tag: "apt-pin-version" - text: "Always pin versions in apt-get install" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/avoid-chmod-777" - tag: "avoid-chmod-777" - text: "Do not give wide permissions on files" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant" - tag: "avoid-commands-not-relevant" - text: "Avoid commands not made for containers" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/avoid-http" - tag: "avoid-http" - text: "Avoid fetching data from HTTP endpoint" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/dnf-use-y" - tag: "dnf-use-y" - text: "Always use -y with dnf install" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/expose-admin-ports" - tag: "expose-admin-ports" - text: "Do not expose sensitive ports" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/expose-valid-port" - tag: "expose-valid-port" - text: "Expose a valid UNIX port number" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/image-avoid-digest" - tag: "image-avoid-digest" - text: "Do not use the digest to pull an image" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/maintainer-deprecated" - tag: "maintainer-deprecated" - text: "The maintainer entry is deprecated" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/multiple-cmd" - tag: "multiple-cmd" - text: "Do not use multiple CMD" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/multiple-entrypoint" - tag: "multiple-entrypoint" - text: "Do not use multiple CMD" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/multiple-healthcheck" - tag: "multiple-healthcheck" - text: "Do not use multiple HEALTHCHECK" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/no-root-user" - tag: "no-root-user" - text: "Last user should not be root" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/pip-no-cache" - tag: "pip-no-cache" - text: "Do not use cache when installing packages" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/pip-pin-versions" - tag: "pip-pin-versions" - text: "Always pin versions with pip" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/tag-image-version" - tag: "tag-image-version" - text: "Always tag the version of an image" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/yum-use-y" - tag: "yum-use-y" - text: "Always use -y with yum install" - - link: "/continuous_integration/static_analysis/rules/docker-best-practices/zypper-use-y" - tag: "zypper-use-y" - text: "Always use -y with zypper install" -javascript_best_practices_data: - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/for-direction" - tag: "for-direction" - text: "Check for loop is moving in the right direction" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/new-parens" - tag: "new-parens" - text: "Invoking a constructor must use parentheses" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-alert" - tag: "no-alert" - text: "Avoid the use of alert, confirm, and prompt" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-async-promise-executor" - tag: "no-async-promise-executor" - text: "Promise executor cannot be an async function" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-caller" - tag: "no-caller" - text: "Avoid the use of arguments.caller or arguments.callee" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-case-declarations" - tag: "no-case-declarations" - text: "Avoid lexical declarations in case clauses" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-compare-neg-zero" - tag: "no-compare-neg-zero" - text: "Direct comparison with -0 detected" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-cond-assign" - tag: "no-cond-assign" - text: "Avoid assignment operators in conditional expressions" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-console" - tag: "no-console" - text: "Avoid leaving console debug statements" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-debugger" - tag: "no-debugger" - text: "Disallow the use of debugger" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-delete-var" - tag: "no-delete-var" - text: "Avoid using delete on variables directly" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-dupe-args" - tag: "no-dupe-args" - text: "Function parameters redeclared" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-dupe-class-members" - tag: "no-dupe-class-members" - text: "Avoid duplicate class members" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-dupe-keys" - tag: "no-dupe-keys" - text: "Avoid duplicate keys in object literals" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-duplicate-case" - tag: "no-duplicate-case" - text: "Avoid duplicate case labels" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-empty" - tag: "no-empty" - text: "Avoid empty block statements" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-empty-character-class" - tag: "no-empty-character-class" - text: "Avoid empty character classes in regular expressions" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-empty-pattern" - tag: "no-empty-pattern" - text: "Avoid empty destructuring patterns" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-ex-assign" - tag: "no-ex-assign" - text: "Avoid reassigning exceptions in catch clauses" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-implied-eval" - tag: "no-implied-eval" - text: "Prevent the use methods similar to eval()" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-import-assign" - tag: "no-import-assign" - text: "Prevent assigning to imported bindings" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-inner-declarations" - tag: "no-inner-declarations" - text: "Avoid variable or function declaration in nested blocks" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-iterator" - tag: "no-iterator" - text: "Avoid the use of the __iterator__ property" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-loss-of-precision" - tag: "no-loss-of-precision" - text: "Avoid numbers that lose precision" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-new-symbol" - tag: "no-new-symbol" - text: "Avoid new statements with the Symbol object" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-octal" - tag: "no-octal" - text: "Avoid using octal literals to prevent unexpected behavior" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-proto" - tag: "no-proto" - text: "Avoid the use of the __proto__ property" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-script-url" - tag: "no-script-url" - text: "Avoid using JavaScript in URLs" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-unsafe-negation" - tag: "no-unsafe-negation" - text: "Avoid negating the left operand of relational operators" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/no-with" - tag: "no-with" - text: "The with statement can lead to ambiguous code" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/require-yield" - tag: "require-yield" - text: "Require yield in generator functions" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/use-isnan" - tag: "use-isnan" - text: "Avoid direct comparison with NaN" - - link: "/continuous_integration/static_analysis/rules/javascript-best-practices/valid-typeof" - tag: "valid-typeof" - text: "Compare typeof expressions against valid strings" -javascript_browser_security_data: - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/event-check-origin" - tag: "event-check-origin" - text: "Check origin of events" - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/inner-outer-html" - tag: "inner-outer-html" - text: "Do not modify innerHTML or outerHTML" - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/insecure-websocket" - tag: "insecure-websocket" - text: "Websockets must use SSL connections" - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data" - tag: "local-storage-sensitive-data" - text: "Do not store sensitive data to local storage" - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/manual-sanitization" - tag: "manual-sanitization" - text: "Avoid manual sanitization of inputs" - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin" - tag: "postmessage-permissive-origin" - text: "Specify origin in postMessage" - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html" - tag: "react-dangerously-inner-html" - text: "Do not inject unsanitized HTML" - - link: "/continuous_integration/static_analysis/rules/javascript-browser-security/regexp-non-literal" - tag: "regexp-non-literal" - text: "Do not use variable for regular expressions" -javascript_code_style_data: - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/assignment-name" - tag: "assignment-name" - text: "Assigment name should use camelCase" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/class-name" - tag: "class-name" - text: "Class name should be PascalCase" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/eqeqeq" - tag: "eqeqeq" - text: "Enforce the use of === and !==" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/func-name-matching" - tag: "func-name-matching" - text: "Function names must match the name of the assignation." - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/func-names" - tag: "func-names" - text: "Enforce named function expressions" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/function-naming" - tag: "function-naming" - text: "Function name should use camelCase or PascalCase" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/max-class-lines" - tag: "max-class-lines" - text: "Classes must be less than 100 lines" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/max-function-lines" - tag: "max-function-lines" - text: "Functions must be less than 200 lines" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/max-params" - tag: "max-params" - text: "Enforce a maximum number of parameters in a function" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/method-name" - tag: "method-name" - text: "Method name should use camelCase" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-array-constructor" - tag: "no-array-constructor" - text: "Avoid Array constructors" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-div-regex" - tag: "no-div-regex" - text: "Avoid equal signs at the beginning of regular expressions" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-duplicate-imports" - tag: "no-duplicate-imports" - text: "Avoid duplicate module imports" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-floating-decimal" - tag: "no-floating-decimal" - text: "Avoid leading or trailing decimal points in numbers" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-lonely-if" - tag: "no-lonely-if" - text: "Avoid if statements as the only statement in else blocks" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-multi-assign" - tag: "no-multi-assign" - text: "Avoid the use of chained assignment expressions" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-new" - tag: "no-new" - text: "Avoid new operators outside of assignments or comparisons" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-new-func" - tag: "no-new-func" - text: "Avoid new operators with the Function object" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-new-object" - tag: "no-new-object" - text: "Avoid Object constructors" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-return-assign" - tag: "no-return-assign" - text: "Avoid assignment operators in return statements" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-self-compare" - tag: "no-self-compare" - text: "Avoid comparisons where both sides are exactly the same" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/no-var" - tag: "no-var" - text: "Require let or const instead of var" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/parameter-name" - tag: "parameter-name" - text: "Parameter name should use camelCase" - - link: "/continuous_integration/static_analysis/rules/javascript-code-style/radix" - tag: "radix" - text: "Consistent use of the radix argument using parseInt" -javascript_common_security_data: - - link: "/continuous_integration/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http" - tag: "axios-avoid-insecure-http" - text: "Avoid insecure HTTP requests with Axios" - - link: "/continuous_integration/static_analysis/rules/javascript-common-security/unique-function-arguments" - tag: "unique-function-arguments" - text: "Function argument names should be unique" - - link: "/continuous_integration/static_analysis/rules/javascript-common-security/xml-no-external-entities" - tag: "xml-no-external-entities" - text: "Do not use external XML entities" -javascript_express_data: - - link: "/continuous_integration/static_analysis/rules/javascript-express/access-restriction" - tag: "access-restriction" - text: "Limit exposure to sensitive directories and files" - - link: "/continuous_integration/static_analysis/rules/javascript-express/default-session-config" - tag: "default-session-config" - text: "Enforce overriding default config" - - link: "/continuous_integration/static_analysis/rules/javascript-express/external-filename-upload" - tag: "external-filename-upload" - text: "Avoid using unsanitized user input with sendFile" - - link: "/continuous_integration/static_analysis/rules/javascript-express/external-resource" - tag: "external-resource" - text: "Avoid rendering resource based on unsanitized user input" - - link: "/continuous_integration/static_analysis/rules/javascript-express/hardcoded-secret" - tag: "hardcoded-secret" - text: "Avoid using a hard-coded secret" - - link: "/continuous_integration/static_analysis/rules/javascript-express/https-protocol-missing" - tag: "https-protocol-missing" - text: "Use `https` protocol over `http`" - - link: "/continuous_integration/static_analysis/rules/javascript-express/insecure-allow-origin" - tag: "insecure-allow-origin" - text: "Avoid using an insecure Access-Control-Allow-Origin header" - - link: "/continuous_integration/static_analysis/rules/javascript-express/insecure-cookie" - tag: "insecure-cookie" - text: "Avoid setting insecure cookie settings" - - link: "/continuous_integration/static_analysis/rules/javascript-express/jwt-not-revoked" - tag: "jwt-not-revoked" - text: "Ensure an isRevoked method is used for tokens" - - link: "/continuous_integration/static_analysis/rules/javascript-express/missing-helmet" - tag: "missing-helmet" - text: "Express application should use Helmet" - - link: "/continuous_integration/static_analysis/rules/javascript-express/path-traversal" - tag: "path-traversal" - text: "Avoid allowing access to unintended directories or files" - - link: "/continuous_integration/static_analysis/rules/javascript-express/reduce-server-fingerprinting" - tag: "reduce-server-fingerprinting" - text: "Server fingerprinting misconfiguration" - - link: "/continuous_integration/static_analysis/rules/javascript-express/xss-vulnerability" - tag: "xss-vulnerability" - text: "Avoid sending unsanitized user input in response" -javascript_inclusive_data: - - link: "/continuous_integration/static_analysis/rules/javascript-inclusive/comments" - tag: "comments" - text: "Check comments for wording issues" - - link: "/continuous_integration/static_analysis/rules/javascript-inclusive/declarations" - tag: "declarations" - text: "Check declaration names for wording issues" - - link: "/continuous_integration/static_analysis/rules/javascript-inclusive/formal-parameters" - tag: "formal-parameters" - text: "Check parameter names for wording issues" - - link: "/continuous_integration/static_analysis/rules/javascript-inclusive/identifiers" - tag: "identifiers" - text: "Check identifier names for wording issues" -javascript_node_security_data: - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/argon2" - tag: "argon2" - text: "Use strong security mechanisms with argon2" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/avoid-crypto-rc4" - tag: "avoid-crypto-rc4" - text: "Avoid RC4" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/avoid-crypto-sha1" - tag: "avoid-crypto-sha1" - text: "Avoid SHA1 security protocol" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/avoid-des" - tag: "avoid-des" - text: "Avoid DES and 3DES" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/chmod-permissions" - tag: "chmod-permissions" - text: "Do not give 777 permissions to a file" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/command-injection" - tag: "command-injection" - text: "Avoid command injection" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash" - tag: "crypto-avoid-weak-hash" - text: "Avoid weak hash algorithm from CryptoJS" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detect-buffer-noassert" - tag: "detect-buffer-noassert" - text: "Avoid calls to 'buffer' with 'noAssert' flag set" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detect-child-process" - tag: "detect-child-process" - text: "Avoid instances of 'child_process' and non-literal 'exec()'" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detect-eval-with-expression" - tag: "detect-eval-with-expression" - text: "Avoid `eval` with expressions" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detect-new-buffer" - tag: "detect-new-buffer" - text: "Avoid Buffer(argument) with non-literal values" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename" - tag: "detect-non-literal-fs-filename" - text: "Avoid variables in 'fs' calls filename argument" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detect-non-literal-regexp" - tag: "detect-non-literal-regexp" - text: "Detects non-literal values in regular expressions" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detect-non-literal-require" - tag: "detect-non-literal-require" - text: "Avoid require with non-literal values" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/detected-jwt-token" - tag: "detected-jwt-token" - text: "Detects hardcoded JWT tokens within the codebase." - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/hardcoded-hmac-key" - tag: "hardcoded-hmac-key" - text: "Avoid hardcoded HMAC keys" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/insecure-hash" - tag: "insecure-hash" - text: "Do not use weak hash functions" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage" - tag: "insecure-jwt-secret-usage" - text: "Insecure Usage of a Static Secret in JWT Signing" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret" - tag: "jwt-hardcoded-secret" - text: "Do not use hardcoded secret with a JWT" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/jwt-sensitive-data" - tag: "jwt-sensitive-data" - text: "Do not put sensitive data in objects" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/jwt-weak-encryption" - tag: "jwt-weak-encryption" - text: "Use default encryption from the JWT library" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/log-sensitive-data" - tag: "log-sensitive-data" - text: "Avoid logging sensitive data" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret" - tag: "oauth2-hardcoded-secret" - text: "Do not use hardcoded secret for OAuth2 providers" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/sql-injection" - tag: "sql-injection" - text: "Avoid SQL injection" - - link: "/continuous_integration/static_analysis/rules/javascript-node-security/variable-sql-statement-injection" - tag: "variable-sql-statement-injection" - text: "Avoid SQL injections" -jsx_react_data: - - link: "/continuous_integration/static_analysis/rules/jsx-react/jsx-key" - tag: "jsx-key" - text: "Prevent missing key props in iterators/collection literals" - - link: "/continuous_integration/static_analysis/rules/jsx-react/jsx-no-comment-textnodes" - tag: "jsx-no-comment-textnodes" - text: "Avoid comments from being inserted as text nodes" - - link: "/continuous_integration/static_analysis/rules/jsx-react/jsx-no-duplicate-key" - tag: "jsx-no-duplicate-key" - text: "Ensures unique key prop" - - link: "/continuous_integration/static_analysis/rules/jsx-react/jsx-no-duplicate-props" - tag: "jsx-no-duplicate-props" - text: "Avoid duplicate properties in JSX" - - link: "/continuous_integration/static_analysis/rules/jsx-react/jsx-no-target-blank" - tag: "jsx-no-target-blank" - text: "Prevent target='_blank' security risks" - - link: "/continuous_integration/static_analysis/rules/jsx-react/no-children-prop" - tag: "no-children-prop" - text: "Avoid passing children as props" - - link: "/continuous_integration/static_analysis/rules/jsx-react/no-danger-with-children" - tag: "no-danger-with-children" - text: "Avoid using children with dangerouslySetInnerHTML" - - link: "/continuous_integration/static_analysis/rules/jsx-react/no-deprecated" - tag: "no-deprecated" - text: "Avoid deprecated methods" - - link: "/continuous_integration/static_analysis/rules/jsx-react/no-render-return-value" - tag: "no-render-return-value" - text: "Avoid usage of the return value of ReactDOM.render" - - link: "/continuous_integration/static_analysis/rules/jsx-react/no-string-refs" - tag: "no-string-refs" - text: "Avoid using string references" - - link: "/continuous_integration/static_analysis/rules/jsx-react/require-render-return" - tag: "require-render-return" - text: "Enforce class for returning value in render function" -python_best_practices_data: - - link: "/continuous_integration/static_analysis/rules/python-best-practices/ambiguous-class-name" - tag: "ambiguous-class-name" - text: "make sure class names are readable" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/ambiguous-function-name" - tag: "ambiguous-function-name" - text: "make sure function names are readable" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/ambiguous-variable-name" - tag: "ambiguous-variable-name" - text: "make sure variable names are readable" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/any-type-disallow" - tag: "any-type-disallow" - text: "do not use Any type" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/argument-same-name" - tag: "argument-same-name" - text: "do not have arguments with the same name" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/assertraises-specific-exception" - tag: "assertraises-specific-exception" - text: "assertRaises must check for a specific exception" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/avoid-duplicate-keys" - tag: "avoid-duplicate-keys" - text: "Avoid duplicate keys in dictionaries" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/avoid-string-concat" - tag: "avoid-string-concat" - text: "avoid string concatenation" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/class-methods-use-self" - tag: "class-methods-use-self" - text: "Class methods should not use self" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/collection-while-iterating" - tag: "collection-while-iterating" - text: "do not modify a dictionary while iterating on it" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership" - tag: "comment-fixme-todo-ownership" - text: "TODO and FIXME comments must have ownership" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/comparison-constant-left" - tag: "comparison-constant-left" - text: "in comparisons, variables must be left" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/condition-similar-block" - tag: "condition-similar-block" - text: "if conditions must have different code blocks" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined" - tag: "ctx-manager-enter-exit-defined" - text: "ensure that both __exit__ and __enter__ are defined" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/dataclass-special-methods" - tag: "dataclass-special-methods" - text: "do not use special method on data class" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/equal-basic-types" - tag: "equal-basic-types" - text: "check equal is used on consistent basic types" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/exception-inherit" - tag: "exception-inherit" - text: "ensure exception inherit a base exception" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/finally-no-break-continue-return" - tag: "finally-no-break-continue-return" - text: "do not use break or continue in finally block" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/function-already-exists" - tag: "function-already-exists" - text: "a function must be defined only once" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/function-variable-argument-name" - tag: "function-variable-argument-name" - text: "Do not assign to function arguments" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/generic-exception-last" - tag: "generic-exception-last" - text: "If using generic exception, it should be last" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/get-set-arguments" - tag: "get-set-arguments" - text: "getter/setter must have 1 or 2 arguments respectively" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/if-return-no-else" - tag: "if-return-no-else" - text: "when an if condition returns an value, else is not necessary" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/import-modules-twice" - tag: "import-modules-twice" - text: "module imported twice" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/import-single-module" - tag: "import-single-module" - text: "only one module to import per import statement" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/init-call-parent" - tag: "init-call-parent" - text: "use super() to call the parent constructor" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/init-method-required" - tag: "init-method-required" - text: "ensure classes have an __init__ method" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/init-no-return-value" - tag: "init-no-return-value" - text: "No return in an __init__ function" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/invalid-strip-call" - tag: "invalid-strip-call" - text: "strip() argument should not have duplicate characters" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/logging-no-format" - tag: "logging-no-format" - text: "do not use format string with logging functions" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/method-hidden" - tag: "method-hidden" - text: "a method has the same name than an attribute" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/nested-blocks" - tag: "nested-blocks" - text: "Do not have too many nested blocks" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-assert" - tag: "no-assert" - text: "do not use assert in production code" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-assert-on-tuples" - tag: "no-assert-on-tuples" - text: "no assert on tuples" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-bare-except" - tag: "no-bare-except" - text: "do not use bare except" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-bare-raise" - tag: "no-bare-raise" - text: "Do not use a raise statement without a specific exception" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-base-exception" - tag: "no-base-exception" - text: "do not raise base exception" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-datetime-today" - tag: "no-datetime-today" - text: "do not use datetime.today()" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-double-not" - tag: "no-double-not" - text: "do not use double negation" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-double-unary-operator" - tag: "no-double-unary-operator" - text: "do not use operator -- and ++" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-duplicate-base-class" - tag: "no-duplicate-base-class" - text: "use a base class only once" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-equal-unary" - tag: "no-equal-unary" - text: "do not use operations =+ and =-" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-exit" - tag: "no-exit" - text: "do not use exit()" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-generic-exception" - tag: "no-generic-exception" - text: "Do not use generic exceptions" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-if-true" - tag: "no-if-true" - text: "do not compare to True in a condition" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-range-loop-with-len" - tag: "no-range-loop-with-len" - text: "Do not use for i in range(len())" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/no-silent-exception" - tag: "no-silent-exception" - text: "Do not ignore Exception with a pass statement" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/open-add-flag" - tag: "open-add-flag" - text: "do not define an open flag for reading" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/os-environ-no-assign" - tag: "os-environ-no-assign" - text: "assigning to os.environ does not clear the environment" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/raising-not-implemented" - tag: "raising-not-implemented" - text: "Do not raise NotImplemented - it does not exists" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/return-bytes-not-string" - tag: "return-bytes-not-string" - text: "__bytes__ method should returns bytes, not string" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/return-outside-function" - tag: "return-outside-function" - text: "do not return outside a function" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/self-assignment" - tag: "self-assignment" - text: "do not assign to itself" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/slots-no-single-string" - tag: "slots-no-single-string" - text: "__slots__ should not be a single string" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/special-methods-arguments" - tag: "special-methods-arguments" - text: "ensure special methods have the correct arguments" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/static-method-no-self" - tag: "static-method-no-self" - text: "do not use self as parameter for static methods" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/too-many-nested-if" - tag: "too-many-nested-if" - text: "do not use too many nested if conditions" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/too-many-while" - tag: "too-many-while" - text: "do not use too many nested loops and conditions " - - link: "/continuous_integration/static_analysis/rules/python-best-practices/type-check-isinstance" - tag: "type-check-isinstance" - text: "use isinstance instead of type" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/unreachable-code" - tag: "unreachable-code" - text: "avoid unreachable code" - - link: "/continuous_integration/static_analysis/rules/python-best-practices/use-callable-not-hasattr" - tag: "use-callable-not-hasattr" - text: "do not use hasattr to check if a value is callable" -python_code_style_data: - - link: "/continuous_integration/static_analysis/rules/python-code-style/assignment-names" - tag: "assignment-names" - text: "variable names must use snake_case" - - link: "/continuous_integration/static_analysis/rules/python-code-style/class-name" - tag: "class-name" - text: "class name should be CamelCase" - - link: "/continuous_integration/static_analysis/rules/python-code-style/function-naming" - tag: "function-naming" - text: "function name and parameters should use snake_case" - - link: "/continuous_integration/static_analysis/rules/python-code-style/max-class-lines" - tag: "max-class-lines" - text: "classes must be less than 100 lines" - - link: "/continuous_integration/static_analysis/rules/python-code-style/max-function-lines" - tag: "max-function-lines" - text: "Functions must be less than 200 lines" -python_design_data: - - link: "/continuous_integration/static_analysis/rules/python-design/function-too-long" - tag: "function-too-long" - text: "functions must have less than 100 lines" -python_django_data: - - link: "/continuous_integration/static_analysis/rules/python-django/http-response-from-request" - tag: "http-response-from-request" - text: "Lack of sanitization of user data" - - link: "/continuous_integration/static_analysis/rules/python-django/http-response-with-json-dumps" - tag: "http-response-with-json-dumps" - text: "use JsonResponse instead of HttpResponse to send JSON data" - - link: "/continuous_integration/static_analysis/rules/python-django/jsonresponse-no-content-type" - tag: "jsonresponse-no-content-type" - text: "do not specify content-type for JsonResponse" - - link: "/continuous_integration/static_analysis/rules/python-django/model-charfield-max-length" - tag: "model-charfield-max-length" - text: "always specify max_length for a Charfield" - - link: "/continuous_integration/static_analysis/rules/python-django/model-help-text" - tag: "model-help-text" - text: "use help_text to document model columns" - - link: "/continuous_integration/static_analysis/rules/python-django/no-null-boolean" - tag: "no-null-boolean" - text: "do not use NullBooleanField" - - link: "/continuous_integration/static_analysis/rules/python-django/no-unicode-on-models" - tag: "no-unicode-on-models" - text: "do not use __unicode__" - - link: "/continuous_integration/static_analysis/rules/python-django/open-filename-from-request" - tag: "open-filename-from-request" - text: "Filename coming from the request" - - link: "/continuous_integration/static_analysis/rules/python-django/os-system-from-request" - tag: "os-system-from-request" - text: "Command coming from incoming request" - - link: "/continuous_integration/static_analysis/rules/python-django/subprocess-from-request" - tag: "subprocess-from-request" - text: "Command coming from incoming request" - - link: "/continuous_integration/static_analysis/rules/python-django/use-convenience-imports" - tag: "use-convenience-imports" - text: "use convenience imports whenever possible" -python_flask_data: - - link: "/continuous_integration/static_analysis/rules/python-flask/disable-sqlalchemy-text" - tag: "disable-sqlalchemy-text" - text: "Do not use text() as it leads to SQL injection" - - link: "/continuous_integration/static_analysis/rules/python-flask/html-format-from-user-input" - tag: "html-format-from-user-input" - text: "Use of unsanitized data to make API calls" - - link: "/continuous_integration/static_analysis/rules/python-flask/listen-all-interfaces" - tag: "listen-all-interfaces" - text: "Your application should not listen on all interfaces" - - link: "/continuous_integration/static_analysis/rules/python-flask/no-render-template-string" - tag: "no-render-template-string" - text: "Do not use template created with strings" - - link: "/continuous_integration/static_analysis/rules/python-flask/open-file-unsanitized-data" - tag: "open-file-unsanitized-data" - text: "Use of unsanitized data to open file" - - link: "/continuous_integration/static_analysis/rules/python-flask/os-system-unsanitized-data" - tag: "os-system-unsanitized-data" - text: "Use of unsanitized data to create processes" - - link: "/continuous_integration/static_analysis/rules/python-flask/secure-cookie" - tag: "secure-cookie" - text: "Make sure cookies are safe and secure" - - link: "/continuous_integration/static_analysis/rules/python-flask/sqlalchemy-injection" - tag: "sqlalchemy-injection" - text: "Use of unsanitized data to issue SQL queries" - - link: "/continuous_integration/static_analysis/rules/python-flask/ssrf-requests" - tag: "ssrf-requests" - text: "Use of unsanitized data to make API calls" - - link: "/continuous_integration/static_analysis/rules/python-flask/urlopen-unsanitized-data" - tag: "urlopen-unsanitized-data" - text: "Use of unsanitized data to open API" - - link: "/continuous_integration/static_analysis/rules/python-flask/use-jsonify" - tag: "use-jsonify" - text: "use jsonify instead of json.dumps for JSON output" -python_inclusive_data: - - link: "/continuous_integration/static_analysis/rules/python-inclusive/comments" - tag: "comments" - text: "check comments for wording issues" - - link: "/continuous_integration/static_analysis/rules/python-inclusive/function-definition" - tag: "function-definition" - text: "check function names for wording issues" - - link: "/continuous_integration/static_analysis/rules/python-inclusive/variable-name" - tag: "variable-name" - text: "check variable names for wording issues" -python_pandas_data: - - link: "/continuous_integration/static_analysis/rules/python-pandas/arith-operator-not-functions" - tag: "arith-operator-not-functions" - text: "Use arithmetic operator instead of a function" - - link: "/continuous_integration/static_analysis/rules/python-pandas/avoid-inplace" - tag: "avoid-inplace" - text: "Avoid using inplace=True" - - link: "/continuous_integration/static_analysis/rules/python-pandas/comp-operator-not-function" - tag: "comp-operator-not-function" - text: "Use operators to compare values, not functions" - - link: "/continuous_integration/static_analysis/rules/python-pandas/import-as-pd" - tag: "import-as-pd" - text: "Import pandas according to coding guidelines" - - link: "/continuous_integration/static_analysis/rules/python-pandas/isna-instead-of-isnull" - tag: "isna-instead-of-isnull" - text: "Use isna instead of isnull" - - link: "/continuous_integration/static_analysis/rules/python-pandas/loc-not-ix" - tag: "loc-not-ix" - text: "prefer iloc or loc rather than ix" - - link: "/continuous_integration/static_analysis/rules/python-pandas/notna-instead-of-notnull" - tag: "notna-instead-of-notnull" - text: "prefer notna to notnull" - - link: "/continuous_integration/static_analysis/rules/python-pandas/pivot-table" - tag: "pivot-table" - text: "Use pivot_table instead of pivot or unstack" - - link: "/continuous_integration/static_analysis/rules/python-pandas/use-read-csv-not-read-table" - tag: "use-read-csv-not-read-table" - text: "prefer read_csv to read_table" -python_security_data: - - link: "/continuous_integration/static_analysis/rules/python-security/asyncio-subprocess-create-shell" - tag: "asyncio-subprocess-create-shell" - text: "Unsafe execution of shell commands" - - link: "/continuous_integration/static_analysis/rules/python-security/asyncio-subprocess-exec" - tag: "asyncio-subprocess-exec" - text: "Unsafe execution of shell commands" - - link: "/continuous_integration/static_analysis/rules/python-security/avoid-random" - tag: "avoid-random" - text: "use secrets package over random package" - - link: "/continuous_integration/static_analysis/rules/python-security/aws-boto-credentials" - tag: "aws-boto-credentials" - text: "use env vars over hardcoded values" - - link: "/continuous_integration/static_analysis/rules/python-security/deserialize-untrusted-data" - tag: "deserialize-untrusted-data" - text: "avoid unsafe function to (de)serialize data" - - link: "/continuous_integration/static_analysis/rules/python-security/file-write-others" - tag: "file-write-others" - text: "do not let all users write permissions" - - link: "/continuous_integration/static_analysis/rules/python-security/hardcoded-tmp-file" - tag: "hardcoded-tmp-file" - text: "Do not hardcode temp file or directory" - - link: "/continuous_integration/static_analysis/rules/python-security/html-string-from-parameters" - tag: "html-string-from-parameters" - text: "Avoid HTML built in strings" - - link: "/continuous_integration/static_analysis/rules/python-security/insecure-hash-functions" - tag: "insecure-hash-functions" - text: "Do not use insecure functions" - - link: "/continuous_integration/static_analysis/rules/python-security/insecure-jwt" - tag: "insecure-jwt" - text: "Ensure JWT signatures are verified" - - link: "/continuous_integration/static_analysis/rules/python-security/insecure-ssl-protocols" - tag: "insecure-ssl-protocols" - text: "Do not use insecure encryption protocols" - - link: "/continuous_integration/static_analysis/rules/python-security/jinja-autoescape" - tag: "jinja-autoescape" - text: "Auto escape should be set to true" - - link: "/continuous_integration/static_analysis/rules/python-security/mktemp" - tag: "mktemp" - text: "Make sure temporary files are secure" - - link: "/continuous_integration/static_analysis/rules/python-security/no-empty-array-as-parameter" - tag: "no-empty-array-as-parameter" - text: "Do not use empty array as default parameter" - - link: "/continuous_integration/static_analysis/rules/python-security/no-eval" - tag: "no-eval" - text: "use of eval can be insecure" - - link: "/continuous_integration/static_analysis/rules/python-security/os-spawn" - tag: "os-spawn" - text: "Call of a spawn process without sanitization" - - link: "/continuous_integration/static_analysis/rules/python-security/os-system" - tag: "os-system" - text: "Command execution without sanitization" - - link: "/continuous_integration/static_analysis/rules/python-security/request-verify" - tag: "request-verify" - text: "verify should be True" - - link: "/continuous_integration/static_analysis/rules/python-security/requests-http" - tag: "requests-http" - text: "Do not make http calls without encryption" - - link: "/continuous_integration/static_analysis/rules/python-security/requests-timeout" - tag: "requests-timeout" - text: "no timeout was given on call to external resource" - - link: "/continuous_integration/static_analysis/rules/python-security/ruamel-unsafe-yaml" - tag: "ruamel-unsafe-yaml" - text: "Do not use insecure YAML deserialization" - - link: "/continuous_integration/static_analysis/rules/python-security/sql-server-security-credentials" - tag: "sql-server-security-credentials" - text: "do not pass hardcoded credentials" - - link: "/continuous_integration/static_analysis/rules/python-security/ssl-unverified-context" - tag: "ssl-unverified-context" - text: "should not bypass certificate verification" - - link: "/continuous_integration/static_analysis/rules/python-security/subprocess-shell-true" - tag: "subprocess-shell-true" - text: "shell argument leads to unnecessary privileges" - - link: "/continuous_integration/static_analysis/rules/python-security/variable-sql-statement-injection" - tag: "variable-sql-statement-injection" - text: "Avoid SQL injections" - - link: "/continuous_integration/static_analysis/rules/python-security/yaml-load" - tag: "yaml-load" - text: "avoid deserializing untrusted YAML" -tsx_react_data: - - link: "/continuous_integration/static_analysis/rules/tsx-react/jsx-no-comment-textnodes" - tag: "jsx-no-comment-textnodes" - text: "Avoid comments from being inserted as text nodes" - - link: "/continuous_integration/static_analysis/rules/tsx-react/no-children-prop" - tag: "no-children-prop" - text: "Avoid passing children as props" - - link: "/continuous_integration/static_analysis/rules/tsx-react/no-danger-with-children" - tag: "no-danger-with-children" - text: "Avoid using children with dangerouslySetInnerHTML" - - link: "/continuous_integration/static_analysis/rules/tsx-react/no-deprecated" - tag: "no-deprecated" - text: "Avoid deprecated methods" - - link: "/continuous_integration/static_analysis/rules/tsx-react/no-render-return-value" - tag: "no-render-return-value" - text: "Avoid usage of the return value of ReactDOM.render" - - link: "/continuous_integration/static_analysis/rules/tsx-react/no-string-refs" - tag: "no-string-refs" - text: "Avoid using string references" - - link: "/continuous_integration/static_analysis/rules/tsx-react/require-render-return" - tag: "require-render-return" - text: "Enforce class for returning value in render function" - - link: "/continuous_integration/static_analysis/rules/tsx-react/tsx-key" - tag: "tsx-key" - text: "Prevent missing key props in iterators/collection literals" - - link: "/continuous_integration/static_analysis/rules/tsx-react/tsx-no-duplicate-key" - tag: "tsx-no-duplicate-key" - text: "Ensures unique key prop" - - link: "/continuous_integration/static_analysis/rules/tsx-react/tsx-no-target-blank" - tag: "tsx-no-target-blank" - text: "Prevent target='_blank' security risks" -typescript_best_practices_data: - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/ban-types" - tag: "ban-types" - text: "Avoid certain types" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/boolean-prop-naming" - tag: "boolean-prop-naming" - text: "Consistent naming for boolean props" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/for-direction" - tag: "for-direction" - text: "Check for loop is moving in the right direction" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/new-parens" - tag: "new-parens" - text: "Invoking a constructor must use parentheses" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-alert" - tag: "no-alert" - text: "Avoid the use of alert, confirm, and prompt" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-async-promise-executor" - tag: "no-async-promise-executor" - text: "Promise executor cannot be an async function" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-caller" - tag: "no-caller" - text: "Avoid the use of arguments.caller or arguments.callee" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-compare-neg-zero" - tag: "no-compare-neg-zero" - text: "Direct comparison with -0 detected" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-cond-assign" - tag: "no-cond-assign" - text: "Avoid assignment operators in conditional expressions" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-console" - tag: "no-console" - text: "Avoid leaving console debug statements" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-debugger" - tag: "no-debugger" - text: "Disallow the use of debugger" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-delete-var" - tag: "no-delete-var" - text: "Avoid using delete on variables directly" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-dupe-keys" - tag: "no-dupe-keys" - text: "Avoid duplicate keys in object literals" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values" - tag: "no-duplicate-enum-values" - text: "Avoid duplicate enum member values" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents" - tag: "no-duplicate-type-constituents" - text: "Avoid duplicate constituents of unions or intersections" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-empty" - tag: "no-empty" - text: "Avoid empty block statements" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-empty-character-class" - tag: "no-empty-character-class" - text: "Avoid empty character classes in regular expressions" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-empty-pattern" - tag: "no-empty-pattern" - text: "Avoid empty destructuring patterns" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-ex-assign" - tag: "no-ex-assign" - text: "Avoid reassigning exceptions in catch clauses" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-explicit-any" - tag: "no-explicit-any" - text: "Avoid the any type" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion" - tag: "no-extra-non-null-assertion" - text: "Avoid extra non-null assertions" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-implied-eval" - tag: "no-implied-eval" - text: "Prevent the use methods similar to eval()" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-inner-declarations" - tag: "no-inner-declarations" - text: "Avoid variable or function declaration in nested blocks" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-iterator" - tag: "no-iterator" - text: "Avoid the use of the __iterator__ property" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-loss-of-precision" - tag: "no-loss-of-precision" - text: "Avoid numbers that lose precision" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-namespace" - tag: "no-namespace" - text: "Avoid TypeScript namespaces" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain" - tag: "no-non-null-optional-chain" - text: "Avoid non-null assertions after an optional chain" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-proto" - tag: "no-proto" - text: "Avoid the use of the __proto__ property" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-script-url" - tag: "no-script-url" - text: "Avoid using Javascript in URLs" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint" - tag: "no-unnecessary-type-constraint" - text: "Avoid unnecessary constraints on generic types" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-unsafe-assignment" - tag: "no-unsafe-assignment" - text: "Avoid assigning a value with type any" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging" - tag: "no-unsafe-declaration-merging" - text: "Avoid unsafe declaration merging" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-unsafe-negation" - tag: "no-unsafe-negation" - text: "Avoid negating the left operand of relational operators" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/no-var-requires" - tag: "no-var-requires" - text: "Avoid require statements" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/require-yield" - tag: "require-yield" - text: "Require yield in generator functions" - - link: "/continuous_integration/static_analysis/rules/typescript-best-practices/triple-slash-reference" - tag: "triple-slash-reference" - text: "Avoid triple slash in favor of ES6 import declarations" -typescript_browser_security_data: - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/event-check-origin" - tag: "event-check-origin" - text: "Check origin of events" - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/inner-outer-html" - tag: "inner-outer-html" - text: "Do not modify innerHTML or outerHTML" - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/insecure-websocket" - tag: "insecure-websocket" - text: "Websockets must use SSL connections" - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data" - tag: "local-storage-sensitive-data" - text: "Do not store sensitive data to local storage" - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/manual-sanitization" - tag: "manual-sanitization" - text: "Avoid manual sanitization of inputs" - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin" - tag: "postmessage-permissive-origin" - text: "Specify origin in postMessage" - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html" - tag: "react-dangerously-inner-html" - text: "Do not inject unsanitized HTML" - - link: "/continuous_integration/static_analysis/rules/typescript-browser-security/regexp-non-literal" - tag: "regexp-non-literal" - text: "Do not use variable for regular expressions" -typescript_code_style_data: - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/array-type" - tag: "array-type" - text: "Require consistently using either T[] or Array for arrays" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/assignment-name" - tag: "assignment-name" - text: "Assigment name should use camelCase" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/ban-ts-comment" - tag: "ban-ts-comment" - text: "Avoid @ts- comments" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/ban-tslint-comment" - tag: "ban-tslint-comment" - text: "Avoid using TSLint comments" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/class-name" - tag: "class-name" - text: "Class name should be PascalCase" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/eqeqeq" - tag: "eqeqeq" - text: "Enforce the use of === and !==" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/func-name-matching" - tag: "func-name-matching" - text: "Function names must match the name of the assignation" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/func-names" - tag: "func-names" - text: "Enforce named function expressions" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/function-naming" - tag: "function-naming" - text: "Function name should use camelCase or PascalCase" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/max-class-lines" - tag: "max-class-lines" - text: "Classes must be less than 100 lines" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/max-function-lines" - tag: "max-function-lines" - text: "Functions must be less than 200 lines" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/max-params" - tag: "max-params" - text: "Enforce a maximum number of parameters in a function" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/method-name" - tag: "method-name" - text: "Method name should use camelCase" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-array-constructor" - tag: "no-array-constructor" - text: "Avoid Array constructors" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion" - tag: "no-confusing-non-null-assertion" - text: "Avoid non-null assertion in confusing locations" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-div-regex" - tag: "no-div-regex" - text: "Avoid equal signs explicitly at the beginning of regex" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-duplicate-imports" - tag: "no-duplicate-imports" - text: "Avoid duplicate module imports" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-empty-interface" - tag: "no-empty-interface" - text: "Avoid the declaration of empty interfaces" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-floating-decimal" - tag: "no-floating-decimal" - text: "Avoid leading or trailing decimal points in numbers" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-inferrable-types" - tag: "no-inferrable-types" - text: "Avoid explicit type declarations for variables and params" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-lonely-if" - tag: "no-lonely-if" - text: "Avoid if statements as the only statement in else blocks" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-multi-assign" - tag: "no-multi-assign" - text: "Avoid the use of chained assignment expressions" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-new" - tag: "no-new" - text: "Avoid new operators outside of assignments or comparisons" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-new-func" - tag: "no-new-func" - text: "Avoid new operators with the Function object" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-new-object" - tag: "no-new-object" - text: "Avoid Object constructors" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-return-assign" - tag: "no-return-assign" - text: "Avoid assignment operators in return statements" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-self-compare" - tag: "no-self-compare" - text: "Avoid comparisons where both sides are exactly the same" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-useless-empty-export" - tag: "no-useless-empty-export" - text: "Avoid empty exports that don't change anything" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/no-var" - tag: "no-var" - text: "Require let or const instead of var" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/parameter-name" - tag: "parameter-name" - text: "Parameter name should use camelCase" - - link: "/continuous_integration/static_analysis/rules/typescript-code-style/radix" - tag: "radix" - text: "Consistent use of the radix argument using parseInt" -typescript_common_security_data: - - link: "/continuous_integration/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http" - tag: "axios-avoid-insecure-http" - text: "Avoid insecure HTTP requests with Axios" - - link: "/continuous_integration/static_analysis/rules/typescript-common-security/unique-function-arguments" - tag: "unique-function-arguments" - text: "Function argument names should be unique" - - link: "/continuous_integration/static_analysis/rules/typescript-common-security/xml-no-external-entities" - tag: "xml-no-external-entities" - text: "Do not use external XML entities" -typescript_express_data: - - link: "/continuous_integration/static_analysis/rules/typescript-express/access-restriction" - tag: "access-restriction" - text: "Limit exposure to sensitive directories and files" - - link: "/continuous_integration/static_analysis/rules/typescript-express/default-session-config" - tag: "default-session-config" - text: "Enforce overriding default config" - - link: "/continuous_integration/static_analysis/rules/typescript-express/external-filename-upload" - tag: "external-filename-upload" - text: "Avoid using unsanitized user input with sendFile" - - link: "/continuous_integration/static_analysis/rules/typescript-express/external-resource" - tag: "external-resource" - text: "Avoid rendering resource based on unsanitized user input" - - link: "/continuous_integration/static_analysis/rules/typescript-express/hardcoded-secret" - tag: "hardcoded-secret" - text: "Avoid using a hard-coded secret" - - link: "/continuous_integration/static_analysis/rules/typescript-express/https-protocol-missing" - tag: "https-protocol-missing" - text: "Use `https` protocol over `http`" - - link: "/continuous_integration/static_analysis/rules/typescript-express/insecure-allow-origin" - tag: "insecure-allow-origin" - text: "Avoid using an insecure Access-Control-Allow-Origin header" - - link: "/continuous_integration/static_analysis/rules/typescript-express/insecure-cookie" - tag: "insecure-cookie" - text: "Avoid setting insecure cookie settings" - - link: "/continuous_integration/static_analysis/rules/typescript-express/jwt-not-revoked" - tag: "jwt-not-revoked" - text: "Ensure an isRevoked method is used for tokens" - - link: "/continuous_integration/static_analysis/rules/typescript-express/missing-helmet" - tag: "missing-helmet" - text: "Express application should use Helmet" - - link: "/continuous_integration/static_analysis/rules/typescript-express/path-traversal" - tag: "path-traversal" - text: "Avoid allowing access to unintended directories or files" - - link: "/continuous_integration/static_analysis/rules/typescript-express/reduce-server-fingerprinting" - tag: "reduce-server-fingerprinting" - text: "Server fingerprinting misconfiguration" - - link: "/continuous_integration/static_analysis/rules/typescript-express/xss-vulnerability" - tag: "xss-vulnerability" - text: "Avoid sending unsanitized user input in response" -typescript_inclusive_data: - - link: "/continuous_integration/static_analysis/rules/typescript-inclusive/comments" - tag: "comments" - text: "Check comments for wording issues" - - link: "/continuous_integration/static_analysis/rules/typescript-inclusive/declarations" - tag: "declarations" - text: "Check declaration names for wording issues" - - link: "/continuous_integration/static_analysis/rules/typescript-inclusive/formal-parameters" - tag: "formal-parameters" - text: "Check parameter names for wording issues" - - link: "/continuous_integration/static_analysis/rules/typescript-inclusive/identifiers" - tag: "identifiers" - text: "Check identifier names for wording issues" -typescript_node_security_data: - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/argon2" - tag: "argon2" - text: "Use strong security mechanisms with argon2" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/avoid-crypto-rc4" - tag: "avoid-crypto-rc4" - text: "Avoid RC4" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/avoid-crypto-sha1" - tag: "avoid-crypto-sha1" - text: "Avoid SHA1 security protocol" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/avoid-des" - tag: "avoid-des" - text: "Avoid DES and 3DES" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/chmod-permissions" - tag: "chmod-permissions" - text: "Do not give 777 permissions to a file" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/command-injection" - tag: "command-injection" - text: "Avoid command injection" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash" - tag: "crypto-avoid-weak-hash" - text: "Avoid weak hash algorithm from CryptoJS" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detect-buffer-noassert" - tag: "detect-buffer-noassert" - text: "Avoid calls to 'buffer' with 'noAssert' flag set" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detect-child-process" - tag: "detect-child-process" - text: "Avoid instances of 'child_process' and non-literal 'exec()'" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detect-eval-with-expression" - tag: "detect-eval-with-expression" - text: "Avoid `eval` with expressions" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detect-new-buffer" - tag: "detect-new-buffer" - text: "Avoid Buffer(argument) with non-literal values" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename" - tag: "detect-non-literal-fs-filename" - text: "Avoid variables in 'fs' calls filename argument" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detect-non-literal-regexp" - tag: "detect-non-literal-regexp" - text: "Detects non-literal values in regular expressions" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detect-non-literal-require" - tag: "detect-non-literal-require" - text: "Avoid require with non-literal values" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/detected-jwt-token" - tag: "detected-jwt-token" - text: "Detects hardcoded JWT tokens within the codebase" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/hardcoded-hmac-key" - tag: "hardcoded-hmac-key" - text: "Detects hardcoded HMAC keys" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/insecure-hash" - tag: "insecure-hash" - text: "Do not use weak hash functions" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage" - tag: "insecure-jwt-secret-usage" - text: "Insecure Usage of a Static Secret in JWT Signing" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret" - tag: "jwt-hardcoded-secret" - text: "Do not use hardcoded secret with a JWT" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/jwt-sensitive-data" - tag: "jwt-sensitive-data" - text: "Do not put sensitive data in objects" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/jwt-weak-encryption" - tag: "jwt-weak-encryption" - text: "Use default encryption from the JWT library" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/log-sensitive-data" - tag: "log-sensitive-data" - text: "Avoid logging sensitive data" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret" - tag: "oauth2-hardcoded-secret" - text: "Do not use hardcoded secret for OAuth2 providers" - - link: "/continuous_integration/static_analysis/rules/typescript-node-security/sql-injection" - tag: "sql-injection" - text: "Avoid SQL injection" -further_reading: - - link: "/continuous_integration/static_analysis/" - tag: "Documentation" - text: "Learn about Datadog Static Analysis" ---- - -## Overview - -{{% site-region region="us,us3,us5,eu,ap1" %}} -
- Static Analysis is in private beta. Python, JavaScript, TypeScript, and Docker are the only supported languages. To request access, contact Support. -
-{{% /site-region %}} - -{{% site-region region="gov" %}} -
- Static Analysis is not available for the {{< region-param key="dd_site_name" >}} site. -
-{{% /site-region %}} - -Datadog Static Analysis provides out-of-the-box rules to help detect violations in your CI/CD pipelines in code reviews and identify bugs, security, and maintainability issues. For more information, see the [Static Analysis documentation][1]. - -## Docker rules - -### Follow best practices with using Docker - -**Ruleset ID:** `docker-best-practices` - -Best practices for using Docker. - -{{< sa-rule-list "docker_best_practices_data" >}} - -
- -## JavaScript rules - -### Follow best practices for writing JavaScript code - -**Ruleset ID:** `javascript-best-practices` - -Rules to enforce JavaScript best practices. - -{{< sa-rule-list "javascript_best_practices_data" >}} - -
- -### Security rules for JavaScript web applications - -**Ruleset ID:** `javascript-browser-security` - -Rules focused on finding security issues in your JavaScript web applications. - -{{< sa-rule-list "javascript_browser_security_data" >}} - -
- -### Enforce JavaScript code style - -**Ruleset ID:** `javascript-code-style` - -Rules to enforce JavaScript code style. - -{{< sa-rule-list "javascript_code_style_data" >}} - -
- -### Common security rules for JavaScript - -**Ruleset ID:** `javascript-common-security` - -Rules focused on finding security issues in your JavaScript code. - -{{< sa-rule-list "javascript_common_security_data" >}} - -
- -### Check for Express.js best practices and security - -**Ruleset ID:** `javascript-express` - -Rules specifically for Express.js best practices and security. - -{{< sa-rule-list "javascript_express_data" >}} - -
- -### Check JavaScript code for wording issues - -**Ruleset ID:** `javascript-inclusive` - -Rules for JavaScript to avoid inappropriate wording in the code and comments. - -{{< sa-rule-list "javascript_inclusive_data" >}} - -
- -### Identify potential security hotspots in Node - -**Ruleset ID:** `javascript-node-security` - -Rules to identify potential security hotspots in Node. This may include false positives that require further triage. - -{{< sa-rule-list "javascript_node_security_data" >}} - -
- -### React specific linting rules - -**Ruleset ID:** `jsx-react` - -This plugin exports a `recommended` configuration that enforces React good practices. - -{{< sa-rule-list "jsx_react_data" >}} - -
- -## Python rules - -### Follow best practices for writing Python code - -**Ruleset ID:** `python-best-practices` - -Best practices for Python to write efficient and bug-free code. - -{{< sa-rule-list "python_best_practices_data" >}} - -
- -### Enforce Python code style - -**Ruleset ID:** `python-code-style` - -Rules to enforce Python code style. - -{{< sa-rule-list "python_code_style_data" >}} - -
- -### Check Python program structure - -**Ruleset ID:** `python-design` - -Rules to check your Python program structure, including things like nested loops. - -{{< sa-rule-list "python_design_data" >}} - -
- -### Check for Django best practices and security - -**Ruleset ID:** `python-django` - -Rules specifically for Django best practices and security. - -{{< sa-rule-list "python_django_data" >}} - -
- -### Check for Flask best practices and security - -**Ruleset ID:** `python-flask` - -Rules specifically for Flask best practices and security. - -{{< sa-rule-list "python_flask_data" >}} - -
- -### Check Python code for wording issues - -**Ruleset ID:** `python-inclusive` - -Rules for Python to avoid inappropriate wording in the code and comments. - -{{< sa-rule-list "python_inclusive_data" >}} - -
- -### Good practices for data science with pandas - -**Ruleset ID:** `python-pandas` - -A set of rules to check that pandas code is used appropriately. - - - Ensures `import` declarations follow coding guidelines. - - Avoid deprecated code and methods. - - Avoid inefficient code whenever possible. - -{{< sa-rule-list "python_pandas_data" >}} - -
- -### Ensure your Python code is safe and secure - -**Ruleset ID:** `python-security` - -Rules focused on finding security and vulnerability issues in your Python code, including those found in the OWASP10 and SANS25. - - - Use of bad encryption and hashing protocols - - Lack of access control - - Security misconfiguration - - SQL injections - - Hardcoded credentials - - Shell injection - - Unsafe deserialization - -{{< sa-rule-list "python_security_data" >}} - -
- -## TypeScript rules - -### TypeScript React code quality - -**Ruleset ID:** `tsx-react` - -This plugin exports a `recommended` configuration that enforces React good practices. - -{{< sa-rule-list "tsx_react_data" >}} - -
- -### Follow best practices for writing TypeScript code - -**Ruleset ID:** `typescript-best-practices` - -Rules to enforce TypeScript best practices. - -{{< sa-rule-list "typescript_best_practices_data" >}} - -
- -### Security rules for TypeScript web applications - -**Ruleset ID:** `typescript-browser-security` - -Rules focused on finding security issues in your TypeScript web applications. - -{{< sa-rule-list "typescript_browser_security_data" >}} - -
- -### TypeScript opinionated code patterns - -**Ruleset ID:** `typescript-code-style` - -Rules considered to be best practice for modern TypeScript codebases, but that do not impact program logic. These rules are generally opinionated about enforcing simpler code patterns. - -{{< sa-rule-list "typescript_code_style_data" >}} - -
- -### Common security rules for TypeScript - -**Ruleset ID:** `typescript-common-security` - -Rules focused on finding security issues in your TypeScript code. - -{{< sa-rule-list "typescript_common_security_data" >}} - -
- -### Check for Express.js TypeScript best practices and security - -**Ruleset ID:** `typescript-express` - -Rules specifically for Express.js TypeScript best practices and security. - -{{< sa-rule-list "typescript_express_data" >}} - -
- -### Check Python code for wording issues - -**Ruleset ID:** `typescript-inclusive` - -Rules for Python to avoid inappropriate wording in the code and comments. - -{{< sa-rule-list "typescript_inclusive_data" >}} - -
- -### Identify potential security hotspots in Node - -**Ruleset ID:** `typescript-node-security` - -Rules to identify potential security hotspots in Node. This may include false positives that require further triage. - -{{< sa-rule-list "typescript_node_security_data" >}} - -
- -## Further Reading - -{{< partial name="whats-next/whats-next.html" >}} - -[1]: /continuous_integration/static_analysis diff --git a/content/en/continuous_integration/dora_metrics/_index.md b/content/en/dora_metrics/_index.md similarity index 99% rename from content/en/continuous_integration/dora_metrics/_index.md rename to content/en/dora_metrics/_index.md index f42d07df804a8..739e7ca275289 100644 --- a/content/en/continuous_integration/dora_metrics/_index.md +++ b/content/en/dora_metrics/_index.md @@ -2,6 +2,8 @@ title: DORA Metrics kind: documentation description: Learn how to use DORA metrics to improve and measure software development. +aliases: +- /continuous_integration/dora_metrics is_beta: true further_reading: - link: "/continuous_integration/tests" diff --git a/content/en/continuous_integration/quality_gates/_index.md b/content/en/quality_gates/_index.md similarity index 99% rename from content/en/continuous_integration/quality_gates/_index.md rename to content/en/quality_gates/_index.md index 38565d8a82fd4..abbda65727bfe 100644 --- a/content/en/continuous_integration/quality_gates/_index.md +++ b/content/en/quality_gates/_index.md @@ -2,6 +2,8 @@ title: Quality Gates kind: documentation description: Learn how to use Quality Gates in your pipeline. +aliases: +- /continuous_integration/quality_gates is_beta: true further_reading: - link: "/continuous_integration/tests" diff --git a/content/en/continuous_integration/static_analysis/_index.md b/content/en/static_analysis/_index.md similarity index 99% rename from content/en/continuous_integration/static_analysis/_index.md rename to content/en/static_analysis/_index.md index 0450f4664144e..f5f71e7dbf45e 100644 --- a/content/en/continuous_integration/static_analysis/_index.md +++ b/content/en/static_analysis/_index.md @@ -2,6 +2,8 @@ title: Static Analysis kind: documentation description: Learn about Datadog Static Analysis to scan code for quality issues and security vulnerabilities before your code reaches production. +aliases: +- /continuous_integration/static_analysis is_beta: true further_reading: - link: "https://www.datadoghq.com/blog/monitor-ci-pipelines/" diff --git a/local/bin/py/build/configurations/pull_config.yaml b/local/bin/py/build/configurations/pull_config.yaml index 006e138e8b4ad..51cba83ee0ad4 100644 --- a/local/bin/py/build/configurations/pull_config.yaml +++ b/local/bin/py/build/configurations/pull_config.yaml @@ -343,13 +343,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'circleci_orbs.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md"] title: Static Analysis and CircleCI Orbs kind: documentation description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/circleci_orbs - repo_name: datadog-static-analyzer-github-action contents: @@ -358,13 +360,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'github_actions.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md"] title: Static Analysis and GitHub Actions kind: documentation description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/github_actions - repo_name: datadog-static-analyzer-rule-docs contents: @@ -373,7 +377,7 @@ globs: - rulesets/**/*.md options: - dest_dir: '/continuous_integration/static_analysis/rules/' + dest_dir: '/static_analysis/rules/' path_to_remove: 'rulesets/' front_matters: disable_edit: true diff --git a/local/bin/py/build/configurations/pull_config_preview.yaml b/local/bin/py/build/configurations/pull_config_preview.yaml index 4e01a7f401c27..ade397a4fbe1f 100644 --- a/local/bin/py/build/configurations/pull_config_preview.yaml +++ b/local/bin/py/build/configurations/pull_config_preview.yaml @@ -344,13 +344,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'circleci_orbs.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-circleci-orb/blob/main/README.md"] title: Static Analysis and CircleCI Orbs kind: documentation description: Use Datadog and CircleCI to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/circleci_orbs - repo_name: datadog-static-analyzer-github-action contents: @@ -359,13 +361,15 @@ globs: - 'README.md' options: - dest_path: '/continuous_integration/static_analysis/' + dest_path: '/static_analysis/' file_name: 'github_actions.md' front_matters: dependencies: ["https://github.com/DataDog/datadog-static-analyzer-github-action/blob/main/README.md"] title: Static Analysis and GitHub Actions kind: documentation description: Use Datadog and GitHub to run Static Analysis jobs in a CI pipeline. + aliases: + - /continuous_integration/static_analysis/github_actions - repo_name: datadog-static-analyzer-rule-docs contents: @@ -374,7 +378,7 @@ globs: - rulesets/**/*.md options: - dest_dir: '/continuous_integration/static_analysis/rules/' + dest_dir: '/static_analysis/rules/' path_to_remove: 'rulesets/' front_matters: disable_edit: true From 148a552b88fbb2d872934b9872b1c3772c07fbda Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Tue, 5 Dec 2023 12:37:10 -0800 Subject: [PATCH 08/12] Generate Preview --- local/bin/py/build/configurations/pull_config_preview.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local/bin/py/build/configurations/pull_config_preview.yaml b/local/bin/py/build/configurations/pull_config_preview.yaml index ade397a4fbe1f..90d444307c516 100644 --- a/local/bin/py/build/configurations/pull_config_preview.yaml +++ b/local/bin/py/build/configurations/pull_config_preview.yaml @@ -1,6 +1,6 @@ --- - config: - cache_enabled: true + cache_enabled: false - data: - org_name: jenkinsci From 8b733ee192fd5af607d3eca828cdb4dfb4e3481c Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:27:36 -0800 Subject: [PATCH 09/12] Update Static Analysis Rules --- .gitignore | 2 +- content/en/static_analysis/rules/_index.md | 1523 ++++++++++++++++++++ 2 files changed, 1524 insertions(+), 1 deletion(-) create mode 100644 content/en/static_analysis/rules/_index.md diff --git a/.gitignore b/.gitignore index 7e9a0716d0c46..2b7c643a61bf8 100644 --- a/.gitignore +++ b/.gitignore @@ -103,7 +103,7 @@ content/en/continuous_testing/cicd_integrations/azure_devops_extension.md # Static Analysis content/en/static_analysis/github_actions.md content/en/static_analysis/circleci_orbs.md -content/en/static_analysis/rules/ +content/en/static_analysis/rules/* !content/en/static_analysis/rules/_index.md # serverless diff --git a/content/en/static_analysis/rules/_index.md b/content/en/static_analysis/rules/_index.md new file mode 100644 index 0000000000000..541d8cb33e215 --- /dev/null +++ b/content/en/static_analysis/rules/_index.md @@ -0,0 +1,1523 @@ +--- +title: Static Analysis Rules +kind: documentation +description: View rules for multiple languages for Static Analysis. +aliases: +- /continuous_integration/static_analysis/rules +is_beta: true +docker_best_practices_data: + - link: "/static_analysis/rules/docker-best-practices/absolute-workdir" + tag: "absolute-workdir" + text: "Use absolute workdir" + - link: "/static_analysis/rules/docker-best-practices/alias-must-be-unique" + tag: "alias-must-be-unique" + text: "FROM aliases must be unique" + - link: "/static_analysis/rules/docker-best-practices/apt-get-yes" + tag: "apt-get-yes" + text: "Always use -y with apt-get install" + - link: "/static_analysis/rules/docker-best-practices/apt-pin-version" + tag: "apt-pin-version" + text: "Always pin versions in apt-get install" + - link: "/static_analysis/rules/docker-best-practices/avoid-chmod-777" + tag: "avoid-chmod-777" + text: "Do not give wide permissions on files" + - link: "/static_analysis/rules/docker-best-practices/avoid-commands-not-relevant" + tag: "avoid-commands-not-relevant" + text: "Avoid commands not made for containers" + - link: "/static_analysis/rules/docker-best-practices/avoid-http" + tag: "avoid-http" + text: "Avoid fetching data from HTTP endpoint" + - link: "/static_analysis/rules/docker-best-practices/dnf-use-y" + tag: "dnf-use-y" + text: "Always use -y with dnf install" + - link: "/static_analysis/rules/docker-best-practices/expose-admin-ports" + tag: "expose-admin-ports" + text: "Do not expose sensitive ports" + - link: "/static_analysis/rules/docker-best-practices/expose-valid-port" + tag: "expose-valid-port" + text: "Expose a valid UNIX port number" + - link: "/static_analysis/rules/docker-best-practices/image-avoid-digest" + tag: "image-avoid-digest" + text: "Do not use the digest to pull an image" + - link: "/static_analysis/rules/docker-best-practices/maintainer-deprecated" + tag: "maintainer-deprecated" + text: "The maintainer entry is deprecated" + - link: "/static_analysis/rules/docker-best-practices/multiple-cmd" + tag: "multiple-cmd" + text: "Do not use multiple CMD" + - link: "/static_analysis/rules/docker-best-practices/multiple-entrypoint" + tag: "multiple-entrypoint" + text: "Do not use multiple CMD" + - link: "/static_analysis/rules/docker-best-practices/multiple-healthcheck" + tag: "multiple-healthcheck" + text: "Do not use multiple HEALTHCHECK" + - link: "/static_analysis/rules/docker-best-practices/no-root-user" + tag: "no-root-user" + text: "Last user should not be root" + - link: "/static_analysis/rules/docker-best-practices/pip-no-cache" + tag: "pip-no-cache" + text: "Do not use cache when installing packages" + - link: "/static_analysis/rules/docker-best-practices/pip-pin-versions" + tag: "pip-pin-versions" + text: "Always pin versions with pip" + - link: "/static_analysis/rules/docker-best-practices/tag-image-version" + tag: "tag-image-version" + text: "Always tag the version of an image" + - link: "/static_analysis/rules/docker-best-practices/yum-use-y" + tag: "yum-use-y" + text: "Always use -y with yum install" + - link: "/static_analysis/rules/docker-best-practices/zypper-use-y" + tag: "zypper-use-y" + text: "Always use -y with zypper install" +javascript_best_practices_data: + - link: "/static_analysis/rules/javascript-best-practices/for-direction" + tag: "for-direction" + text: "Check for loop is moving in the right direction" + - link: "/static_analysis/rules/javascript-best-practices/new-parens" + tag: "new-parens" + text: "Invoking a constructor must use parentheses" + - link: "/static_analysis/rules/javascript-best-practices/no-alert" + tag: "no-alert" + text: "Avoid the use of alert, confirm, and prompt" + - link: "/static_analysis/rules/javascript-best-practices/no-async-promise-executor" + tag: "no-async-promise-executor" + text: "Promise executor cannot be an async function" + - link: "/static_analysis/rules/javascript-best-practices/no-caller" + tag: "no-caller" + text: "Avoid the use of arguments.caller or arguments.callee" + - link: "/static_analysis/rules/javascript-best-practices/no-case-declarations" + tag: "no-case-declarations" + text: "Avoid lexical declarations in case clauses" + - link: "/static_analysis/rules/javascript-best-practices/no-compare-neg-zero" + tag: "no-compare-neg-zero" + text: "Direct comparison with -0 detected" + - link: "/static_analysis/rules/javascript-best-practices/no-cond-assign" + tag: "no-cond-assign" + text: "Avoid assignment operators in conditional expressions" + - link: "/static_analysis/rules/javascript-best-practices/no-console" + tag: "no-console" + text: "Avoid leaving console debug statements" + - link: "/static_analysis/rules/javascript-best-practices/no-debugger" + tag: "no-debugger" + text: "Disallow the use of debugger" + - link: "/static_analysis/rules/javascript-best-practices/no-delete-var" + tag: "no-delete-var" + text: "Avoid using delete on variables directly" + - link: "/static_analysis/rules/javascript-best-practices/no-dupe-args" + tag: "no-dupe-args" + text: "Function parameters redeclared" + - link: "/static_analysis/rules/javascript-best-practices/no-dupe-class-members" + tag: "no-dupe-class-members" + text: "Avoid duplicate class members" + - link: "/static_analysis/rules/javascript-best-practices/no-dupe-keys" + tag: "no-dupe-keys" + text: "Avoid duplicate keys in object literals" + - link: "/static_analysis/rules/javascript-best-practices/no-duplicate-case" + tag: "no-duplicate-case" + text: "Avoid duplicate case labels" + - link: "/static_analysis/rules/javascript-best-practices/no-empty" + tag: "no-empty" + text: "Avoid empty block statements" + - link: "/static_analysis/rules/javascript-best-practices/no-empty-character-class" + tag: "no-empty-character-class" + text: "Avoid empty character classes in regular expressions" + - link: "/static_analysis/rules/javascript-best-practices/no-empty-pattern" + tag: "no-empty-pattern" + text: "Avoid empty destructuring patterns" + - link: "/static_analysis/rules/javascript-best-practices/no-ex-assign" + tag: "no-ex-assign" + text: "Avoid reassigning exceptions in catch clauses" + - link: "/static_analysis/rules/javascript-best-practices/no-implied-eval" + tag: "no-implied-eval" + text: "Prevent the use methods similar to eval()" + - link: "/static_analysis/rules/javascript-best-practices/no-import-assign" + tag: "no-import-assign" + text: "Prevent assigning to imported bindings" + - link: "/static_analysis/rules/javascript-best-practices/no-inner-declarations" + tag: "no-inner-declarations" + text: "Avoid variable or function declaration in nested blocks" + - link: "/static_analysis/rules/javascript-best-practices/no-iterator" + tag: "no-iterator" + text: "Avoid the use of the __iterator__ property" + - link: "/static_analysis/rules/javascript-best-practices/no-loss-of-precision" + tag: "no-loss-of-precision" + text: "Avoid numbers that lose precision" + - link: "/static_analysis/rules/javascript-best-practices/no-new-symbol" + tag: "no-new-symbol" + text: "Avoid new statements with the Symbol object" + - link: "/static_analysis/rules/javascript-best-practices/no-octal" + tag: "no-octal" + text: "Avoid using octal literals to prevent unexpected behavior" + - link: "/static_analysis/rules/javascript-best-practices/no-proto" + tag: "no-proto" + text: "Avoid the use of the __proto__ property" + - link: "/static_analysis/rules/javascript-best-practices/no-script-url" + tag: "no-script-url" + text: "Avoid using JavaScript in URLs" + - link: "/static_analysis/rules/javascript-best-practices/no-unsafe-negation" + tag: "no-unsafe-negation" + text: "Avoid negating the left operand of relational operators" + - link: "/static_analysis/rules/javascript-best-practices/no-with" + tag: "no-with" + text: "The with statement can lead to ambiguous code" + - link: "/static_analysis/rules/javascript-best-practices/require-yield" + tag: "require-yield" + text: "Require yield in generator functions" + - link: "/static_analysis/rules/javascript-best-practices/use-isnan" + tag: "use-isnan" + text: "Avoid direct comparison with NaN" + - link: "/static_analysis/rules/javascript-best-practices/valid-typeof" + tag: "valid-typeof" + text: "Compare typeof expressions against valid strings" +javascript_browser_security_data: + - link: "/static_analysis/rules/javascript-browser-security/event-check-origin" + tag: "event-check-origin" + text: "Check origin of events" + - link: "/static_analysis/rules/javascript-browser-security/inner-outer-html" + tag: "inner-outer-html" + text: "Do not modify innerHTML or outerHTML" + - link: "/static_analysis/rules/javascript-browser-security/insecure-websocket" + tag: "insecure-websocket" + text: "Websockets must use SSL connections" + - link: "/static_analysis/rules/javascript-browser-security/local-storage-sensitive-data" + tag: "local-storage-sensitive-data" + text: "Do not store sensitive data to local storage" + - link: "/static_analysis/rules/javascript-browser-security/manual-sanitization" + tag: "manual-sanitization" + text: "Avoid manual sanitization of inputs" + - link: "/static_analysis/rules/javascript-browser-security/postmessage-permissive-origin" + tag: "postmessage-permissive-origin" + text: "Specify origin in postMessage" + - link: "/static_analysis/rules/javascript-browser-security/react-dangerously-inner-html" + tag: "react-dangerously-inner-html" + text: "Do not inject unsanitized HTML" + - link: "/static_analysis/rules/javascript-browser-security/regexp-non-literal" + tag: "regexp-non-literal" + text: "Do not use variable for regular expressions" +javascript_code_style_data: + - link: "/static_analysis/rules/javascript-code-style/assignment-name" + tag: "assignment-name" + text: "Assigment name should use camelCase" + - link: "/static_analysis/rules/javascript-code-style/class-name" + tag: "class-name" + text: "Class name should be PascalCase" + - link: "/static_analysis/rules/javascript-code-style/eqeqeq" + tag: "eqeqeq" + text: "Enforce the use of === and !==" + - link: "/static_analysis/rules/javascript-code-style/func-name-matching" + tag: "func-name-matching" + text: "Function names must match the name of the assignation." + - link: "/static_analysis/rules/javascript-code-style/func-names" + tag: "func-names" + text: "Enforce named function expressions" + - link: "/static_analysis/rules/javascript-code-style/function-naming" + tag: "function-naming" + text: "Function name should use camelCase or PascalCase" + - link: "/static_analysis/rules/javascript-code-style/max-class-lines" + tag: "max-class-lines" + text: "Classes must be less than 100 lines" + - link: "/static_analysis/rules/javascript-code-style/max-function-lines" + tag: "max-function-lines" + text: "Functions must be less than 200 lines" + - link: "/static_analysis/rules/javascript-code-style/max-params" + tag: "max-params" + text: "Enforce a maximum number of parameters in a function" + - link: "/static_analysis/rules/javascript-code-style/method-name" + tag: "method-name" + text: "Method name should use camelCase" + - link: "/static_analysis/rules/javascript-code-style/no-array-constructor" + tag: "no-array-constructor" + text: "Avoid Array constructors" + - link: "/static_analysis/rules/javascript-code-style/no-div-regex" + tag: "no-div-regex" + text: "Avoid equal signs at the beginning of regular expressions" + - link: "/static_analysis/rules/javascript-code-style/no-duplicate-imports" + tag: "no-duplicate-imports" + text: "Avoid duplicate module imports" + - link: "/static_analysis/rules/javascript-code-style/no-floating-decimal" + tag: "no-floating-decimal" + text: "Avoid leading or trailing decimal points in numbers" + - link: "/static_analysis/rules/javascript-code-style/no-lonely-if" + tag: "no-lonely-if" + text: "Avoid if statements as the only statement in else blocks" + - link: "/static_analysis/rules/javascript-code-style/no-multi-assign" + tag: "no-multi-assign" + text: "Avoid the use of chained assignment expressions" + - link: "/static_analysis/rules/javascript-code-style/no-new" + tag: "no-new" + text: "Avoid new operators outside of assignments or comparisons" + - link: "/static_analysis/rules/javascript-code-style/no-new-func" + tag: "no-new-func" + text: "Avoid new operators with the Function object" + - link: "/static_analysis/rules/javascript-code-style/no-new-object" + tag: "no-new-object" + text: "Avoid Object constructors" + - link: "/static_analysis/rules/javascript-code-style/no-return-assign" + tag: "no-return-assign" + text: "Avoid assignment operators in return statements" + - link: "/static_analysis/rules/javascript-code-style/no-self-compare" + tag: "no-self-compare" + text: "Avoid comparisons where both sides are exactly the same" + - link: "/static_analysis/rules/javascript-code-style/no-var" + tag: "no-var" + text: "Require let or const instead of var" + - link: "/static_analysis/rules/javascript-code-style/parameter-name" + tag: "parameter-name" + text: "Parameter name should use camelCase" + - link: "/static_analysis/rules/javascript-code-style/radix" + tag: "radix" + text: "Consistent use of the radix argument using parseInt" +javascript_common_security_data: + - link: "/static_analysis/rules/javascript-common-security/axios-avoid-insecure-http" + tag: "axios-avoid-insecure-http" + text: "Avoid insecure HTTP requests with Axios" + - link: "/static_analysis/rules/javascript-common-security/unique-function-arguments" + tag: "unique-function-arguments" + text: "Function argument names should be unique" + - link: "/static_analysis/rules/javascript-common-security/xml-no-external-entities" + tag: "xml-no-external-entities" + text: "Do not use external XML entities" +javascript_express_data: + - link: "/static_analysis/rules/javascript-express/access-restriction" + tag: "access-restriction" + text: "Limit exposure to sensitive directories and files" + - link: "/static_analysis/rules/javascript-express/default-session-config" + tag: "default-session-config" + text: "Enforce overriding default config" + - link: "/static_analysis/rules/javascript-express/external-filename-upload" + tag: "external-filename-upload" + text: "Avoid using unsanitized user input with sendFile" + - link: "/static_analysis/rules/javascript-express/external-resource" + tag: "external-resource" + text: "Avoid rendering resource based on unsanitized user input" + - link: "/static_analysis/rules/javascript-express/hardcoded-secret" + tag: "hardcoded-secret" + text: "Avoid using a hard-coded secret" + - link: "/static_analysis/rules/javascript-express/https-protocol-missing" + tag: "https-protocol-missing" + text: "Use `https` protocol over `http`" + - link: "/static_analysis/rules/javascript-express/insecure-allow-origin" + tag: "insecure-allow-origin" + text: "Avoid using an insecure Access-Control-Allow-Origin header" + - link: "/static_analysis/rules/javascript-express/insecure-cookie" + tag: "insecure-cookie" + text: "Avoid setting insecure cookie settings" + - link: "/static_analysis/rules/javascript-express/jwt-not-revoked" + tag: "jwt-not-revoked" + text: "Ensure an isRevoked method is used for tokens" + - link: "/static_analysis/rules/javascript-express/missing-helmet" + tag: "missing-helmet" + text: "Express application should use Helmet" + - link: "/static_analysis/rules/javascript-express/path-traversal" + tag: "path-traversal" + text: "Avoid allowing access to unintended directories or files" + - link: "/static_analysis/rules/javascript-express/reduce-server-fingerprinting" + tag: "reduce-server-fingerprinting" + text: "Server fingerprinting misconfiguration" + - link: "/static_analysis/rules/javascript-express/xss-vulnerability" + tag: "xss-vulnerability" + text: "Avoid sending unsanitized user input in response" +javascript_inclusive_data: + - link: "/static_analysis/rules/javascript-inclusive/comments" + tag: "comments" + text: "Check comments for wording issues" + - link: "/static_analysis/rules/javascript-inclusive/declarations" + tag: "declarations" + text: "Check declaration names for wording issues" + - link: "/static_analysis/rules/javascript-inclusive/formal-parameters" + tag: "formal-parameters" + text: "Check parameter names for wording issues" + - link: "/static_analysis/rules/javascript-inclusive/identifiers" + tag: "identifiers" + text: "Check identifier names for wording issues" +javascript_node_security_data: + - link: "/static_analysis/rules/javascript-node-security/argon2" + tag: "argon2" + text: "Use strong security mechanisms with argon2" + - link: "/static_analysis/rules/javascript-node-security/avoid-crypto-rc4" + tag: "avoid-crypto-rc4" + text: "Avoid RC4" + - link: "/static_analysis/rules/javascript-node-security/avoid-crypto-sha1" + tag: "avoid-crypto-sha1" + text: "Avoid SHA1 security protocol" + - link: "/static_analysis/rules/javascript-node-security/avoid-des" + tag: "avoid-des" + text: "Avoid DES and 3DES" + - link: "/static_analysis/rules/javascript-node-security/chmod-permissions" + tag: "chmod-permissions" + text: "Do not give 777 permissions to a file" + - link: "/static_analysis/rules/javascript-node-security/command-injection" + tag: "command-injection" + text: "Avoid command injection" + - link: "/static_analysis/rules/javascript-node-security/crypto-avoid-weak-hash" + tag: "crypto-avoid-weak-hash" + text: "Avoid weak hash algorithm from CryptoJS" + - link: "/static_analysis/rules/javascript-node-security/detect-buffer-noassert" + tag: "detect-buffer-noassert" + text: "Avoid calls to 'buffer' with 'noAssert' flag set" + - link: "/static_analysis/rules/javascript-node-security/detect-child-process" + tag: "detect-child-process" + text: "Avoid instances of 'child_process' and non-literal 'exec()'" + - link: "/static_analysis/rules/javascript-node-security/detect-eval-with-expression" + tag: "detect-eval-with-expression" + text: "Avoid `eval` with expressions" + - link: "/static_analysis/rules/javascript-node-security/detect-new-buffer" + tag: "detect-new-buffer" + text: "Avoid Buffer(argument) with non-literal values" + - link: "/static_analysis/rules/javascript-node-security/detect-non-literal-fs-filename" + tag: "detect-non-literal-fs-filename" + text: "Avoid variables in 'fs' calls filename argument" + - link: "/static_analysis/rules/javascript-node-security/detect-non-literal-regexp" + tag: "detect-non-literal-regexp" + text: "Detects non-literal values in regular expressions" + - link: "/static_analysis/rules/javascript-node-security/detect-non-literal-require" + tag: "detect-non-literal-require" + text: "Avoid require with non-literal values" + - link: "/static_analysis/rules/javascript-node-security/detected-jwt-token" + tag: "detected-jwt-token" + text: "Detects hardcoded JWT tokens within the codebase." + - link: "/static_analysis/rules/javascript-node-security/hardcoded-hmac-key" + tag: "hardcoded-hmac-key" + text: "Avoid hardcoded HMAC keys" + - link: "/static_analysis/rules/javascript-node-security/insecure-hash" + tag: "insecure-hash" + text: "Do not use weak hash functions" + - link: "/static_analysis/rules/javascript-node-security/insecure-jwt-secret-usage" + tag: "insecure-jwt-secret-usage" + text: "Insecure Usage of a Static Secret in JWT Signing" + - link: "/static_analysis/rules/javascript-node-security/jwt-hardcoded-secret" + tag: "jwt-hardcoded-secret" + text: "Do not use hardcoded secret with a JWT" + - link: "/static_analysis/rules/javascript-node-security/jwt-sensitive-data" + tag: "jwt-sensitive-data" + text: "Do not put sensitive data in objects" + - link: "/static_analysis/rules/javascript-node-security/jwt-weak-encryption" + tag: "jwt-weak-encryption" + text: "Use default encryption from the JWT library" + - link: "/static_analysis/rules/javascript-node-security/log-sensitive-data" + tag: "log-sensitive-data" + text: "Avoid logging sensitive data" + - link: "/static_analysis/rules/javascript-node-security/oauth2-hardcoded-secret" + tag: "oauth2-hardcoded-secret" + text: "Do not use hardcoded secret for OAuth2 providers" + - link: "/static_analysis/rules/javascript-node-security/sql-injection" + tag: "sql-injection" + text: "Avoid SQL injection" + - link: "/static_analysis/rules/javascript-node-security/variable-sql-statement-injection" + tag: "variable-sql-statement-injection" + text: "Avoid SQL injections" +jsx_react_data: + - link: "/static_analysis/rules/jsx-react/jsx-key" + tag: "jsx-key" + text: "Prevent missing key props in iterators/collection literals" + - link: "/static_analysis/rules/jsx-react/jsx-no-comment-textnodes" + tag: "jsx-no-comment-textnodes" + text: "Avoid comments from being inserted as text nodes" + - link: "/static_analysis/rules/jsx-react/jsx-no-duplicate-key" + tag: "jsx-no-duplicate-key" + text: "Ensures unique key prop" + - link: "/static_analysis/rules/jsx-react/jsx-no-duplicate-props" + tag: "jsx-no-duplicate-props" + text: "Avoid duplicate properties in JSX" + - link: "/static_analysis/rules/jsx-react/jsx-no-target-blank" + tag: "jsx-no-target-blank" + text: "Prevent target='_blank' security risks" + - link: "/static_analysis/rules/jsx-react/no-children-prop" + tag: "no-children-prop" + text: "Avoid passing children as props" + - link: "/static_analysis/rules/jsx-react/no-danger-with-children" + tag: "no-danger-with-children" + text: "Avoid using children with dangerouslySetInnerHTML" + - link: "/static_analysis/rules/jsx-react/no-deprecated" + tag: "no-deprecated" + text: "Avoid deprecated methods" + - link: "/static_analysis/rules/jsx-react/no-render-return-value" + tag: "no-render-return-value" + text: "Avoid usage of the return value of ReactDOM.render" + - link: "/static_analysis/rules/jsx-react/no-string-refs" + tag: "no-string-refs" + text: "Avoid using string references" + - link: "/static_analysis/rules/jsx-react/require-render-return" + tag: "require-render-return" + text: "Enforce class for returning value in render function" +python_best_practices_data: + - link: "/static_analysis/rules/python-best-practices/ambiguous-class-name" + tag: "ambiguous-class-name" + text: "make sure class names are readable" + - link: "/static_analysis/rules/python-best-practices/ambiguous-function-name" + tag: "ambiguous-function-name" + text: "make sure function names are readable" + - link: "/static_analysis/rules/python-best-practices/ambiguous-variable-name" + tag: "ambiguous-variable-name" + text: "make sure variable names are readable" + - link: "/static_analysis/rules/python-best-practices/any-type-disallow" + tag: "any-type-disallow" + text: "do not use Any type" + - link: "/static_analysis/rules/python-best-practices/argument-same-name" + tag: "argument-same-name" + text: "do not have arguments with the same name" + - link: "/static_analysis/rules/python-best-practices/assertraises-specific-exception" + tag: "assertraises-specific-exception" + text: "assertRaises must check for a specific exception" + - link: "/static_analysis/rules/python-best-practices/avoid-duplicate-keys" + tag: "avoid-duplicate-keys" + text: "Avoid duplicate keys in dictionaries" + - link: "/static_analysis/rules/python-best-practices/avoid-string-concat" + tag: "avoid-string-concat" + text: "avoid string concatenation" + - link: "/static_analysis/rules/python-best-practices/class-methods-use-self" + tag: "class-methods-use-self" + text: "Class methods should not use self" + - link: "/static_analysis/rules/python-best-practices/collection-while-iterating" + tag: "collection-while-iterating" + text: "do not modify a dictionary while iterating on it" + - link: "/static_analysis/rules/python-best-practices/comment-fixme-todo-ownership" + tag: "comment-fixme-todo-ownership" + text: "TODO and FIXME comments must have ownership" + - link: "/static_analysis/rules/python-best-practices/comparison-constant-left" + tag: "comparison-constant-left" + text: "in comparisons, variables must be left" + - link: "/static_analysis/rules/python-best-practices/condition-similar-block" + tag: "condition-similar-block" + text: "if conditions must have different code blocks" + - link: "/static_analysis/rules/python-best-practices/ctx-manager-enter-exit-defined" + tag: "ctx-manager-enter-exit-defined" + text: "ensure that both __exit__ and __enter__ are defined" + - link: "/static_analysis/rules/python-best-practices/dataclass-special-methods" + tag: "dataclass-special-methods" + text: "do not use special method on data class" + - link: "/static_analysis/rules/python-best-practices/equal-basic-types" + tag: "equal-basic-types" + text: "check equal is used on consistent basic types" + - link: "/static_analysis/rules/python-best-practices/exception-inherit" + tag: "exception-inherit" + text: "ensure exception inherit a base exception" + - link: "/static_analysis/rules/python-best-practices/finally-no-break-continue-return" + tag: "finally-no-break-continue-return" + text: "do not use break or continue in finally block" + - link: "/static_analysis/rules/python-best-practices/function-already-exists" + tag: "function-already-exists" + text: "a function must be defined only once" + - link: "/static_analysis/rules/python-best-practices/function-variable-argument-name" + tag: "function-variable-argument-name" + text: "Do not assign to function arguments" + - link: "/static_analysis/rules/python-best-practices/generic-exception-last" + tag: "generic-exception-last" + text: "If using generic exception, it should be last" + - link: "/static_analysis/rules/python-best-practices/get-set-arguments" + tag: "get-set-arguments" + text: "getter/setter must have 1 or 2 arguments respectively" + - link: "/static_analysis/rules/python-best-practices/if-return-no-else" + tag: "if-return-no-else" + text: "when an if condition returns an value, else is not necessary" + - link: "/static_analysis/rules/python-best-practices/import-modules-twice" + tag: "import-modules-twice" + text: "module imported twice" + - link: "/static_analysis/rules/python-best-practices/import-single-module" + tag: "import-single-module" + text: "only one module to import per import statement" + - link: "/static_analysis/rules/python-best-practices/init-call-parent" + tag: "init-call-parent" + text: "use super() to call the parent constructor" + - link: "/static_analysis/rules/python-best-practices/init-method-required" + tag: "init-method-required" + text: "ensure classes have an __init__ method" + - link: "/static_analysis/rules/python-best-practices/init-no-return-value" + tag: "init-no-return-value" + text: "No return in an __init__ function" + - link: "/static_analysis/rules/python-best-practices/invalid-strip-call" + tag: "invalid-strip-call" + text: "strip() argument should not have duplicate characters" + - link: "/static_analysis/rules/python-best-practices/logging-no-format" + tag: "logging-no-format" + text: "do not use format string with logging functions" + - link: "/static_analysis/rules/python-best-practices/method-hidden" + tag: "method-hidden" + text: "a method has the same name than an attribute" + - link: "/static_analysis/rules/python-best-practices/nested-blocks" + tag: "nested-blocks" + text: "Do not have too many nested blocks" + - link: "/static_analysis/rules/python-best-practices/no-assert" + tag: "no-assert" + text: "do not use assert in production code" + - link: "/static_analysis/rules/python-best-practices/no-assert-on-tuples" + tag: "no-assert-on-tuples" + text: "no assert on tuples" + - link: "/static_analysis/rules/python-best-practices/no-bare-except" + tag: "no-bare-except" + text: "do not use bare except" + - link: "/static_analysis/rules/python-best-practices/no-bare-raise" + tag: "no-bare-raise" + text: "Do not use a raise statement without a specific exception" + - link: "/static_analysis/rules/python-best-practices/no-base-exception" + tag: "no-base-exception" + text: "do not raise base exception" + - link: "/static_analysis/rules/python-best-practices/no-datetime-today" + tag: "no-datetime-today" + text: "do not use datetime.today()" + - link: "/static_analysis/rules/python-best-practices/no-double-not" + tag: "no-double-not" + text: "do not use double negation" + - link: "/static_analysis/rules/python-best-practices/no-double-unary-operator" + tag: "no-double-unary-operator" + text: "do not use operator -- and ++" + - link: "/static_analysis/rules/python-best-practices/no-duplicate-base-class" + tag: "no-duplicate-base-class" + text: "use a base class only once" + - link: "/static_analysis/rules/python-best-practices/no-equal-unary" + tag: "no-equal-unary" + text: "do not use operations =+ and =-" + - link: "/static_analysis/rules/python-best-practices/no-exit" + tag: "no-exit" + text: "do not use exit()" + - link: "/static_analysis/rules/python-best-practices/no-generic-exception" + tag: "no-generic-exception" + text: "Do not use generic exceptions" + - link: "/static_analysis/rules/python-best-practices/no-if-true" + tag: "no-if-true" + text: "do not compare to True in a condition" + - link: "/static_analysis/rules/python-best-practices/no-range-loop-with-len" + tag: "no-range-loop-with-len" + text: "Do not use for i in range(len())" + - link: "/static_analysis/rules/python-best-practices/no-silent-exception" + tag: "no-silent-exception" + text: "Do not ignore Exception with a pass statement" + - link: "/static_analysis/rules/python-best-practices/open-add-flag" + tag: "open-add-flag" + text: "do not define an open flag for reading" + - link: "/static_analysis/rules/python-best-practices/os-environ-no-assign" + tag: "os-environ-no-assign" + text: "assigning to os.environ does not clear the environment" + - link: "/static_analysis/rules/python-best-practices/raising-not-implemented" + tag: "raising-not-implemented" + text: "Do not raise NotImplemented - it does not exists" + - link: "/static_analysis/rules/python-best-practices/return-bytes-not-string" + tag: "return-bytes-not-string" + text: "__bytes__ method should returns bytes, not string" + - link: "/static_analysis/rules/python-best-practices/return-outside-function" + tag: "return-outside-function" + text: "do not return outside a function" + - link: "/static_analysis/rules/python-best-practices/self-assignment" + tag: "self-assignment" + text: "do not assign to itself" + - link: "/static_analysis/rules/python-best-practices/slots-no-single-string" + tag: "slots-no-single-string" + text: "__slots__ should not be a single string" + - link: "/static_analysis/rules/python-best-practices/special-methods-arguments" + tag: "special-methods-arguments" + text: "ensure special methods have the correct arguments" + - link: "/static_analysis/rules/python-best-practices/static-method-no-self" + tag: "static-method-no-self" + text: "do not use self as parameter for static methods" + - link: "/static_analysis/rules/python-best-practices/too-many-nested-if" + tag: "too-many-nested-if" + text: "do not use too many nested if conditions" + - link: "/static_analysis/rules/python-best-practices/too-many-while" + tag: "too-many-while" + text: "do not use too many nested loops and conditions " + - link: "/static_analysis/rules/python-best-practices/type-check-isinstance" + tag: "type-check-isinstance" + text: "use isinstance instead of type" + - link: "/static_analysis/rules/python-best-practices/unreachable-code" + tag: "unreachable-code" + text: "avoid unreachable code" + - link: "/static_analysis/rules/python-best-practices/use-callable-not-hasattr" + tag: "use-callable-not-hasattr" + text: "do not use hasattr to check if a value is callable" +python_code_style_data: + - link: "/static_analysis/rules/python-code-style/assignment-names" + tag: "assignment-names" + text: "variable names must use snake_case" + - link: "/static_analysis/rules/python-code-style/class-name" + tag: "class-name" + text: "class name should be CamelCase" + - link: "/static_analysis/rules/python-code-style/function-naming" + tag: "function-naming" + text: "function name and parameters should use snake_case" + - link: "/static_analysis/rules/python-code-style/max-class-lines" + tag: "max-class-lines" + text: "classes must be less than 100 lines" + - link: "/static_analysis/rules/python-code-style/max-function-lines" + tag: "max-function-lines" + text: "Functions must be less than 200 lines" +python_design_data: + - link: "/static_analysis/rules/python-design/function-too-long" + tag: "function-too-long" + text: "functions must have less than 100 lines" +python_django_data: + - link: "/static_analysis/rules/python-django/http-response-from-request" + tag: "http-response-from-request" + text: "Lack of sanitization of user data" + - link: "/static_analysis/rules/python-django/http-response-with-json-dumps" + tag: "http-response-with-json-dumps" + text: "use JsonResponse instead of HttpResponse to send JSON data" + - link: "/static_analysis/rules/python-django/jsonresponse-no-content-type" + tag: "jsonresponse-no-content-type" + text: "do not specify content-type for JsonResponse" + - link: "/static_analysis/rules/python-django/model-charfield-max-length" + tag: "model-charfield-max-length" + text: "always specify max_length for a Charfield" + - link: "/static_analysis/rules/python-django/model-help-text" + tag: "model-help-text" + text: "use help_text to document model columns" + - link: "/static_analysis/rules/python-django/no-null-boolean" + tag: "no-null-boolean" + text: "do not use NullBooleanField" + - link: "/static_analysis/rules/python-django/no-unicode-on-models" + tag: "no-unicode-on-models" + text: "do not use __unicode__" + - link: "/static_analysis/rules/python-django/open-filename-from-request" + tag: "open-filename-from-request" + text: "Filename coming from the request" + - link: "/static_analysis/rules/python-django/os-system-from-request" + tag: "os-system-from-request" + text: "Command coming from incoming request" + - link: "/static_analysis/rules/python-django/subprocess-from-request" + tag: "subprocess-from-request" + text: "Command coming from incoming request" + - link: "/static_analysis/rules/python-django/use-convenience-imports" + tag: "use-convenience-imports" + text: "use convenience imports whenever possible" +python_flask_data: + - link: "/static_analysis/rules/python-flask/disable-sqlalchemy-text" + tag: "disable-sqlalchemy-text" + text: "Do not use text() as it leads to SQL injection" + - link: "/static_analysis/rules/python-flask/html-format-from-user-input" + tag: "html-format-from-user-input" + text: "Use of unsanitized data to make API calls" + - link: "/static_analysis/rules/python-flask/listen-all-interfaces" + tag: "listen-all-interfaces" + text: "Your application should not listen on all interfaces" + - link: "/static_analysis/rules/python-flask/no-render-template-string" + tag: "no-render-template-string" + text: "Do not use template created with strings" + - link: "/static_analysis/rules/python-flask/open-file-unsanitized-data" + tag: "open-file-unsanitized-data" + text: "Use of unsanitized data to open file" + - link: "/static_analysis/rules/python-flask/os-system-unsanitized-data" + tag: "os-system-unsanitized-data" + text: "Use of unsanitized data to create processes" + - link: "/static_analysis/rules/python-flask/secure-cookie" + tag: "secure-cookie" + text: "Make sure cookies are safe and secure" + - link: "/static_analysis/rules/python-flask/sqlalchemy-injection" + tag: "sqlalchemy-injection" + text: "Use of unsanitized data to issue SQL queries" + - link: "/static_analysis/rules/python-flask/ssrf-requests" + tag: "ssrf-requests" + text: "Use of unsanitized data to make API calls" + - link: "/static_analysis/rules/python-flask/urlopen-unsanitized-data" + tag: "urlopen-unsanitized-data" + text: "Use of unsanitized data to open API" + - link: "/static_analysis/rules/python-flask/use-jsonify" + tag: "use-jsonify" + text: "use jsonify instead of json.dumps for JSON output" +python_inclusive_data: + - link: "/static_analysis/rules/python-inclusive/comments" + tag: "comments" + text: "check comments for wording issues" + - link: "/static_analysis/rules/python-inclusive/function-definition" + tag: "function-definition" + text: "check function names for wording issues" + - link: "/static_analysis/rules/python-inclusive/variable-name" + tag: "variable-name" + text: "check variable names for wording issues" +python_pandas_data: + - link: "/static_analysis/rules/python-pandas/arith-operator-not-functions" + tag: "arith-operator-not-functions" + text: "Use arithmetic operator instead of a function" + - link: "/static_analysis/rules/python-pandas/avoid-inplace" + tag: "avoid-inplace" + text: "Avoid using inplace=True" + - link: "/static_analysis/rules/python-pandas/comp-operator-not-function" + tag: "comp-operator-not-function" + text: "Use operators to compare values, not functions" + - link: "/static_analysis/rules/python-pandas/import-as-pd" + tag: "import-as-pd" + text: "Import pandas according to coding guidelines" + - link: "/static_analysis/rules/python-pandas/isna-instead-of-isnull" + tag: "isna-instead-of-isnull" + text: "Use isna instead of isnull" + - link: "/static_analysis/rules/python-pandas/loc-not-ix" + tag: "loc-not-ix" + text: "prefer iloc or loc rather than ix" + - link: "/static_analysis/rules/python-pandas/notna-instead-of-notnull" + tag: "notna-instead-of-notnull" + text: "prefer notna to notnull" + - link: "/static_analysis/rules/python-pandas/pivot-table" + tag: "pivot-table" + text: "Use pivot_table instead of pivot or unstack" + - link: "/static_analysis/rules/python-pandas/use-read-csv-not-read-table" + tag: "use-read-csv-not-read-table" + text: "prefer read_csv to read_table" +python_security_data: + - link: "/static_analysis/rules/python-security/asyncio-subprocess-create-shell" + tag: "asyncio-subprocess-create-shell" + text: "Unsafe execution of shell commands" + - link: "/static_analysis/rules/python-security/asyncio-subprocess-exec" + tag: "asyncio-subprocess-exec" + text: "Unsafe execution of shell commands" + - link: "/static_analysis/rules/python-security/avoid-random" + tag: "avoid-random" + text: "use secrets package over random package" + - link: "/static_analysis/rules/python-security/aws-boto-credentials" + tag: "aws-boto-credentials" + text: "use env vars over hardcoded values" + - link: "/static_analysis/rules/python-security/deserialize-untrusted-data" + tag: "deserialize-untrusted-data" + text: "avoid unsafe function to (de)serialize data" + - link: "/static_analysis/rules/python-security/file-write-others" + tag: "file-write-others" + text: "do not let all users write permissions" + - link: "/static_analysis/rules/python-security/hardcoded-tmp-file" + tag: "hardcoded-tmp-file" + text: "Do not hardcode temp file or directory" + - link: "/static_analysis/rules/python-security/html-string-from-parameters" + tag: "html-string-from-parameters" + text: "Avoid HTML built in strings" + - link: "/static_analysis/rules/python-security/insecure-hash-functions" + tag: "insecure-hash-functions" + text: "Do not use insecure functions" + - link: "/static_analysis/rules/python-security/insecure-jwt" + tag: "insecure-jwt" + text: "Ensure JWT signatures are verified" + - link: "/static_analysis/rules/python-security/insecure-ssl-protocols" + tag: "insecure-ssl-protocols" + text: "Do not use insecure encryption protocols" + - link: "/static_analysis/rules/python-security/jinja-autoescape" + tag: "jinja-autoescape" + text: "Auto escape should be set to true" + - link: "/static_analysis/rules/python-security/mktemp" + tag: "mktemp" + text: "Make sure temporary files are secure" + - link: "/static_analysis/rules/python-security/no-empty-array-as-parameter" + tag: "no-empty-array-as-parameter" + text: "Do not use empty array as default parameter" + - link: "/static_analysis/rules/python-security/no-eval" + tag: "no-eval" + text: "use of eval can be insecure" + - link: "/static_analysis/rules/python-security/os-spawn" + tag: "os-spawn" + text: "Call of a spawn process without sanitization" + - link: "/static_analysis/rules/python-security/os-system" + tag: "os-system" + text: "Command execution without sanitization" + - link: "/static_analysis/rules/python-security/request-verify" + tag: "request-verify" + text: "verify should be True" + - link: "/static_analysis/rules/python-security/requests-http" + tag: "requests-http" + text: "Do not make http calls without encryption" + - link: "/static_analysis/rules/python-security/requests-timeout" + tag: "requests-timeout" + text: "no timeout was given on call to external resource" + - link: "/static_analysis/rules/python-security/ruamel-unsafe-yaml" + tag: "ruamel-unsafe-yaml" + text: "Do not use insecure YAML deserialization" + - link: "/static_analysis/rules/python-security/sql-server-security-credentials" + tag: "sql-server-security-credentials" + text: "do not pass hardcoded credentials" + - link: "/static_analysis/rules/python-security/ssl-unverified-context" + tag: "ssl-unverified-context" + text: "should not bypass certificate verification" + - link: "/static_analysis/rules/python-security/subprocess-shell-true" + tag: "subprocess-shell-true" + text: "shell argument leads to unnecessary privileges" + - link: "/static_analysis/rules/python-security/variable-sql-statement-injection" + tag: "variable-sql-statement-injection" + text: "Avoid SQL injections" + - link: "/static_analysis/rules/python-security/yaml-load" + tag: "yaml-load" + text: "avoid deserializing untrusted YAML" +tsx_react_data: + - link: "/static_analysis/rules/tsx-react/jsx-no-comment-textnodes" + tag: "jsx-no-comment-textnodes" + text: "Avoid comments from being inserted as text nodes" + - link: "/static_analysis/rules/tsx-react/no-children-prop" + tag: "no-children-prop" + text: "Avoid passing children as props" + - link: "/static_analysis/rules/tsx-react/no-danger-with-children" + tag: "no-danger-with-children" + text: "Avoid using children with dangerouslySetInnerHTML" + - link: "/static_analysis/rules/tsx-react/no-deprecated" + tag: "no-deprecated" + text: "Avoid deprecated methods" + - link: "/static_analysis/rules/tsx-react/no-render-return-value" + tag: "no-render-return-value" + text: "Avoid usage of the return value of ReactDOM.render" + - link: "/static_analysis/rules/tsx-react/no-string-refs" + tag: "no-string-refs" + text: "Avoid using string references" + - link: "/static_analysis/rules/tsx-react/require-render-return" + tag: "require-render-return" + text: "Enforce class for returning value in render function" + - link: "/static_analysis/rules/tsx-react/tsx-key" + tag: "tsx-key" + text: "Prevent missing key props in iterators/collection literals" + - link: "/static_analysis/rules/tsx-react/tsx-no-duplicate-key" + tag: "tsx-no-duplicate-key" + text: "Ensures unique key prop" + - link: "/static_analysis/rules/tsx-react/tsx-no-target-blank" + tag: "tsx-no-target-blank" + text: "Prevent target='_blank' security risks" +typescript_best_practices_data: + - link: "/static_analysis/rules/typescript-best-practices/ban-types" + tag: "ban-types" + text: "Avoid certain types" + - link: "/static_analysis/rules/typescript-best-practices/boolean-prop-naming" + tag: "boolean-prop-naming" + text: "Consistent naming for boolean props" + - link: "/static_analysis/rules/typescript-best-practices/for-direction" + tag: "for-direction" + text: "Check for loop is moving in the right direction" + - link: "/static_analysis/rules/typescript-best-practices/new-parens" + tag: "new-parens" + text: "Invoking a constructor must use parentheses" + - link: "/static_analysis/rules/typescript-best-practices/no-alert" + tag: "no-alert" + text: "Avoid the use of alert, confirm, and prompt" + - link: "/static_analysis/rules/typescript-best-practices/no-async-promise-executor" + tag: "no-async-promise-executor" + text: "Promise executor cannot be an async function" + - link: "/static_analysis/rules/typescript-best-practices/no-caller" + tag: "no-caller" + text: "Avoid the use of arguments.caller or arguments.callee" + - link: "/static_analysis/rules/typescript-best-practices/no-compare-neg-zero" + tag: "no-compare-neg-zero" + text: "Direct comparison with -0 detected" + - link: "/static_analysis/rules/typescript-best-practices/no-cond-assign" + tag: "no-cond-assign" + text: "Avoid assignment operators in conditional expressions" + - link: "/static_analysis/rules/typescript-best-practices/no-console" + tag: "no-console" + text: "Avoid leaving console debug statements" + - link: "/static_analysis/rules/typescript-best-practices/no-debugger" + tag: "no-debugger" + text: "Disallow the use of debugger" + - link: "/static_analysis/rules/typescript-best-practices/no-delete-var" + tag: "no-delete-var" + text: "Avoid using delete on variables directly" + - link: "/static_analysis/rules/typescript-best-practices/no-dupe-keys" + tag: "no-dupe-keys" + text: "Avoid duplicate keys in object literals" + - link: "/static_analysis/rules/typescript-best-practices/no-duplicate-enum-values" + tag: "no-duplicate-enum-values" + text: "Avoid duplicate enum member values" + - link: "/static_analysis/rules/typescript-best-practices/no-duplicate-type-constituents" + tag: "no-duplicate-type-constituents" + text: "Avoid duplicate constituents of unions or intersections" + - link: "/static_analysis/rules/typescript-best-practices/no-empty" + tag: "no-empty" + text: "Avoid empty block statements" + - link: "/static_analysis/rules/typescript-best-practices/no-empty-character-class" + tag: "no-empty-character-class" + text: "Avoid empty character classes in regular expressions" + - link: "/static_analysis/rules/typescript-best-practices/no-empty-pattern" + tag: "no-empty-pattern" + text: "Avoid empty destructuring patterns" + - link: "/static_analysis/rules/typescript-best-practices/no-ex-assign" + tag: "no-ex-assign" + text: "Avoid reassigning exceptions in catch clauses" + - link: "/static_analysis/rules/typescript-best-practices/no-explicit-any" + tag: "no-explicit-any" + text: "Avoid the any type" + - link: "/static_analysis/rules/typescript-best-practices/no-extra-non-null-assertion" + tag: "no-extra-non-null-assertion" + text: "Avoid extra non-null assertions" + - link: "/static_analysis/rules/typescript-best-practices/no-implied-eval" + tag: "no-implied-eval" + text: "Prevent the use methods similar to eval()" + - link: "/static_analysis/rules/typescript-best-practices/no-inner-declarations" + tag: "no-inner-declarations" + text: "Avoid variable or function declaration in nested blocks" + - link: "/static_analysis/rules/typescript-best-practices/no-iterator" + tag: "no-iterator" + text: "Avoid the use of the __iterator__ property" + - link: "/static_analysis/rules/typescript-best-practices/no-loss-of-precision" + tag: "no-loss-of-precision" + text: "Avoid numbers that lose precision" + - link: "/static_analysis/rules/typescript-best-practices/no-namespace" + tag: "no-namespace" + text: "Avoid TypeScript namespaces" + - link: "/static_analysis/rules/typescript-best-practices/no-non-null-optional-chain" + tag: "no-non-null-optional-chain" + text: "Avoid non-null assertions after an optional chain" + - link: "/static_analysis/rules/typescript-best-practices/no-proto" + tag: "no-proto" + text: "Avoid the use of the __proto__ property" + - link: "/static_analysis/rules/typescript-best-practices/no-script-url" + tag: "no-script-url" + text: "Avoid using Javascript in URLs" + - link: "/static_analysis/rules/typescript-best-practices/no-unnecessary-type-constraint" + tag: "no-unnecessary-type-constraint" + text: "Avoid unnecessary constraints on generic types" + - link: "/static_analysis/rules/typescript-best-practices/no-unsafe-assignment" + tag: "no-unsafe-assignment" + text: "Avoid assigning a value with type any" + - link: "/static_analysis/rules/typescript-best-practices/no-unsafe-declaration-merging" + tag: "no-unsafe-declaration-merging" + text: "Avoid unsafe declaration merging" + - link: "/static_analysis/rules/typescript-best-practices/no-unsafe-negation" + tag: "no-unsafe-negation" + text: "Avoid negating the left operand of relational operators" + - link: "/static_analysis/rules/typescript-best-practices/no-var-requires" + tag: "no-var-requires" + text: "Avoid require statements" + - link: "/static_analysis/rules/typescript-best-practices/require-yield" + tag: "require-yield" + text: "Require yield in generator functions" + - link: "/static_analysis/rules/typescript-best-practices/triple-slash-reference" + tag: "triple-slash-reference" + text: "Avoid triple slash in favor of ES6 import declarations" +typescript_browser_security_data: + - link: "/static_analysis/rules/typescript-browser-security/event-check-origin" + tag: "event-check-origin" + text: "Check origin of events" + - link: "/static_analysis/rules/typescript-browser-security/inner-outer-html" + tag: "inner-outer-html" + text: "Do not modify innerHTML or outerHTML" + - link: "/static_analysis/rules/typescript-browser-security/insecure-websocket" + tag: "insecure-websocket" + text: "Websockets must use SSL connections" + - link: "/static_analysis/rules/typescript-browser-security/local-storage-sensitive-data" + tag: "local-storage-sensitive-data" + text: "Do not store sensitive data to local storage" + - link: "/static_analysis/rules/typescript-browser-security/manual-sanitization" + tag: "manual-sanitization" + text: "Avoid manual sanitization of inputs" + - link: "/static_analysis/rules/typescript-browser-security/postmessage-permissive-origin" + tag: "postmessage-permissive-origin" + text: "Specify origin in postMessage" + - link: "/static_analysis/rules/typescript-browser-security/react-dangerously-inner-html" + tag: "react-dangerously-inner-html" + text: "Do not inject unsanitized HTML" + - link: "/static_analysis/rules/typescript-browser-security/regexp-non-literal" + tag: "regexp-non-literal" + text: "Do not use variable for regular expressions" +typescript_code_style_data: + - link: "/static_analysis/rules/typescript-code-style/array-type" + tag: "array-type" + text: "Require consistently using either T[] or Array for arrays" + - link: "/static_analysis/rules/typescript-code-style/assignment-name" + tag: "assignment-name" + text: "Assigment name should use camelCase" + - link: "/static_analysis/rules/typescript-code-style/ban-ts-comment" + tag: "ban-ts-comment" + text: "Avoid @ts- comments" + - link: "/static_analysis/rules/typescript-code-style/ban-tslint-comment" + tag: "ban-tslint-comment" + text: "Avoid using TSLint comments" + - link: "/static_analysis/rules/typescript-code-style/class-name" + tag: "class-name" + text: "Class name should be PascalCase" + - link: "/static_analysis/rules/typescript-code-style/eqeqeq" + tag: "eqeqeq" + text: "Enforce the use of === and !==" + - link: "/static_analysis/rules/typescript-code-style/func-name-matching" + tag: "func-name-matching" + text: "Function names must match the name of the assignation" + - link: "/static_analysis/rules/typescript-code-style/func-names" + tag: "func-names" + text: "Enforce named function expressions" + - link: "/static_analysis/rules/typescript-code-style/function-naming" + tag: "function-naming" + text: "Function name should use camelCase or PascalCase" + - link: "/static_analysis/rules/typescript-code-style/max-class-lines" + tag: "max-class-lines" + text: "Classes must be less than 100 lines" + - link: "/static_analysis/rules/typescript-code-style/max-function-lines" + tag: "max-function-lines" + text: "Functions must be less than 200 lines" + - link: "/static_analysis/rules/typescript-code-style/max-params" + tag: "max-params" + text: "Enforce a maximum number of parameters in a function" + - link: "/static_analysis/rules/typescript-code-style/method-name" + tag: "method-name" + text: "Method name should use camelCase" + - link: "/static_analysis/rules/typescript-code-style/no-array-constructor" + tag: "no-array-constructor" + text: "Avoid Array constructors" + - link: "/static_analysis/rules/typescript-code-style/no-confusing-non-null-assertion" + tag: "no-confusing-non-null-assertion" + text: "Avoid non-null assertion in confusing locations" + - link: "/static_analysis/rules/typescript-code-style/no-div-regex" + tag: "no-div-regex" + text: "Avoid equal signs explicitly at the beginning of regex" + - link: "/static_analysis/rules/typescript-code-style/no-duplicate-imports" + tag: "no-duplicate-imports" + text: "Avoid duplicate module imports" + - link: "/static_analysis/rules/typescript-code-style/no-empty-interface" + tag: "no-empty-interface" + text: "Avoid the declaration of empty interfaces" + - link: "/static_analysis/rules/typescript-code-style/no-floating-decimal" + tag: "no-floating-decimal" + text: "Avoid leading or trailing decimal points in numbers" + - link: "/static_analysis/rules/typescript-code-style/no-inferrable-types" + tag: "no-inferrable-types" + text: "Avoid explicit type declarations for variables and params" + - link: "/static_analysis/rules/typescript-code-style/no-lonely-if" + tag: "no-lonely-if" + text: "Avoid if statements as the only statement in else blocks" + - link: "/static_analysis/rules/typescript-code-style/no-multi-assign" + tag: "no-multi-assign" + text: "Avoid the use of chained assignment expressions" + - link: "/static_analysis/rules/typescript-code-style/no-new" + tag: "no-new" + text: "Avoid new operators outside of assignments or comparisons" + - link: "/static_analysis/rules/typescript-code-style/no-new-func" + tag: "no-new-func" + text: "Avoid new operators with the Function object" + - link: "/static_analysis/rules/typescript-code-style/no-new-object" + tag: "no-new-object" + text: "Avoid Object constructors" + - link: "/static_analysis/rules/typescript-code-style/no-return-assign" + tag: "no-return-assign" + text: "Avoid assignment operators in return statements" + - link: "/static_analysis/rules/typescript-code-style/no-self-compare" + tag: "no-self-compare" + text: "Avoid comparisons where both sides are exactly the same" + - link: "/static_analysis/rules/typescript-code-style/no-useless-empty-export" + tag: "no-useless-empty-export" + text: "Avoid empty exports that don't change anything" + - link: "/static_analysis/rules/typescript-code-style/no-var" + tag: "no-var" + text: "Require let or const instead of var" + - link: "/static_analysis/rules/typescript-code-style/parameter-name" + tag: "parameter-name" + text: "Parameter name should use camelCase" + - link: "/static_analysis/rules/typescript-code-style/radix" + tag: "radix" + text: "Consistent use of the radix argument using parseInt" +typescript_common_security_data: + - link: "/static_analysis/rules/typescript-common-security/axios-avoid-insecure-http" + tag: "axios-avoid-insecure-http" + text: "Avoid insecure HTTP requests with Axios" + - link: "/static_analysis/rules/typescript-common-security/unique-function-arguments" + tag: "unique-function-arguments" + text: "Function argument names should be unique" + - link: "/static_analysis/rules/typescript-common-security/xml-no-external-entities" + tag: "xml-no-external-entities" + text: "Do not use external XML entities" +typescript_express_data: + - link: "/static_analysis/rules/typescript-express/access-restriction" + tag: "access-restriction" + text: "Limit exposure to sensitive directories and files" + - link: "/static_analysis/rules/typescript-express/default-session-config" + tag: "default-session-config" + text: "Enforce overriding default config" + - link: "/static_analysis/rules/typescript-express/external-filename-upload" + tag: "external-filename-upload" + text: "Avoid using unsanitized user input with sendFile" + - link: "/static_analysis/rules/typescript-express/external-resource" + tag: "external-resource" + text: "Avoid rendering resource based on unsanitized user input" + - link: "/static_analysis/rules/typescript-express/hardcoded-secret" + tag: "hardcoded-secret" + text: "Avoid using a hard-coded secret" + - link: "/static_analysis/rules/typescript-express/https-protocol-missing" + tag: "https-protocol-missing" + text: "Use `https` protocol over `http`" + - link: "/static_analysis/rules/typescript-express/insecure-allow-origin" + tag: "insecure-allow-origin" + text: "Avoid using an insecure Access-Control-Allow-Origin header" + - link: "/static_analysis/rules/typescript-express/insecure-cookie" + tag: "insecure-cookie" + text: "Avoid setting insecure cookie settings" + - link: "/static_analysis/rules/typescript-express/jwt-not-revoked" + tag: "jwt-not-revoked" + text: "Ensure an isRevoked method is used for tokens" + - link: "/static_analysis/rules/typescript-express/missing-helmet" + tag: "missing-helmet" + text: "Express application should use Helmet" + - link: "/static_analysis/rules/typescript-express/path-traversal" + tag: "path-traversal" + text: "Avoid allowing access to unintended directories or files" + - link: "/static_analysis/rules/typescript-express/reduce-server-fingerprinting" + tag: "reduce-server-fingerprinting" + text: "Server fingerprinting misconfiguration" + - link: "/static_analysis/rules/typescript-express/xss-vulnerability" + tag: "xss-vulnerability" + text: "Avoid sending unsanitized user input in response" +typescript_inclusive_data: + - link: "/static_analysis/rules/typescript-inclusive/comments" + tag: "comments" + text: "Check comments for wording issues" + - link: "/static_analysis/rules/typescript-inclusive/declarations" + tag: "declarations" + text: "Check declaration names for wording issues" + - link: "/static_analysis/rules/typescript-inclusive/formal-parameters" + tag: "formal-parameters" + text: "Check parameter names for wording issues" + - link: "/static_analysis/rules/typescript-inclusive/identifiers" + tag: "identifiers" + text: "Check identifier names for wording issues" +typescript_node_security_data: + - link: "/static_analysis/rules/typescript-node-security/argon2" + tag: "argon2" + text: "Use strong security mechanisms with argon2" + - link: "/static_analysis/rules/typescript-node-security/avoid-crypto-rc4" + tag: "avoid-crypto-rc4" + text: "Avoid RC4" + - link: "/static_analysis/rules/typescript-node-security/avoid-crypto-sha1" + tag: "avoid-crypto-sha1" + text: "Avoid SHA1 security protocol" + - link: "/static_analysis/rules/typescript-node-security/avoid-des" + tag: "avoid-des" + text: "Avoid DES and 3DES" + - link: "/static_analysis/rules/typescript-node-security/chmod-permissions" + tag: "chmod-permissions" + text: "Do not give 777 permissions to a file" + - link: "/static_analysis/rules/typescript-node-security/command-injection" + tag: "command-injection" + text: "Avoid command injection" + - link: "/static_analysis/rules/typescript-node-security/crypto-avoid-weak-hash" + tag: "crypto-avoid-weak-hash" + text: "Avoid weak hash algorithm from CryptoJS" + - link: "/static_analysis/rules/typescript-node-security/detect-buffer-noassert" + tag: "detect-buffer-noassert" + text: "Avoid calls to 'buffer' with 'noAssert' flag set" + - link: "/static_analysis/rules/typescript-node-security/detect-child-process" + tag: "detect-child-process" + text: "Avoid instances of 'child_process' and non-literal 'exec()'" + - link: "/static_analysis/rules/typescript-node-security/detect-eval-with-expression" + tag: "detect-eval-with-expression" + text: "Avoid `eval` with expressions" + - link: "/static_analysis/rules/typescript-node-security/detect-new-buffer" + tag: "detect-new-buffer" + text: "Avoid Buffer(argument) with non-literal values" + - link: "/static_analysis/rules/typescript-node-security/detect-non-literal-fs-filename" + tag: "detect-non-literal-fs-filename" + text: "Avoid variables in 'fs' calls filename argument" + - link: "/static_analysis/rules/typescript-node-security/detect-non-literal-regexp" + tag: "detect-non-literal-regexp" + text: "Detects non-literal values in regular expressions" + - link: "/static_analysis/rules/typescript-node-security/detect-non-literal-require" + tag: "detect-non-literal-require" + text: "Avoid require with non-literal values" + - link: "/static_analysis/rules/typescript-node-security/detected-jwt-token" + tag: "detected-jwt-token" + text: "Detects hardcoded JWT tokens within the codebase" + - link: "/static_analysis/rules/typescript-node-security/hardcoded-hmac-key" + tag: "hardcoded-hmac-key" + text: "Detects hardcoded HMAC keys" + - link: "/static_analysis/rules/typescript-node-security/insecure-hash" + tag: "insecure-hash" + text: "Do not use weak hash functions" + - link: "/static_analysis/rules/typescript-node-security/insecure-jwt-secret-usage" + tag: "insecure-jwt-secret-usage" + text: "Insecure Usage of a Static Secret in JWT Signing" + - link: "/static_analysis/rules/typescript-node-security/jwt-hardcoded-secret" + tag: "jwt-hardcoded-secret" + text: "Do not use hardcoded secret with a JWT" + - link: "/static_analysis/rules/typescript-node-security/jwt-sensitive-data" + tag: "jwt-sensitive-data" + text: "Do not put sensitive data in objects" + - link: "/static_analysis/rules/typescript-node-security/jwt-weak-encryption" + tag: "jwt-weak-encryption" + text: "Use default encryption from the JWT library" + - link: "/static_analysis/rules/typescript-node-security/log-sensitive-data" + tag: "log-sensitive-data" + text: "Avoid logging sensitive data" + - link: "/static_analysis/rules/typescript-node-security/oauth2-hardcoded-secret" + tag: "oauth2-hardcoded-secret" + text: "Do not use hardcoded secret for OAuth2 providers" + - link: "/static_analysis/rules/typescript-node-security/sql-injection" + tag: "sql-injection" + text: "Avoid SQL injection" +further_reading: + - link: "/static_analysis/" + tag: "Documentation" + text: "Learn about Datadog Static Analysis" +--- + +## Overview + +{{% site-region region="us,us3,us5,eu,ap1" %}} +
+ Static Analysis is in private beta. Python, JavaScript, TypeScript, and Docker are the only supported languages. To request access, contact Support. +
+{{% /site-region %}} + +{{% site-region region="gov" %}} +
+ Static Analysis is not available for the {{< region-param key="dd_site_name" >}} site. +
+{{% /site-region %}} + +Datadog Static Analysis provides out-of-the-box rules to help detect violations in your CI/CD pipelines in code reviews and identify bugs, security, and maintainability issues. For more information, see the [Static Analysis documentation][1]. + +## Docker rules + +### Follow best practices with using Docker + +**Ruleset ID:** `docker-best-practices` + +Best practices for using Docker. + +{{< sa-rule-list "docker_best_practices_data" >}} + +
+ +## JavaScript rules + +### Follow best practices for writing JavaScript code + +**Ruleset ID:** `javascript-best-practices` + +Rules to enforce JavaScript best practices. + +{{< sa-rule-list "javascript_best_practices_data" >}} + +
+ +### Security rules for JavaScript web applications + +**Ruleset ID:** `javascript-browser-security` + +Rules focused on finding security issues in your JavaScript web applications. + +{{< sa-rule-list "javascript_browser_security_data" >}} + +
+ +### Enforce JavaScript code style + +**Ruleset ID:** `javascript-code-style` + +Rules to enforce JavaScript code style. + +{{< sa-rule-list "javascript_code_style_data" >}} + +
+ +### Common security rules for JavaScript + +**Ruleset ID:** `javascript-common-security` + +Rules focused on finding security issues in your JavaScript code. + +{{< sa-rule-list "javascript_common_security_data" >}} + +
+ +### Check for Express.js best practices and security + +**Ruleset ID:** `javascript-express` + +Rules specifically for Express.js best practices and security. + +{{< sa-rule-list "javascript_express_data" >}} + +
+ +### Check JavaScript code for wording issues + +**Ruleset ID:** `javascript-inclusive` + +Rules for JavaScript to avoid inappropriate wording in the code and comments. + +{{< sa-rule-list "javascript_inclusive_data" >}} + +
+ +### Identify potential security hotspots in Node + +**Ruleset ID:** `javascript-node-security` + +Rules to identify potential security hotspots in Node. This may include false positives that require further triage. + +{{< sa-rule-list "javascript_node_security_data" >}} + +
+ +### React specific linting rules + +**Ruleset ID:** `jsx-react` + +This plugin exports a `recommended` configuration that enforces React good practices. + +{{< sa-rule-list "jsx_react_data" >}} + +
+ +## Python rules + +### Follow best practices for writing Python code + +**Ruleset ID:** `python-best-practices` + +Best practices for Python to write efficient and bug-free code. + +{{< sa-rule-list "python_best_practices_data" >}} + +
+ +### Enforce Python code style + +**Ruleset ID:** `python-code-style` + +Rules to enforce Python code style. + +{{< sa-rule-list "python_code_style_data" >}} + +
+ +### Check Python program structure + +**Ruleset ID:** `python-design` + +Rules to check your Python program structure, including things like nested loops. + +{{< sa-rule-list "python_design_data" >}} + +
+ +### Check for Django best practices and security + +**Ruleset ID:** `python-django` + +Rules specifically for Django best practices and security. + +{{< sa-rule-list "python_django_data" >}} + +
+ +### Check for Flask best practices and security + +**Ruleset ID:** `python-flask` + +Rules specifically for Flask best practices and security. + +{{< sa-rule-list "python_flask_data" >}} + +
+ +### Check Python code for wording issues + +**Ruleset ID:** `python-inclusive` + +Rules for Python to avoid inappropriate wording in the code and comments. + +{{< sa-rule-list "python_inclusive_data" >}} + +
+ +### Good practices for data science with pandas + +**Ruleset ID:** `python-pandas` + +A set of rules to check that pandas code is used appropriately. + + - Ensures `import` declarations follow coding guidelines. + - Avoid deprecated code and methods. + - Avoid inefficient code whenever possible. + +{{< sa-rule-list "python_pandas_data" >}} + +
+ +### Ensure your Python code is safe and secure + +**Ruleset ID:** `python-security` + +Rules focused on finding security and vulnerability issues in your Python code, including those found in the OWASP10 and SANS25. + + - Use of bad encryption and hashing protocols + - Lack of access control + - Security misconfiguration + - SQL injections + - Hardcoded credentials + - Shell injection + - Unsafe deserialization + +{{< sa-rule-list "python_security_data" >}} + +
+ +## TypeScript rules + +### TypeScript React code quality + +**Ruleset ID:** `tsx-react` + +This plugin exports a `recommended` configuration that enforces React good practices. + +{{< sa-rule-list "tsx_react_data" >}} + +
+ +### Follow best practices for writing TypeScript code + +**Ruleset ID:** `typescript-best-practices` + +Rules to enforce TypeScript best practices. + +{{< sa-rule-list "typescript_best_practices_data" >}} + +
+ +### Security rules for TypeScript web applications + +**Ruleset ID:** `typescript-browser-security` + +Rules focused on finding security issues in your TypeScript web applications. + +{{< sa-rule-list "typescript_browser_security_data" >}} + +
+ +### TypeScript opinionated code patterns + +**Ruleset ID:** `typescript-code-style` + +Rules considered to be best practice for modern TypeScript codebases, but that do not impact program logic. These rules are generally opinionated about enforcing simpler code patterns. + +{{< sa-rule-list "typescript_code_style_data" >}} + +
+ +### Common security rules for TypeScript + +**Ruleset ID:** `typescript-common-security` + +Rules focused on finding security issues in your TypeScript code. + +{{< sa-rule-list "typescript_common_security_data" >}} + +
+ +### Check for Express.js TypeScript best practices and security + +**Ruleset ID:** `typescript-express` + +Rules specifically for Express.js TypeScript best practices and security. + +{{< sa-rule-list "typescript_express_data" >}} + +
+ +### Check Python code for wording issues + +**Ruleset ID:** `typescript-inclusive` + +Rules for Python to avoid inappropriate wording in the code and comments. + +{{< sa-rule-list "typescript_inclusive_data" >}} + +
+ +### Identify potential security hotspots in Node + +**Ruleset ID:** `typescript-node-security` + +Rules to identify potential security hotspots in Node. This may include false positives that require further triage. + +{{< sa-rule-list "typescript_node_security_data" >}} + +
+ +## Further Reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: /continuous_integration/static_analysis From dfde9c2f26c95c714a67f2f56c1ef194eba7469d Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 14 Dec 2023 10:18:32 -0800 Subject: [PATCH 10/12] DOCS-6238 Add Test Visibility and Intelligent Test Runner Documentation (#20944) * Make Individual Doc Sets * Separate Guide + Troubleshooting Content * More Link Fixes * Naming Nit * Doc Review Co-authored-by: DeForest Richards <56796055+drichards-87@users.noreply.github.com> * One More Co-authored-by: DeForest Richards <56796055+drichards-87@users.noreply.github.com> --------- Co-authored-by: DeForest Richards <56796055+drichards-87@users.noreply.github.com> --- config/_default/menus/menus.en.yaml | 283 ++++++++++-------- .../continuous_integration/guides/_index.md | 5 - .../continuous_integration/search/_index.md | 120 ++------ .../continuous_integration/troubleshooting.md | 179 +---------- .../guide/source-code-integration.md | 6 +- .../intelligent_test_runner/_index.md | 2 + .../intelligent_test_runner/setup/_index.md | 2 + .../intelligent_test_runner/setup/dotnet.md | 1 + .../intelligent_test_runner/setup/java.md | 2 + .../setup/javascript.md | 1 + .../intelligent_test_runner/setup/python.md | 1 + .../intelligent_test_runner/setup/swift.md | 1 + .../troubleshooting/_index.md | 61 ++++ .../tests/_index.md | 37 +-- .../tests/browser_tests.md | 3 +- .../tests/code_coverage.md | 5 +- .../tests/containers.md | 13 +- .../tests/developer_workflows.md | 5 +- content/en/tests/guides/_index.md | 16 + .../guides/add_custom_metrics.md | 2 + .../guides/flaky_test_management.md | 1 + content/en/tests/search/_index.md | 93 ++++++ .../tests/setup/_index.md | 2 + .../tests/setup/dotnet.md | 1 + .../tests/setup/java.md | 1 + .../tests/setup/javascript.md | 1 + .../tests/setup/junit_xml.md | 1 + .../tests/setup/python.md | 1 + .../tests/setup/ruby.md | 1 + .../tests/setup/swift.md | 1 + .../tests/swift_tests.md | 1 + content/en/tests/troubleshooting/_index.md | 175 +++++++++++ 32 files changed, 585 insertions(+), 439 deletions(-) rename content/en/{continuous_integration => }/intelligent_test_runner/_index.md (99%) rename content/en/{continuous_integration => }/intelligent_test_runner/setup/_index.md (82%) rename content/en/{continuous_integration => }/intelligent_test_runner/setup/dotnet.md (98%) rename content/en/{continuous_integration => }/intelligent_test_runner/setup/java.md (99%) rename content/en/{continuous_integration => }/intelligent_test_runner/setup/javascript.md (98%) rename content/en/{continuous_integration => }/intelligent_test_runner/setup/python.md (98%) rename content/en/{continuous_integration => }/intelligent_test_runner/setup/swift.md (96%) create mode 100644 content/en/intelligent_test_runner/troubleshooting/_index.md rename content/en/{continuous_integration => }/tests/_index.md (83%) rename content/en/{continuous_integration => }/tests/browser_tests.md (95%) rename content/en/{continuous_integration => }/tests/code_coverage.md (99%) rename content/en/{continuous_integration => }/tests/containers.md (95%) rename content/en/{continuous_integration => }/tests/developer_workflows.md (94%) create mode 100644 content/en/tests/guides/_index.md rename content/en/{continuous_integration => tests}/guides/add_custom_metrics.md (98%) rename content/en/{continuous_integration => tests}/guides/flaky_test_management.md (98%) create mode 100644 content/en/tests/search/_index.md rename content/en/{continuous_integration => }/tests/setup/_index.md (85%) rename content/en/{continuous_integration => }/tests/setup/dotnet.md (99%) rename content/en/{continuous_integration => }/tests/setup/java.md (99%) rename content/en/{continuous_integration => }/tests/setup/javascript.md (99%) rename content/en/{continuous_integration => }/tests/setup/junit_xml.md (99%) rename content/en/{continuous_integration => }/tests/setup/python.md (99%) rename content/en/{continuous_integration => }/tests/setup/ruby.md (99%) rename content/en/{continuous_integration => }/tests/setup/swift.md (99%) rename content/en/{continuous_integration => }/tests/swift_tests.md (97%) create mode 100644 content/en/tests/troubleshooting/_index.md diff --git a/config/_default/menus/menus.en.yaml b/config/_default/menus/menus.en.yaml index 98e8efdb35645..9c7b4c6160e35 100644 --- a/config/_default/menus/menus.en.yaml +++ b/config/_default/menus/menus.en.yaml @@ -2375,212 +2375,239 @@ main: identifier: ci parent: software_delivery_heading weight: 150000 - - name: Test Visibility - url: continuous_integration/tests/ - parent: ci - identifier: ci_tests - weight: 1 - - name: Setup - url: continuous_integration/tests/setup/ - parent: ci_tests - identifier: ci_tests_setup - weight: 101 - - name: .NET - url: continuous_integration/tests/setup/dotnet/ - parent: ci_tests_setup - identifier: ci_tests_setup_dotnet - weight: 101 - - name: Java - url: continuous_integration/tests/setup/java/ - parent: ci_tests_setup - identifier: ci_tests_setup_java - weight: 102 - - name: JavaScript and TypeScript - url: continuous_integration/tests/setup/javascript/ - parent: ci_tests_setup - identifier: ci_tests_setup_javascript - weight: 103 - - name: Python - url: continuous_integration/tests/setup/python/ - parent: ci_tests_setup - identifier: ci_tests_setup_python - weight: 104 - - name: Ruby - url: continuous_integration/tests/setup/ruby/ - parent: ci_tests_setup - identifier: ci_tests_setup_ruby - weight: 105 - - name: Swift - url: continuous_integration/tests/setup/swift/ - parent: ci_tests_setup - identifier: ci_tests_setup_swift - weight: 106 - - name: JUnit Report Uploads - url: continuous_integration/tests/setup/junit_xml/ - parent: ci_tests_setup - identifier: ci_tests_setup_junit_xml - weight: 107 - - name: Tests in Containers - url: continuous_integration/tests/containers/ - parent: ci_tests - identifier: ci_tests_containers - weight: 103 - - name: Developer Workflows - url: continuous_integration/tests/developer_workflows - parent: ci_tests - identifier: ci_tests_developer_workflows - weight: 104 - - name: Code Coverage - url: continuous_integration/tests/code_coverage - parent: ci_tests - identifier: ci_tests_code_coverage - weight: 105 - - name: Instrument Browser Tests with RUM - url: continuous_integration/tests/browser_tests - parent: ci_tests - identifier: ci_tests_browser_tests - weight: 106 - - name: Instrument Swift Tests with RUM - url: continuous_integration/tests/swift_tests - parent: ci_tests - identifier: ci_tests_swift_tests - weight: 107 - - name: Intelligent Test Runner - url: continuous_integration/intelligent_test_runner/ - parent: ci - identifier: ci_intelligent_test_runner - weight: 2 - - name: Setup - url: continuous_integration/intelligent_test_runner/setup/ - parent: ci_intelligent_test_runner - identifier: ci_intelligent_test_runner_setup - weight: 201 - - name: .NET - url: continuous_integration/intelligent_test_runner/setup/dotnet/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_dotnet - weight: 201 - - name: Java - url: continuous_integration/intelligent_test_runner/setup/java/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_java - weight: 202 - - name: JavaScript and TypeScript - url: continuous_integration/intelligent_test_runner/setup/javascript/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_javascript - weight: 203 - - name: Python - url: continuous_integration/intelligent_test_runner/setup/python/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_python - weight: 204 - - name: Swift - url: continuous_integration/intelligent_test_runner/setup/swift/ - parent: ci_intelligent_test_runner_setup - identifier: ci_itr_swift - weight: 205 - name: Pipeline Visibility url: continuous_integration/pipelines/ parent: ci identifier: pipeline_visibility - weight: 3 + weight: 1 - name: AWS CodePipeline url: continuous_integration/pipelines/awscodepipeline/ parent: pipeline_visibility identifier: ci_awscodepipeline - weight: 301 + weight: 101 - name: Azure url: continuous_integration/pipelines/azure/ parent: pipeline_visibility identifier: ci_azure - weight: 302 + weight: 102 - name: Buildkite url: continuous_integration/pipelines/buildkite/ parent: pipeline_visibility identifier: ci_buildkite - weight: 303 + weight: 103 - name: CircleCI url: continuous_integration/pipelines/circleci/ parent: pipeline_visibility identifier: ci_circleci - weight: 304 + weight: 104 - name: Codefresh url: continuous_integration/pipelines/codefresh/ parent: pipeline_visibility identifier: ci_codefresh - weight: 305 + weight: 105 - name: GitHub Actions url: continuous_integration/pipelines/github/ parent: pipeline_visibility identifier: ci_github - weight: 306 + weight: 106 - name: GitLab url: continuous_integration/pipelines/gitlab/ parent: pipeline_visibility identifier: ci_gitlab - weight: 307 + weight: 107 - name: Jenkins url: continuous_integration/pipelines/jenkins/ parent: pipeline_visibility identifier: ci_jenkins - weight: 308 + weight: 108 - name: TeamCity url: continuous_integration/pipelines/teamcity/ parent: pipeline_visibility identifier: ci_teamcity - weight: 309 + weight: 109 - name: Custom Commands url: continuous_integration/pipelines/custom_commands/ parent: pipeline_visibility identifier: ci_custom_commands - weight: 310 + weight: 110 - name: Custom Tags and Metrics url: continuous_integration/pipelines/custom_tags_and_metrics/ parent: pipeline_visibility identifier: ci_custom_tags_and_metrics - weight: 311 + weight: 111 - name: Search and Manage url: continuous_integration/search/ parent: ci identifier: ci_search - weight: 4 + weight: 2 - name: Explorer - url: continuous_integration/explorer/ + url: continuous_integration/explorer parent: ci identifier: ci_explorer - weight: 5 + weight: 3 - name: Search Syntax url: continuous_integration/explorer/search_syntax/ parent: ci_explorer identifier: ci_explorer_search_syntax - weight: 501 + weight: 301 - name: Facets url: continuous_integration/explorer/facets/ parent: ci_explorer identifier: ci_explorer_facets - weight: 502 + weight: 302 - name: Saved Views url: continuous_integration/explorer/saved_views/ parent: ci_explorer identifier: ci_explorer_saved_views - weight: 502 + weight: 302 - name: Guides url: continuous_integration/guides/ parent: ci identifier: ci_guides - weight: 6 + weight: 4 - name: Troubleshooting url: continuous_integration/troubleshooting/ parent: ci identifier: ci_troubleshooting + weight: 5 + - name: Test Visibility + url: tests/ + pre: ci + parent: software_delivery_heading + identifier: tests + weight: 160000 + - name: Setup + url: tests/setup/ + parent: tests + identifier: tests_setup + weight: 1 + - name: .NET + url: tests/setup/dotnet/ + parent: tests_setup + identifier: tests_setup_dotnet + weight: 101 + - name: Java + url: tests/setup/java/ + parent: tests_setup + identifier: tests_setup_java + weight: 102 + - name: JavaScript and TypeScript + url: tests/setup/javascript/ + parent: tests_setup + identifier: tests_setup_javascript + weight: 103 + - name: Python + url: tests/setup/python/ + parent: tests_setup + identifier: tests_setup_python + weight: 104 + - name: Ruby + url: tests/setup/ruby/ + parent: tests_setup + identifier: tests_setup_ruby + weight: 105 + - name: Swift + url: tests/setup/swift/ + parent: tests_setup + identifier: tests_setup_swift + weight: 106 + - name: JUnit Report Uploads + url: tests/setup/junit_xml/ + parent: tests_setup + identifier: tests_setup_junit_xml + weight: 107 + - name: Tests in Containers + url: tests/containers/ + parent: tests + identifier: tests_containers + weight: 2 + - name: Search and Manage + url: tests/search/ + parent: tests + identifier: tests_search + weight: 3 + - name: Explorer + url: continuous_integration/explorer + parent: tests + identifier: tests_explorer + weight: 4 + - name: Developer Workflows + url: tests/developer_workflows + parent: tests + identifier: tests_developer_workflows + weight: 5 + - name: Code Coverage + url: tests/code_coverage + parent: tests + identifier: tests_code_coverage + weight: 6 + - name: Instrument Browser Tests with RUM + url: tests/browser_tests + parent: tests + identifier: tests_browser_tests weight: 7 + - name: Instrument Swift Tests with RUM + url: tests/swift_tests + parent: tests + identifier: tests_swift_tests + weight: 8 + - name: Guides + url: tests/guides/ + parent: tests + identifier: tests_guides + weight: 9 + - name: Troubleshooting + url: tests/troubleshooting/ + parent: tests + identifier: tests_troubleshooting + weight: 10 + - name: Intelligent Test Runner + url: intelligent_test_runner/ + pre: ci + parent: software_delivery_heading + identifier: intelligent_test_runner + weight: 170000 + - name: Setup + url: intelligent_test_runner/setup/ + parent: intelligent_test_runner + identifier: intelligent_test_runner_setup + weight: 1 + - name: .NET + url: intelligent_test_runner/setup/dotnet/ + parent: intelligent_test_runner_setup + identifier: intelligent_test_runner_setup_dotnet + weight: 101 + - name: Java + url: intelligent_test_runner/setup/java/ + parent: intelligent_test_runner_setup + identifier: intelligent_test_runner_setup_java + weight: 202 + - name: JavaScript and TypeScript + url: intelligent_test_runner/setup/javascript/ + parent: intelligent_test_runner_setup + identifier: intelligent_test_runner_setup_javascript + weight: 103 + - name: Python + url: intelligent_test_runner/setup/python/ + parent: intelligent_test_runner_setup + identifier: intelligent_test_runner_setup_python + weight: 104 + - name: Swift + url: intelligent_test_runner/setup/swift/ + parent: intelligent_test_runner_setup + identifier: intelligent_test_runner_setup_swift + weight: 105 + - name: Troubleshooting + url: intelligent_test_runner/troubleshooting/ + parent: intelligent_test_runner + identifier: intelligent_test_runner_troubleshooting + weight: 2 - name: CD Visibility url: continuous_delivery/ pre: ci identifier: cd parent: software_delivery_heading - weight: 160000 + weight: 180000 - name: Deployment Visibility url: continuous_delivery/deployments identifier: cd_deployments @@ -2621,13 +2648,13 @@ main: pre: ci parent: software_delivery_heading identifier: dora_metrics - weight: 170000 + weight: 190000 - name: Static Analysis url: static_analysis/ pre: ci parent: software_delivery_heading identifier: static_analysis - weight: 180000 + weight: 200000 - name: Rules url: static_analysis/rules parent: static_analysis @@ -2648,7 +2675,7 @@ main: pre: ci parent: software_delivery_heading identifier: quality_gates - weight: 190000 + weight: 210000 - name: Database Monitoring url: database_monitoring/ pre: database-2 diff --git a/content/en/continuous_integration/guides/_index.md b/content/en/continuous_integration/guides/_index.md index 9cc7f12f151b0..d28751f7775bd 100644 --- a/content/en/continuous_integration/guides/_index.md +++ b/content/en/continuous_integration/guides/_index.md @@ -10,11 +10,6 @@ cascade: subcategory: CI Visibility Guides --- -{{< whatsnext desc="Test Visibility Guides:" >}} - {{< nextlink href="/continuous_integration/guides/flaky_test_management" >}}Flaky Test Management{{< /nextlink >}} - {{< nextlink href="/continuous_integration/guides/add_custom_metrics" >}}Add Custom Metrics to Your Tests{{< /nextlink >}} -{{< /whatsnext >}} - {{< whatsnext desc="Pipeline Visibility Guides:" >}} {{< nextlink href="/continuous_integration/guides/ingestion_control" >}}Creating Exclusion Filters for Ingestion Control{{< /nextlink >}} {{< nextlink href="/continuous_integration/guides/pipeline_data_model" >}}Understanding the Pipeline Data Model and Execution Types{{< /nextlink >}} diff --git a/content/en/continuous_integration/search/_index.md b/content/en/continuous_integration/search/_index.md index f8c587cef7541..fe7f442a71454 100644 --- a/content/en/continuous_integration/search/_index.md +++ b/content/en/continuous_integration/search/_index.md @@ -1,18 +1,10 @@ --- -title: Search and Manage CI Pipelines and Tests -description: Learn how to search for your CI pipelines and tests. -aliases: -- /continuous_integration/guides/find_flaky_tests/ -algolia: - rank: 70 - tags: ['flaky test', 'flaky tests', 'test regression', 'test regressions', 'test service', 'test services'] +title: Search and Manage CI Pipelines +description: Learn how to search for your CI pipelines. further_reading: - link: "/continuous_integration/explorer" tag: "Documentation" - text: "Search and filter test runs or pipeline executions" -- link: "/continuous_integration/guides/flaky_test_management" - tag: "Documentation" - text: "Learn how to manage flaky tests" + text: "Search and filter pipeline executions" --- {{< site-region region="gov" >}} @@ -21,10 +13,7 @@ further_reading: ## Overview -{{< tabs >}} -{{% tab "Pipelines" %}} - -The [Pipelines page][101] is useful for developers who want to keep an eye on the build pipeline for their service. +The [Pipelines page][1] is useful for developers who want to keep an eye on the build pipeline for their service. {{< img src="/continuous_integration/pipelines.png" text="CI Pipelines page" style="width:100%" >}} @@ -42,13 +31,13 @@ You can access high-level accumulation and trends, including: ## Search for pipelines -To see your pipelines, navigate to [**CI** > **Pipelines**][101]. +To see your pipelines, navigate to [**CI** > **Pipelines**][1]. -The [Pipelines page][101] shows aggregate stats for the default branch of each pipeline over the selected time frame, as well as the status of the latest pipeline execution. Use this page to see all your pipelines and get a quick view of their health. Only pipelines with Git information associated to the default branch (usually named `main` or `prod`), as well as pipelines without any Git information, are displayed on this page. +The [Pipelines page][1] shows aggregate stats for the default branch of each pipeline over the selected time frame, as well as the status of the latest pipeline execution. Use this page to see all your pipelines and get a quick view of their health. Only pipelines with Git information associated to the default branch (usually named `main` or `prod`), as well as pipelines without any Git information, are displayed on this page. The metrics shown include build frequency, failure rate, median duration, and change in median duration on both an absolute and relative basis. This information reveals which pipelines are high-usage and potentially high-resource consumers, or are experiencing regressions. The last build result, duration, and last runtime shows you the effect of the last commit. -You can filter the page by pipeline name to see the pipelines you're most concerned with. Click on a pipeline that is slow or failing to dig into details that show what commit might have introduced the performance regression or build error. If you are using [Datadog Teams][106], you can filter for specific pipelines associated to your team using [custom tags][107] that match team handles. +You can filter the page by pipeline name to see the pipelines you're most concerned with. Click on a pipeline that is slow or failing to dig into details that show what commit might have introduced the performance regression or build error. If you are using [Datadog Teams][6], you can filter for specific pipelines associated to your team using [custom tags][7] that match team handles. ## Pipeline details and executions @@ -74,9 +63,9 @@ If job log collection is supported and enabled for the CI provider, related log Job log collection is supported for the following providers: -- [GitHub Actions][103] -- [GitLab][104] -- [Jenkins][105] +- [GitHub Actions][3] +- [GitLab][4] +- [Jenkins][5] #### AI-generated log summaries @@ -84,88 +73,13 @@ Job log collection is supported for the following providers: Pipeline Visibility provides AI-generated explanations for pipeline errors based on your CI job logs. These explanations can be found on the **Failed Jobs** tab for each pipeline execution. You can use these summaries to determine whether an error in CI is associated with developer-written code or the CI pipeline itself, as well as troubleshoot execution failures. -[101]: https://app.datadoghq.com/ci/pipelines -[103]: /continuous_integration/pipelines/github/#enable-log-collection -[104]: /continuous_integration/pipelines/gitlab/#enable-job-log-collection-beta -[105]: /continuous_integration/pipelines/jenkins#enable-job-log-collection -[106]: /account_management/teams/ -[107]: /continuous_integration/pipelines/custom_tags_and_metrics/?tab=linux - -{{% /tab %}} -{{% tab "Tests" %}} - -The [Tests page][101] is useful for developers who want to keep an eye on their test results. - -{{< img src="/continuous_integration/tests.png" text="CI Tests page" style="width:100%" >}} - -You can access low-level and immediate insights: - -- See what tests are failing and why. -- See your last commit's test results. -- View the wall time of your tests in your feature branch and compare it to the default branch, to identify if you're about to introduce a performance regression. -- Find out if your commit introduces a new [flaky test][105] that wasn't flaky before, indicating that your code change is what's making it flaky. This gives you the opportunity to fix the problem before proceeding rather than contributing to the number of flaky tests in your CI. - -You can also access high-level accumulation and trends: - -- See the effects that changed code, added tests, and increased complexity have on your test suite performance over time. -- See which tests have become slower over time and identify the commit that introduced the regression. -- Take advantage of Datadog's automatic test flakiness detection and tracking, which shows you which tests are becoming more or less unreliable over time. - -## Search for tests - -To see your tests, navigate to [**CI** > **Tests**][101] and select between the [**Branches**](#branches-view) or [**Default Branches** view](#default-branches-view). - -### Branches view - -The [Branches][102] view of the Tests page lists all branches from all [test services][103] that have reported test results. This tab is useful for individual developers to quickly see the status of tests that run on their code branches and troubleshoot test failures. - -In this page, you can filter the list by name, test service, or commit SHA, or to show only your branches (branches that contain at least one commit authored by you), enable the **My branches** toggle and add the email addresses you use in your Git configuration. - -#### Test results - -For each branch, you can see the test service, the number of failed, passed, and skipped tests, test regressions, wall time, the percentage of change compared to the default branch, when the commit was last updated, and the avatar of the author of the commit. - -Click on a branch to explore the test details page, which includes information about the branch's latest commits, flaky tests, test performance, common error types, and all test runs. - -{{< img src="continuous_integration/test_details.png" alt="Test Details page for a single branch" style="width:100%;">}} - -#### Test suite performance - -There is also information about the [wall time][104] of the most recent test suite run, and a comparison to the average wall time of the default branch. The comparison of your branch's wall time to the default branch's wall time can help you determine if your commit is introducing performance [regressions][106] to your test suite. - -Hovering over the commit author avatar shows detailed information about the latest commit. - -#### Test regressions - -[Test regressions][106] are evaluated per commit in an effort to tie performance regressions to specific code changes. - -#### Investigate for more details - -Click on the row to see test suite run details such as test results for the last commit on this branch (or you can switch branches), failing tests and the most common errors, slow tests, flaky tests, and a complete list of test runs over the time frame selected. You can filter this list of test runs by facet to get to the information you want to see most. - -Click into one of the test runs to see the test trace as a flame graph or a span list. The _Runs (n)_ list on the left lets you quickly access traces for each retry of the test for the same commit. - -#### Explore connections to services, resources, logs, and network events - -Click the CI provider link to examine the Resource, Service, or Analytics page for the test. You can also find complete tags information and links to related log events and network monitoring events. - -### Default Branches view - -The [Default Branches][107] view of the Tests page shows aggregated health metrics for the _default_ branch of each test service. This view is useful for teams to understand the overall health of the service over time. - -The Default Branches view shows similar information to the Branches view, but applied to the default branch. It compares the current wall time with the average default branch wall time to give you an indication of how your test suite performance is trending over time. - -[101]: https://app.datadoghq.com/ci/test-services -[102]: https://app.datadoghq.com/ci/test-services?view=branches -[103]: /glossary/#test-service -[104]: /glossary/#wall-time -[105]: /glossary/#flaky-test -[106]: /glossary/#test-regression -[107]: https://app.datadoghq.com/ci/test-services?view=default-branches - -{{% /tab %}} -{{< /tabs >}} - ## Further reading {{< partial name="whats-next/whats-next.html" >}} + +[1]: https://app.datadoghq.com/ci/pipelines +[3]: /continuous_integration/pipelines/github/#enable-log-collection +[4]: /continuous_integration/pipelines/gitlab/#enable-job-log-collection-beta +[5]: /continuous_integration/pipelines/jenkins#enable-job-log-collection +[6]: /account_management/teams/ +[7]: /continuous_integration/pipelines/custom_tags_and_metrics/?tab=linux \ No newline at end of file diff --git a/content/en/continuous_integration/troubleshooting.md b/content/en/continuous_integration/troubleshooting.md index fb3d9280f8abf..62c37fef52b9b 100644 --- a/content/en/continuous_integration/troubleshooting.md +++ b/content/en/continuous_integration/troubleshooting.md @@ -21,195 +21,24 @@ further_reading: This page provides information to help you troubleshot issues with CI Visibility. If you need additional help, contact [Datadog Support][2]. -## CI tests - -### Your tests are instrumented, but Datadog isn't showing any data - -1. Go to the [**Tests**][3] page for the language you're instrumenting and check that the testing framework you are using is supported in the **Compatibility** section. -2. Check if you see any test results in the [**Test Runs**][4] section. If you do see results there, but not in the [**Tests**][5] section, Git information is missing. See [Data appears in Test Runs but not Tests](#data-appears-in-test-runs-but-not-tests) to troubleshoot it. -3. If you are reporting the data through the Datadog Agent, make sure it is running on the host where tests are run (accessible at `localhost:8126`), or if accessible on another hostname or port, make sure you run your tests with the appropriate Agent hostname set in the `DD_AGENT_HOST` and the appropriate port in `DD_TRACE_AGENT_PORT` environment variables. You can activate [debug mode][6] in the tracer to check if it's able to connect to the Agent. -4. If you still don't see any results, [contact Support][2] for troubleshooting help. - -### You are uploading JUnit test reports with `datadog-ci` but some or all tests are missing -If you are uploading JUnit test report files with `datadog-ci` CLI and you do not see the tests, it is likely the tests are being discarded because the report is considered incorrect. - -The following aspects make a JUnit test report incorrect: -* A timestamp of the reported tests that is older than **71 hours** before the moment the report is uploaded. -* A testsuite without a name. - -### Data appears in test runs but not tests - -If you can see test results data in the **Test Runs** tab, but not the **Tests** tab, Git metadata (repository, commit, or branch) is probably missing. To confirm this is the case, open a test execution in the [**Test Runs**][4] section, and check that there is no `git.repository_url`, `git.commit.sha`, or `git.branch`. If these tags are not populated, nothing shows in the [**Tests**][5] section. - -1. Tracers first use the environment variables, if any, set by the CI provider to collect Git information. See [Running tests inside a container][7] for a list of environment variables that the tracer attempts to read for each supported CI provider. At a minimum, this populates the repository, commit hash, and branch information. -2. Next, tracers fetch Git metadata using the local `.git` folder, if present, by executing `git` commands. This populates all Git metadata fields, including commit message, author, and committer information. Ensure the `.git` folder is present and the `git` binary is installed and in `$PATH`. This information is used to populate attributes not detected in the previous step. -3. You can also provide Git information manually using environment variables, which override information detected by any of the previous steps. - - The supported environment variables for providing Git information are: - - `DD_GIT_REPOSITORY_URL` **(required)** - : URL of the repository where the code is stored. Both HTTP and SSH URLs are supported.
- **Example**: `git@github.com:MyCompany/MyApp.git`, `https://github.com/MyCompany/MyApp.git` - - `DD_GIT_COMMIT_SHA` **(required)** - : Full (40-character long SHA1) commit hash.
- **Example**: `a18ebf361cc831f5535e58ec4fae04ffd98d8152` - - `DD_GIT_BRANCH` - : Git branch being tested. Leave empty if providing tag information instead.
- **Example**: `develop` - - `DD_GIT_TAG` - : Git tag being tested (if applicable). Leave empty if providing branch information instead.
- **Example**: `1.0.1` - - `DD_GIT_COMMIT_MESSAGE` - : Commit message.
- **Example**: `Set release number` - - `DD_GIT_COMMIT_AUTHOR_NAME` - : Commit author name.
- **Example**: `John Smith` - - `DD_GIT_COMMIT_AUTHOR_EMAIL` - : Commit author email.
- **Example**: `john@example.com` - - `DD_GIT_COMMIT_AUTHOR_DATE` - : Commit author date in ISO 8601 format.
- **Example**: `2021-03-12T16:00:28Z` - - `DD_GIT_COMMIT_COMMITTER_NAME` - : Commit committer name.
- **Example**: `Jane Smith` - - `DD_GIT_COMMIT_COMMITTER_EMAIL` - : Commit committer email.
- **Example**: `jane@example.com` - - `DD_GIT_COMMIT_COMMITTER_DATE` - : Commit committer date in ISO 8601 format.
- **Example**: `2021-03-12T16:00:28Z` - -4. If no CI provider environment variables are found, tests results are sent with no Git metadata. - -### The tests wall time is empty - -If you cannot see the tests wall time it is likely that the CI provider metadata is missing. To confirm this is the case, open a test execution in the [**Test Runs**][4] section, and check if the `ci.pipeline.id`, `ci.pipeline.name`, `ci.pipeline.number`, or `ci.job.url` tags are missing. If these tags are not populated, then nothing shows in the wall time column. - -1. Tracers use the environment variables set by the CI provider to collect this information. See [Running tests inside a container][7] for a list of environment variables that the tracer attempts to read for each supported CI provider. Make sure that the environment variables have the expected values set. -2. Check that you are running your tests in a supported CI provider. For a list of supported CI providers, see [Running tests inside a container][7]. Only these CI providers can extract the information to enrich the test metadata with CI information. -3. If you still don't see the wall time, contact [Datadog support][2] for help. - -### The tests wall time is not what is expected - -#### How wall time is calculated -The wall time is defined as the time difference between the start time of the first test and the end time of the last test for the given pipeline. - -This is done using the following algorithm: - -1. Compute a hash based on CI information to group the tests. - 1. If the tests include `ci.job.url`, use this tag to calculate the hash. - 2. If the tests don't include `ci.job.url`, use `ci.pipeline.id` + `ci.pipeline.name` + `ci.pipeline.number` to calculate the hash. -2. The calculated wall time is associated to a given hash. **Note**: If there are multiple jobs that execute tests, the wall time is calculated for each job, and the maximum from all calculated wall times is shown. - -#### Possible issues with wall time calculation -If you're using a library for testing time-dependent code, like [timecop][8] for Ruby or [FreezeGun][9] for Python, it is possible that test timestamps are wrong, and therefore calculated wall times. If this is the case, make sure that modifications to time are rolled back before finishing your tests. - -### The test status numbers are not what is expected - -The test status numbers are calculated based on the unique tests that were collected. The uniqueness of a test is defined not only by its suite and name, but by its test parameters and test configurations as well. - -#### The numbers are lower than expected - -If the numbers are lower than expected, it is likely that either the library or the tool you are using to collect test data cannot collect test parameters and/or some test configurations. - -1. If you are uploading JUnit test report files: - 1. If you are running the same tests in different environment configurations, [make sure you are setting those configuration tags during the upload][10]. - 2. If you are running parameterized tests, it's very likely that the JUnit report does not have that information. [Try using a native library to report test data][3]. -2. If you still don't see the expected results, [contact Datadog support][2] for troubleshooting help. - -#### The passed/failed/skipped numbers are different than expected - -If the same test is collected several times for the same commit but with different status, the aggregated result follows the algorithm in the table below: - -| **Test Status - First Try** | **Test Status - Retry #1** | **Result** | -|-----------------------------|----------------------------|------------| -| `Passed` | `Passed` | `Passed` | -| `Passed` | `Failed` | `Passed` | -| `Passed` | `Skipped` | `Passed` | -| `Failed` | `Passed` | `Passed` | -| `Failed` | `Failed` | `Failed` | -| `Failed` | `Skipped` | `Failed` | -| `Skipped` | `Passed` | `Passed` | -| `Skipped` | `Failed` | `Failed` | -| `Skipped` | `Skipped` | `Skipped` | - -### The default branch is not correct - -#### How it impacts the product - -The default branch is used to power some features of the products, namely: - -- Default branches list on the Tests page: This list only displays default branches. Setting the wrong default branch can result in missing or incorrect data in the default branches list. - -- Wall time comparison for non-default branches: On the Tests page, in the Branches view, the **VS Default** column is calculated by comparing wall time for the current branch against wall time for the default branch. - -- New flaky tests: Tests that are not currently classified as flaky in the default branch. If the default branch is not properly set, this could lead to a wrong number of detected new flaky tests. - -- Pipelines list: The pipelines list only displays default branches. Setting the wrong default branch can result in missing or incorrect data in the pipelines list. - -#### How to fix the default branch - -If you have admin access, you can update it from the [Repository Settings Page][11]. - -## CI pipelines - -### Your Jenkins instance is instrumented, but Datadog isn't showing any data +## Your Jenkins instance is instrumented, but Datadog isn't showing any data 1. Make sure that at least one pipeline has finished executing. Pipeline execution information is only sent after the pipeline has finished. 2. Make sure the Datadog Agent host is properly configured and is reachable by the Datadog Plugin. You can test connectivity by clicking on the **Check connectivity with the Datadog Agent** button on the Jenkins plugin configuration UI. 3. Check for any errors in the Jenkins logs. You can enable debug-level logs for the Datadog plugin by [creating a `logging.properties` file][1] and adding the line: `org.datadog.level = ALL`. -### Pipeline not found +## Pipeline not found A "Pipeline not found" message is shown when you click on incomplete data coming from an in-progress pipeline. Data is received progressively for stages, jobs, or custom commands. Wait until the pipeline has finished and try again. -### Missing pipelines on the Pipelines page +## Missing pipelines on the Pipelines page The pipeline page only displays pipelines with no Git information, or pipelines with Git information which belong to the default branch of the Git repository. -### Missing stages or jobs in summary tables +## Missing stages or jobs in summary tables Missing stages or jobs in the _Pipeline Details_ page might be due to a wrong configuration. Make sure that the pipeline name stored in the stage or job executions matches the **same** name of their parent pipeline. If you are using custom pipelines, refer to the [public API endpoint specification][15]. -## Intelligent Test Runner - -### Intelligent Test Runner is not working - -[Intelligent Test Runner][12] works by analyzing your commit history along with code coverage information about past test runs to determine which tests need to be run and which ones can be safely skipped. A minimum amount of information needs to exist in order for the Intelligent Test Runner to work correctly: - -- Your repository needs to have a commit history of at least two commits in the past month. -- You need to have collected test code coverage in past commits, which happens on test runs where Intelligent Test Runner was enabled. -- Your git clone must contain commit and tree history. Intelligent Test Runner tries to unshallow git clones that do not contain history (`git clone --depth=1`), but that might not work on older versions of git. Automatic unshallowing might require additional set up in some CI providers (Harness CI, for example, requires [extra configuration][13] to make sure your pipeline can execute git commands). If your CI job is using shallow git clones, you can change it to use partial git clones by using the following command: `git clone --filter=blob:none`. - -Due to these restrictions, the first time you enable Intelligent Test Runner, you cannot see any tests skipped and the test execution time may be slower than usual because the code coverage is collected automatically. - -Intelligent Test Runner only takes into account the commit history and test code coverage information for the past month. Additionally, it does not take into account code coverage information that is generated more than one week after a commit was made. - -There is a limitation when [synchronizing a fork through GitHub's UI][14] which causes all tests to be run for the generated synchronization commit. - -### Intelligent Test Runner incorrectly skipped a test - -Intelligent Test Runner performs test impact analysis based on code coverage to determine which tests are impacted by a given commit or set of commits. While this strategy works for the majority of tests, there are known scenarios where Intelligent Test Runner could skip a test that should have been run: - -- Changes in library dependencies. -- Changes in compiler options. -- Changes in external services. -- Changes to data files in data-driven tests. - -If you are authoring a commit that includes any of those cases, you can force-disable test skipping in Intelligent Test Runner by adding `ITR:NoSkip` (case insensitive) anywhere in your Git commit message. - ## Further reading {{< partial name="whats-next/whats-next.html" >}} diff --git a/content/en/integrations/guide/source-code-integration.md b/content/en/integrations/guide/source-code-integration.md index 0ae6400428115..85a4b6869d03e 100644 --- a/content/en/integrations/guide/source-code-integration.md +++ b/content/en/integrations/guide/source-code-integration.md @@ -15,7 +15,7 @@ further_reading: - link: "/serverless/aws_lambda/configuration/?tab=datadogcli#link-errors-to-your-source-code" tag: "Documentation" text: "Learn about Serverless Monitoring" -- link: "/continuous_integration/tests/developer_workflows/" +- link: "/tests/developer_workflows/" tag: "Documentation" text: "Learn about CI Visibility" - link: "/security/application_security/" @@ -363,7 +363,7 @@ Setting up the GitHub integration also allows you to see inline code snippets in [103]: /logs/error_tracking/backend/?tab=serilog#setup [104]: /integrations/guide/source-code-integration/?tab=continuousprofiler#links-to-git-providers [105]: /serverless/aws_lambda/configuration/?tab=datadogcli#link-errors-to-your-source-code -[106]: /continuous_integration/tests/developer_workflows/#open-tests-in-github-and-your-ide +[106]: /tests/developer_workflows/#open-tests-in-github-and-your-ide [107]: /security/application_security/ {{% /tab %}} @@ -463,7 +463,7 @@ You can see links from failed test runs to their source repository in **CI Visib For more information, see [Enhancing Developer Workflows with Datadog][102]. [101]: https://app.datadoghq.com/ci/test-runs -[102]: /continuous_integration/tests/developer_workflows#open-tests-in-github-and-your-ide +[102]: /tests/developer_workflows/#open-tests-in-github-and-your-ide {{% /tab %}} {{% tab "Application Security Monitoring" %}} diff --git a/content/en/continuous_integration/intelligent_test_runner/_index.md b/content/en/intelligent_test_runner/_index.md similarity index 99% rename from content/en/continuous_integration/intelligent_test_runner/_index.md rename to content/en/intelligent_test_runner/_index.md index 9face6f8b99dc..fd7767524f6b1 100644 --- a/content/en/continuous_integration/intelligent_test_runner/_index.md +++ b/content/en/intelligent_test_runner/_index.md @@ -1,6 +1,8 @@ --- title: Intelligent Test Runner kind: documentation +aliases: +- /continuous_integration/intelligent_test_runner/ further_reading: - link: "https://www.datadoghq.com/blog/streamline-ci-testing-with-datadog-intelligent-test-runner/" tag: "Blog" diff --git a/content/en/continuous_integration/intelligent_test_runner/setup/_index.md b/content/en/intelligent_test_runner/setup/_index.md similarity index 82% rename from content/en/continuous_integration/intelligent_test_runner/setup/_index.md rename to content/en/intelligent_test_runner/setup/_index.md index 29ea74017e567..be238e0c9fbd0 100644 --- a/content/en/continuous_integration/intelligent_test_runner/setup/_index.md +++ b/content/en/intelligent_test_runner/setup/_index.md @@ -1,6 +1,8 @@ --- title: Configure the Intelligent Test Runner kind: documentation +aliases: +- /continuous_integration/intelligent_test_runner/setup/ type: multi-code-lang --- diff --git a/content/en/continuous_integration/intelligent_test_runner/setup/dotnet.md b/content/en/intelligent_test_runner/setup/dotnet.md similarity index 98% rename from content/en/continuous_integration/intelligent_test_runner/setup/dotnet.md rename to content/en/intelligent_test_runner/setup/dotnet.md index 0e89b5450edea..580fedee6b21c 100644 --- a/content/en/continuous_integration/intelligent_test_runner/setup/dotnet.md +++ b/content/en/intelligent_test_runner/setup/dotnet.md @@ -6,6 +6,7 @@ type: multi-code-lang code_lang_weight: 0 aliases: - continuous_integration/intelligent_test_runner/dotnet/ + - continuous_integration/intelligent_test_runner/setup/dotnet/ further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/intelligent_test_runner/setup/java.md b/content/en/intelligent_test_runner/setup/java.md similarity index 99% rename from content/en/continuous_integration/intelligent_test_runner/setup/java.md rename to content/en/intelligent_test_runner/setup/java.md index 58c663b3ef5c9..163108bbec05c 100644 --- a/content/en/continuous_integration/intelligent_test_runner/setup/java.md +++ b/content/en/intelligent_test_runner/setup/java.md @@ -7,6 +7,8 @@ type: multi-code-lang code_lang_weight: 10 aliases: - continuous_integration/intelligent_test_runner/java/ + - continuous_integration/intelligent_test_runner/setup/java/ + further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/intelligent_test_runner/setup/javascript.md b/content/en/intelligent_test_runner/setup/javascript.md similarity index 98% rename from content/en/continuous_integration/intelligent_test_runner/setup/javascript.md rename to content/en/intelligent_test_runner/setup/javascript.md index 5f362c65a294f..1a220088d56c7 100644 --- a/content/en/continuous_integration/intelligent_test_runner/setup/javascript.md +++ b/content/en/intelligent_test_runner/setup/javascript.md @@ -6,6 +6,7 @@ type: multi-code-lang code_lang_weight: 20 aliases: - continuous_integration/intelligent_test_runner/javascript/ + - continuous_integration/intelligent_test_runner/setup/javascript/ further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/intelligent_test_runner/setup/python.md b/content/en/intelligent_test_runner/setup/python.md similarity index 98% rename from content/en/continuous_integration/intelligent_test_runner/setup/python.md rename to content/en/intelligent_test_runner/setup/python.md index b264211e64e0f..83c9faad733ec 100644 --- a/content/en/continuous_integration/intelligent_test_runner/setup/python.md +++ b/content/en/intelligent_test_runner/setup/python.md @@ -6,6 +6,7 @@ type: multi-code-lang code_lang_weight: 30 aliases: - continuous_integration/intelligent_test_runner/python/ + - continuous_integration/intelligent_test_runner/setup/python/ further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/intelligent_test_runner/setup/swift.md b/content/en/intelligent_test_runner/setup/swift.md similarity index 96% rename from content/en/continuous_integration/intelligent_test_runner/setup/swift.md rename to content/en/intelligent_test_runner/setup/swift.md index b1388684eff80..1dbe5b11c5953 100644 --- a/content/en/continuous_integration/intelligent_test_runner/setup/swift.md +++ b/content/en/intelligent_test_runner/setup/swift.md @@ -7,6 +7,7 @@ type: multi-code-lang code_lang_weight: 40 aliases: - continuous_integration/intelligent_test_runner/swift/ + - continuous_integration/intelligent_test_runner/setup/swift/ further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/intelligent_test_runner/troubleshooting/_index.md b/content/en/intelligent_test_runner/troubleshooting/_index.md new file mode 100644 index 0000000000000..575933a0bd7e6 --- /dev/null +++ b/content/en/intelligent_test_runner/troubleshooting/_index.md @@ -0,0 +1,61 @@ +--- +title: Intelligent Test Runner Troubleshooting +kind: documentation +further_reading: +- link: "/intelligent_test_runner" + tag: "Documentation" + text: "Learn about the Intelligent Test Runner" +--- + +{{< site-region region="gov" >}} +
Intelligent Test Runner is not available in the selected site ({{< region-param key="dd_site_name" >}}) at this time.
+{{< /site-region >}} + +## Overview + +This page provides information to help you troubleshot issues with Intelligent Test Runner. If you need additional help, contact [Datadog Support][2]. + +## Intelligent Test Runner is not working + +[Intelligent Test Runner][12] works by analyzing your commit history along with code coverage information about past test runs to determine which tests need to be run and which ones can be safely skipped. A minimum amount of information needs to exist in order for Intelligent Test Runner to work correctly: + +- Your repository needs to have a commit history of at least two commits in the past month. +- You need to have collected test code coverage in past commits, which happens on test runs where Intelligent Test Runner was enabled. +- Your git clone must contain commit and tree history. Intelligent Test Runner tries to unshallow git clones that do not contain history (`git clone --depth=1`), but that might not work on older versions of git. Automatic unshallowing might require additional set up in some CI providers (Harness CI, for example, requires [extra configuration][13] to make sure your pipeline can execute git commands). If your CI job is using shallow git clones, you can change it to use partial git clones by using the following command: `git clone --filter=blob:none`. + +Due to these restrictions, the first time you enable Intelligent Test Runner, you cannot see any tests skipped and the test execution time may be slower than usual because the code coverage is collected automatically. + +Intelligent Test Runner only takes into account the commit history and test code coverage information for the past month. Additionally, it does not take into account code coverage information that is generated more than one week after a commit was made. + +There is a limitation when [synchronizing a fork through GitHub's UI][14] which causes all tests to be run for the generated synchronization commit. + +## Intelligent Test Runner incorrectly skipped a test + +Intelligent Test Runner performs test impact analysis based on code coverage to determine which tests are impacted by a given commit or set of commits. While this strategy works for the majority of tests, there are known scenarios where Intelligent Test Runner could skip a test that should have been run: + +- Changes in library dependencies. +- Changes in compiler options. +- Changes in external services. +- Changes to data files in data-driven tests. + +If you are authoring a commit that includes any of those cases, you can force-disable test skipping in Intelligent Test Runner by adding `ITR:NoSkip` (case insensitive) anywhere in your Git commit message. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://www.jenkins.io/doc/book/system-administration/viewing-logs/ +[2]: /help/ +[3]: /continuous_integration/tests/ +[4]: https://app.datadoghq.com/ci/test-runs +[5]: https://app.datadoghq.com/ci/test-services +[6]: /tracing/troubleshooting/tracer_debug_logs +[7]: /continuous_integration/tests/containers/ +[8]: https://github.com/travisjeffery/timecop +[9]: https://github.com/spulec/freezegun +[10]: /continuous_integration/tests/junit_upload/?tabs=linux#collecting-environment-configuration-metadata +[11]: https://app.datadoghq.com/ci/settings/repository +[12]: /continuous_integration/intelligent_test_runner/ +[13]: https://developer.harness.io/kb/continuous-integration/articles/using_git_credentials_from_codebase_connector_in_ci_pipelines_run_step/ +[14]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork#syncing-a-fork-branch-from-the-web-ui +[15]: /api/latest/ci-visibility-pipelines/#send-pipeline-event diff --git a/content/en/continuous_integration/tests/_index.md b/content/en/tests/_index.md similarity index 83% rename from content/en/continuous_integration/tests/_index.md rename to content/en/tests/_index.md index cc31070efef57..c1cab620eaed0 100644 --- a/content/en/continuous_integration/tests/_index.md +++ b/content/en/tests/_index.md @@ -5,6 +5,7 @@ aliases: - /continuous_integration/explore_tests/ - /continuous_integration/guides/test_configurations/ - /continuous_integration/integrate_tests/ + - /continuous_integration/tests/ further_reading: - link: "/monitors/types/ci/" tag: "Documentation" @@ -38,17 +39,17 @@ cascade: ## Setup {{< whatsnext desc="Choose a language to set up Test Visibility in Datadog:" >}} - {{< nextlink href="continuous_integration/tests/setup/dotnet" >}}.NET{{< /nextlink >}} - {{< nextlink href="continuous_integration/tests/setup/java" >}}Java{{< /nextlink >}} - {{< nextlink href="continuous_integration/tests/setup/javascript" >}}JavaScript{{< /nextlink >}} - {{< nextlink href="continuous_integration/tests/setup/python" >}}Python{{< /nextlink >}} - {{< nextlink href="continuous_integration/tests/setup/ruby" >}}Ruby{{< /nextlink >}} - {{< nextlink href="continuous_integration/tests/setup/swift" >}}Swift{{< /nextlink >}} - {{< nextlink href="continuous_integration/tests/junit_upload" >}}Uploading JUnit test report files to Datadog{{< /nextlink >}} - {{< nextlink href="continuous_integration/tests/containers" >}}Tests running in containers{{< /nextlink >}} + {{< nextlink href="tests/setup/dotnet" >}}.NET{{< /nextlink >}} + {{< nextlink href="tests/setup/java" >}}Java{{< /nextlink >}} + {{< nextlink href="tests/setup/javascript" >}}JavaScript{{< /nextlink >}} + {{< nextlink href="tests/setup/python" >}}Python{{< /nextlink >}} + {{< nextlink href="tests/setup/ruby" >}}Ruby{{< /nextlink >}} + {{< nextlink href="tests/setup/swift" >}}Swift{{< /nextlink >}} + {{< nextlink href="tests/setup/junit_xml" >}}Uploading JUnit test report files to Datadog{{< /nextlink >}} + {{< nextlink href="tests/containers" >}}Tests running in containers{{< /nextlink >}} {{< /whatsnext >}} -In addition to tests, CI Visibility provides visibility over the whole testing phase of your project (except for Ruby). +In addition to tests, Test Visibility provides visibility over the whole testing phase of your project (except for Ruby). ### Supported features @@ -73,13 +74,13 @@ In addition to tests, CI Visibility provides visibility over the whole testing p Tests evaluate the behavior of code for a set of given conditions. Some of those conditions are related to the environment where the tests are run, such as the operating system or the runtime used. The same code executed under different sets of conditions can behave differently, so developers usually configure their tests to run in different sets of conditions and validate that the behavior is the expected for all of them. This specific set of conditions is called a *configuration*. -In CI Visibility, a test with multiple configurations is treated as multiple tests with a separate test for each configuration. In the case where one of the configurations fails but the others pass, only that specific test and configuration combination is marked as failed. +In Test Visibility, a test with multiple configurations is treated as multiple tests with a separate test for each configuration. In the case where one of the configurations fails but the others pass, only that specific test and configuration combination is marked as failed. For example, suppose you're testing a single commit and you have a Python test that runs against three different Python versions. If the test fails for one of those versions, that specific test is marked as failed, while the other versions are marked as passed. If you retry the tests against the same commit and now the test for all three Python versions pass, the test with the version that previously failed is now marked as both passed and flaky, while the other two versions remain passed, with no flakiness detected. ### Test configuration attributes -When you run your tests with CI Visibility, the library detects and reports information about the environment where tests are run as test tags. For example, the operating system name, such as `Windows` or `Linux`, and the architecture of the platform, such as `arm64` or `x86_64`, are added as tags on each test. These values are shown in the commit and on branch overview pages when a test fails or is flaky for a specific configuration but not others. +When you run your tests with Test Visibility, the library detects and reports information about the environment where tests are run as test tags. For example, the operating system name, such as `Windows` or `Linux`, and the architecture of the platform, such as `arm64` or `x86_64`, are added as tags on each test. These values are shown in the commit and on branch overview pages when a test fails or is flaky for a specific configuration but not others. The following tags are automatically collected to identify test configurations, and some may only apply to specific platforms: @@ -101,7 +102,7 @@ The following tags are automatically collected to identify test configurations, ## Custom configurations -There are some configurations that cannot be directly identified and reported automatically because they can depend on environment variables, test run arguments, or other approaches that developers use. For those cases, you must provide the configuration details to the library so CI Visibility can properly identify them. +There are some configurations that cannot be directly identified and reported automatically because they can depend on environment variables, test run arguments, or other approaches that developers use. For those cases, you must provide the configuration details to the library so Test Visibility can properly identify them. Define these tags as part of the `DD_TAGS` environment variable using the `test.configuration` prefix. @@ -122,10 +123,10 @@ In order to filter using these configurations tags, [you must create facets for ### Integrations {{< whatsnext desc="Learn about the following integrations with Test Visibility:" >}} -{{< nextlink href="/continuous_integration/tests/developer_workflows" >}}Enhancing Developer Workflows with Datadog{{< /nextlink >}} -{{< nextlink href="/continuous_integration/tests/code_coverage" >}}Code Coverage{{< /nextlink >}} -{{< nextlink href="/continuous_integration/tests/browser_tests" >}}Instrument Cypress Browser Tests with Browser RUM{{< /nextlink >}} -{{< nextlink href="/continuous_integration/tests/swift_tests" >}}Instrument Swift Tests with Browser RUM{{< /nextlink >}} +{{< nextlink href="/tests/developer_workflows/" >}}Enhancing Developer Workflows with Datadog{{< /nextlink >}} +{{< nextlink href="/tests/code_coverage" >}}Code Coverage{{< /nextlink >}} +{{< nextlink href="/tests/browser_tests" >}}Instrument Cypress Browser Tests with Browser RUM{{< /nextlink >}} +{{< nextlink href="/tests/swift_tests" >}}Instrument Swift Tests with Browser RUM{{< /nextlink >}} {{< /whatsnext >}} If [Intelligent Test Runner][13] is enabled for .NET, JavaScript, or Swift, [code coverage information][12], including file names and line numbers covered by each test, are collected from your projects. @@ -146,5 +147,5 @@ When you evaluate failed or flaky tests, or the performance of a CI test on the [9]: https://app.datadoghq.com/notebook/list [10]: https://app.datadoghq.com/ci/test-runs [11]: /monitors/types/ci/ -[12]: /continuous_integration/guides/code_coverage/ -[13]: /continuous_integration/intelligent_test_runner/ +[12]: /tests/code_coverage/ +[13]: /intelligent_test_runner/ diff --git a/content/en/continuous_integration/tests/browser_tests.md b/content/en/tests/browser_tests.md similarity index 95% rename from content/en/continuous_integration/tests/browser_tests.md rename to content/en/tests/browser_tests.md index 3839ad51ad99f..8147e44fd2e60 100644 --- a/content/en/continuous_integration/tests/browser_tests.md +++ b/content/en/tests/browser_tests.md @@ -5,6 +5,7 @@ description: Learn how to use CI Visibility and RUM to connect your test results aliases: - /continuous_integration/guides/rum_integration - /continuous_integration/integrate_tests/browser_tests +- /continuous_integration/tests/browser_tests further_reading: - link: "/continuous_integration/tests" tag: "Documentation" @@ -52,6 +53,6 @@ The RUM session has all the data that [RUM normally collects][3] so you can debu {{< partial name="whats-next/whats-next.html" >}} -[1]: /continuous_integration/tests/javascript/?tab=cypress#instrument-your-tests +[1]: /tests/setup/javascript/?tab=cypress#instrument-your-tests [2]: /real_user_monitoring/browser/ [3]: /real_user_monitoring/browser/data_collected/ diff --git a/content/en/continuous_integration/tests/code_coverage.md b/content/en/tests/code_coverage.md similarity index 99% rename from content/en/continuous_integration/tests/code_coverage.md rename to content/en/tests/code_coverage.md index 112ba92241441..79215fd47b7d4 100644 --- a/content/en/continuous_integration/tests/code_coverage.md +++ b/content/en/tests/code_coverage.md @@ -5,8 +5,9 @@ description: Learn how to report and use code coverage in Datadog. aliases: - /continuous_integration/guides/code_coverage/ - /continuous_integration/integrate_tests/code_coverage/ +- /continuous_integration/tests/code_coverage/ further_reading: -- link: "/continuous_integration/tests" +- link: "/tests" tag: "Documentation" text: "Learn about Test Visibility" - link: "/monitors/types/ci" @@ -234,7 +235,7 @@ Get alerted whenever code coverage for your service drops below a certain thresh {{< partial name="whats-next/whats-next.html" >}} -[1]: /continuous_integration/tests/ +[1]: /tests/ [2]: /dashboards [3]: /notebooks [4]: /monitors diff --git a/content/en/continuous_integration/tests/containers.md b/content/en/tests/containers.md similarity index 95% rename from content/en/continuous_integration/tests/containers.md rename to content/en/tests/containers.md index b4ad6c074d746..bcdeee06867e5 100644 --- a/content/en/continuous_integration/tests/containers.md +++ b/content/en/tests/containers.md @@ -3,10 +3,15 @@ title: Tests in Containers kind: documentation aliases: - /continuous_integration/setup_tests/containers + - /continuous_integration/tests/containers +further_reading: +- link: "/tests" + tag: "Documentation" + text: "Learn about Test Visibility" --- {{< site-region region="gov" >}} -
CI Visibility is not available in the selected site ({{< region-param key="dd_site_name" >}}) at this time.
+
Test Visibility is not available in the selected site ({{< region-param key="dd_site_name" >}}) at this time.
{{< /site-region >}} ## Overview @@ -295,6 +300,10 @@ Additionally, you need to pass in the environment variables required to configur {{% /tab %}} {{< /tabs >}} +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + [1]: https://docs.docker.com/engine/reference/run/ [2]: https://docs.docker.com/compose/reference/ -[3]: /continuous_integration/tests/ +[3]: /tests/ diff --git a/content/en/continuous_integration/tests/developer_workflows.md b/content/en/tests/developer_workflows.md similarity index 94% rename from content/en/continuous_integration/tests/developer_workflows.md rename to content/en/tests/developer_workflows.md index 43e58bdd31f38..60502c8150f2c 100644 --- a/content/en/continuous_integration/tests/developer_workflows.md +++ b/content/en/tests/developer_workflows.md @@ -6,6 +6,7 @@ aliases: - /continuous_integration/guides/developer_workflows - /continuous_integration/guides/pull_request_comments - /continuous_integration/integrate_tests/developer_workflows +- /continuous_integration/tests/developer_workflows further_reading: - link: "https://www.datadoghq.com/blog/datadog-github-actions-ci-visibility/" tag: "Blog" @@ -18,10 +19,10 @@ further_reading: ## Overview {{< site-region region="gov" >}} -
CI Visibility is not available in the selected site ({{< region-param key="dd_site_name" >}}) at this time.
+
Test Visibility is not available in the selected site ({{< region-param key="dd_site_name" >}}) at this time.
{{< /site-region >}} -[CI Test Visibility][5] integrates with other developer-oriented Datadog products as well as external partners such as GitHub to streamline developer workflows with features including being able to: +[Test Visibility][5] integrates with other developer-oriented Datadog products as well as external partners such as GitHub to streamline developer workflows with features including being able to: - [Create and open GitHub issues](#create-and-open-github-issues) - [Open tests in GitHub and your IDE](#open-tests-in-github-and-your-ide) diff --git a/content/en/tests/guides/_index.md b/content/en/tests/guides/_index.md new file mode 100644 index 0000000000000..16726d79bddc5 --- /dev/null +++ b/content/en/tests/guides/_index.md @@ -0,0 +1,16 @@ +--- +title: Test Visibility Guides +kind: guide +private: true +disable_toc: true +cascade: + algolia: + rank: 20 + category: Guide + subcategory: Test Visibility Guides +--- + +{{< whatsnext desc="Test Visibility Guides:" >}} + {{< nextlink href="/tests/guides/flaky_test_management" >}}Flaky Test Management{{< /nextlink >}} + {{< nextlink href="/tests/guides/add_custom_metrics" >}}Add Custom Metrics to Your Tests{{< /nextlink >}} +{{< /whatsnext >}} diff --git a/content/en/continuous_integration/guides/add_custom_metrics.md b/content/en/tests/guides/add_custom_metrics.md similarity index 98% rename from content/en/continuous_integration/guides/add_custom_metrics.md rename to content/en/tests/guides/add_custom_metrics.md index 49af329c3dd4f..7766bd1e28347 100644 --- a/content/en/continuous_integration/guides/add_custom_metrics.md +++ b/content/en/tests/guides/add_custom_metrics.md @@ -2,6 +2,8 @@ title: Add Custom Metrics To Your Tests kind: guide description: Learn how to use custom metrics (measures) in your tests. +aliases: +- /continuous_integration/guides/add_custom_metrics/ further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/guides/flaky_test_management.md b/content/en/tests/guides/flaky_test_management.md similarity index 98% rename from content/en/continuous_integration/guides/flaky_test_management.md rename to content/en/tests/guides/flaky_test_management.md index d4e7bb9514718..9af73ecc4c4a2 100644 --- a/content/en/continuous_integration/guides/flaky_test_management.md +++ b/content/en/tests/guides/flaky_test_management.md @@ -3,6 +3,7 @@ title: Flaky Test Management kind: guide aliases: - /continuous_integration/guides/find_flaky_tests/ +- /continuous_integration/guides/flaky_test_management/ further_reading: - link: "/continuous_integration/tests/" tag: "Documentation" diff --git a/content/en/tests/search/_index.md b/content/en/tests/search/_index.md new file mode 100644 index 0000000000000..0714e8fba887e --- /dev/null +++ b/content/en/tests/search/_index.md @@ -0,0 +1,93 @@ +--- +title: Search and Manage CI Tests +description: Learn how to search for your CI tests. +algolia: + rank: 70 + tags: ['flaky test', 'flaky tests', 'test regression', 'test regressions', 'test service', 'test services'] +further_reading: +- link: "/continuous_integration/explorer" + tag: "Documentation" + text: "Search and filter test runs" +- link: "/continuous_integration/guides/flaky_test_management" + tag: "Documentation" + text: "Learn how to manage flaky tests" +--- + +{{< site-region region="gov" >}} +
CI Visibility is not available in the selected site ({{< region-param key="dd_site_name" >}}) at this time.
+{{< /site-region >}} + +## Overview + +The [Tests page][1] is useful for developers who want to keep an eye on their test results. + +{{< img src="/continuous_integration/tests.png" text="CI Tests page" style="width:100%" >}} + +You can access low-level and immediate insights: + +- See what tests are failing and why. +- See your last commit's test results. +- View the wall time of your tests in your feature branch and compare it to the default branch, to identify if you're about to introduce a performance regression. +- Find out if your commit introduces a new [flaky test][5] that wasn't flaky before, indicating that your code change is what's making it flaky. This gives you the opportunity to fix the problem before proceeding rather than contributing to the number of flaky tests in your CI. + +You can also access high-level accumulation and trends: + +- See the effects that changed code, added tests, and increased complexity have on your test suite performance over time. +- See which tests have become slower over time and identify the commit that introduced the regression. +- Take advantage of Datadog's automatic test flakiness detection and tracking, which shows you which tests are becoming more or less unreliable over time. + +## Search for tests + +To see your tests, navigate to [**CI** > **Tests**][1] and select between the [**Branches**](#branches-view) or [**Default Branches** view](#default-branches-view). + +### Branches view + +The [Branches][2] view of the Tests page lists all branches from all [test services][3] that have reported test results. This tab is useful for individual developers to quickly see the status of tests that run on their code branches and troubleshoot test failures. + +In this page, you can filter the list by name, test service, or commit SHA, or to show only your branches (branches that contain at least one commit authored by you), enable the **My branches** toggle and add the email addresses you use in your Git configuration. + +#### Test results + +For each branch, you can see the test service, the number of failed, passed, and skipped tests, test regressions, wall time, the percentage of change compared to the default branch, when the commit was last updated, and the avatar of the author of the commit. + +Click on a branch to explore the test details page, which includes information about the branch's latest commits, flaky tests, test performance, common error types, and all test runs. + +{{< img src="continuous_integration/test_details.png" alt="Test Details page for a single branch" style="width:100%;">}} + +#### Test suite performance + +There is also information about the [wall time][4] of the most recent test suite run, and a comparison to the average wall time of the default branch. The comparison of your branch's wall time to the default branch's wall time can help you determine if your commit is introducing performance [regressions][6] to your test suite. + +Hovering over the commit author avatar shows detailed information about the latest commit. + +#### Test regressions + +[Test regressions][6] are evaluated per commit in an effort to tie performance regressions to specific code changes. + +#### Investigate for more details + +Click on the row to see test suite run details such as test results for the last commit on this branch (or you can switch branches), failing tests and the most common errors, slow tests, flaky tests, and a complete list of test runs over the time frame selected. You can filter this list of test runs by facet to get to the information you want to see most. + +Click into one of the test runs to see the test trace as a flame graph or a span list. The _Runs (n)_ list on the left lets you quickly access traces for each retry of the test for the same commit. + +#### Explore connections to services, resources, logs, and network events + +Click the CI provider link to examine the Resource, Service, or Analytics page for the test. You can also find complete tags information and links to related log events and network monitoring events. + +### Default Branches view + +The [Default Branches][7] view of the Tests page shows aggregated health metrics for the _default_ branch of each test service. This view is useful for teams to understand the overall health of the service over time. + +The Default Branches view shows similar information to the Branches view, but applied to the default branch. It compares the current wall time with the average default branch wall time to give you an indication of how your test suite performance is trending over time. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://app.datadoghq.com/ci/test-services +[2]: https://app.datadoghq.com/ci/test-services?view=branches +[3]: /glossary/#test-service +[4]: /glossary/#wall-time +[5]: /glossary/#flaky-test +[6]: /glossary/#test-regression +[7]: https://app.datadoghq.com/ci/test-services?view=default-branches \ No newline at end of file diff --git a/content/en/continuous_integration/tests/setup/_index.md b/content/en/tests/setup/_index.md similarity index 85% rename from content/en/continuous_integration/tests/setup/_index.md rename to content/en/tests/setup/_index.md index 68e70780a043c..8277d84b53b01 100644 --- a/content/en/continuous_integration/tests/setup/_index.md +++ b/content/en/tests/setup/_index.md @@ -2,6 +2,8 @@ title: Configure Test Visibility kind: documentation type: multi-code-lang +aliases: +- continuous_integration/tests/setup/ --- For information about configuration options for [Test Visibility][1], choose your language: diff --git a/content/en/continuous_integration/tests/setup/dotnet.md b/content/en/tests/setup/dotnet.md similarity index 99% rename from content/en/continuous_integration/tests/setup/dotnet.md rename to content/en/tests/setup/dotnet.md index a436c17eca070..6e0e0be6bcaa2 100644 --- a/content/en/continuous_integration/tests/setup/dotnet.md +++ b/content/en/tests/setup/dotnet.md @@ -7,6 +7,7 @@ code_lang_weight: 0 aliases: - /continuous_integration/setup_tests/dotnet - /continuous_integration/tests/dotnet + - continuous_integration/tests/setup/dotnet further_reading: - link: "/continuous_integration/tests/containers/" tag: "Documentation" diff --git a/content/en/continuous_integration/tests/setup/java.md b/content/en/tests/setup/java.md similarity index 99% rename from content/en/continuous_integration/tests/setup/java.md rename to content/en/tests/setup/java.md index 5e681773bc9ea..a19206c03cb53 100644 --- a/content/en/continuous_integration/tests/setup/java.md +++ b/content/en/tests/setup/java.md @@ -7,6 +7,7 @@ code_lang_weight: 10 aliases: - /continuous_integration/setup_tests/java - /continuous_integration/tests/java + - continuous_integration/tests/setup/java further_reading: - link: "/continuous_integration/tests/containers/" tag: "Documentation" diff --git a/content/en/continuous_integration/tests/setup/javascript.md b/content/en/tests/setup/javascript.md similarity index 99% rename from content/en/continuous_integration/tests/setup/javascript.md rename to content/en/tests/setup/javascript.md index 9a1908e583bf7..4d9dd0b31ed08 100644 --- a/content/en/continuous_integration/tests/setup/javascript.md +++ b/content/en/tests/setup/javascript.md @@ -7,6 +7,7 @@ code_lang_weight: 20 aliases: - /continuous_integration/setup_tests/javascript - /continuous_integration/tests/javascript + - continuous_integration/tests/setup/javascript further_reading: - link: "/continuous_integration/tests/containers/" tag: "Documentation" diff --git a/content/en/continuous_integration/tests/setup/junit_xml.md b/content/en/tests/setup/junit_xml.md similarity index 99% rename from content/en/continuous_integration/tests/setup/junit_xml.md rename to content/en/tests/setup/junit_xml.md index 3260ae8082bfc..ca4521272e8c4 100644 --- a/content/en/continuous_integration/tests/setup/junit_xml.md +++ b/content/en/tests/setup/junit_xml.md @@ -7,6 +7,7 @@ code_lang_weight: 60 aliases: - /continuous_integration/setup_tests/junit_upload - /continuous_integration/tests/junit_upload + - continuous_integration/tests/setup/junit_xml further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/tests/setup/python.md b/content/en/tests/setup/python.md similarity index 99% rename from content/en/continuous_integration/tests/setup/python.md rename to content/en/tests/setup/python.md index 52e95596e4789..b74d4fd2f6038 100644 --- a/content/en/continuous_integration/tests/setup/python.md +++ b/content/en/tests/setup/python.md @@ -7,6 +7,7 @@ code_lang_weight: 30 aliases: - /continuous_integration/setup_tests/python - /continuous_integration/tests/python + - continuous_integration/tests/setup/python further_reading: - link: "/continuous_integration/tests/containers/" tag: "Documentation" diff --git a/content/en/continuous_integration/tests/setup/ruby.md b/content/en/tests/setup/ruby.md similarity index 99% rename from content/en/continuous_integration/tests/setup/ruby.md rename to content/en/tests/setup/ruby.md index 67efd96ef7da2..8fe5f6dc18f62 100644 --- a/content/en/continuous_integration/tests/setup/ruby.md +++ b/content/en/tests/setup/ruby.md @@ -7,6 +7,7 @@ code_lang_weight: 40 aliases: - /continuous_integration/setup_tests/ruby - /continuous_integration/tests/ruby + - continuous_integration/tests/setup/ruby further_reading: - link: "/continuous_integration/tests/containers/" tag: "Documentation" diff --git a/content/en/continuous_integration/tests/setup/swift.md b/content/en/tests/setup/swift.md similarity index 99% rename from content/en/continuous_integration/tests/setup/swift.md rename to content/en/tests/setup/swift.md index 26cb10e92ff54..32cdca6920c29 100644 --- a/content/en/continuous_integration/tests/setup/swift.md +++ b/content/en/tests/setup/swift.md @@ -7,6 +7,7 @@ code_lang_weight: 50 aliases: - /continuous_integration/setup_tests/swift - /continuous_integration/tests/swift + - continuous_integration/tests/setup/swift further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/continuous_integration/tests/swift_tests.md b/content/en/tests/swift_tests.md similarity index 97% rename from content/en/continuous_integration/tests/swift_tests.md rename to content/en/tests/swift_tests.md index 557719c591aca..8a8cfe5b386d5 100644 --- a/content/en/continuous_integration/tests/swift_tests.md +++ b/content/en/tests/swift_tests.md @@ -5,6 +5,7 @@ description: Learn how to use CI Visibility and RUM to connect your Swift test r aliases: - /continuous_integration/guides/rum_swift_integration - /continuous_integration/integrate_tests/swift_tests +- continuous_integration/tests/swift_tests further_reading: - link: "/continuous_integration/tests" tag: "Documentation" diff --git a/content/en/tests/troubleshooting/_index.md b/content/en/tests/troubleshooting/_index.md new file mode 100644 index 0000000000000..1141ded83ab5e --- /dev/null +++ b/content/en/tests/troubleshooting/_index.md @@ -0,0 +1,175 @@ +--- +title: Test Visibility Troubleshooting +kind: documentation +further_reading: + - link: "/continuous_integration/tests" + tag: "Documentation" + text: "Learn how to monitor your CI tests" +--- + +{{< site-region region="gov" >}} +
CI Visibility is not available in the selected site ({{< region-param key="dd_site_name" >}}) at this time.
+{{< /site-region >}} + +## Overview + +This page provides information to help you troubleshot issues with Test Visibility. If you need additional help, contact [Datadog Support][2]. + +## Your tests are instrumented, but Datadog isn't showing any data + +1. Go to the [**Tests**][3] page for the language you're instrumenting and check that the testing framework you are using is supported in the **Compatibility** section. +2. Check if you see any test results in the [**Test Runs**][4] section. If you do see results there, but not in the [**Tests**][5] section, Git information is missing. See [Data appears in Test Runs but not Tests](#data-appears-in-test-runs-but-not-tests) to troubleshoot it. +3. If you are reporting the data through the Datadog Agent, make sure it is running on the host where tests are run (accessible at `localhost:8126`), or if accessible on another hostname or port, make sure you run your tests with the appropriate Agent hostname set in the `DD_AGENT_HOST` and the appropriate port in `DD_TRACE_AGENT_PORT` environment variables. You can activate [debug mode][6] in the tracer to check if it's able to connect to the Agent. +4. If you still don't see any results, [contact Support][2] for troubleshooting help. + +## You are uploading JUnit test reports with `datadog-ci` but some or all tests are missing +If you are uploading JUnit test report files with `datadog-ci` CLI and you do not see the tests, it is likely the tests are being discarded because the report is considered incorrect. + +The following aspects make a JUnit test report incorrect: +* A timestamp of the reported tests that is older than **71 hours** before the moment the report is uploaded. +* A testsuite without a name. + +## Data appears in test runs but not tests + +If you can see test results data in the **Test Runs** tab, but not the **Tests** tab, Git metadata (repository, commit, or branch) is probably missing. To confirm this is the case, open a test execution in the [**Test Runs**][4] section, and check that there is no `git.repository_url`, `git.commit.sha`, or `git.branch`. If these tags are not populated, nothing shows in the [**Tests**][5] section. + +1. Tracers first use the environment variables, if any, set by the CI provider to collect Git information. See [Running tests inside a container][7] for a list of environment variables that the tracer attempts to read for each supported CI provider. At a minimum, this populates the repository, commit hash, and branch information. +2. Next, tracers fetch Git metadata using the local `.git` folder, if present, by executing `git` commands. This populates all Git metadata fields, including commit message, author, and committer information. Ensure the `.git` folder is present and the `git` binary is installed and in `$PATH`. This information is used to populate attributes not detected in the previous step. +3. You can also provide Git information manually using environment variables, which override information detected by any of the previous steps. + + The supported environment variables for providing Git information are: + + `DD_GIT_REPOSITORY_URL` **(required)** + : URL of the repository where the code is stored. Both HTTP and SSH URLs are supported.
+ **Example**: `git@github.com:MyCompany/MyApp.git`, `https://github.com/MyCompany/MyApp.git` + + `DD_GIT_COMMIT_SHA` **(required)** + : Full (40-character long SHA1) commit hash.
+ **Example**: `a18ebf361cc831f5535e58ec4fae04ffd98d8152` + + `DD_GIT_BRANCH` + : Git branch being tested. Leave empty if providing tag information instead.
+ **Example**: `develop` + + `DD_GIT_TAG` + : Git tag being tested (if applicable). Leave empty if providing branch information instead.
+ **Example**: `1.0.1` + + `DD_GIT_COMMIT_MESSAGE` + : Commit message.
+ **Example**: `Set release number` + + `DD_GIT_COMMIT_AUTHOR_NAME` + : Commit author name.
+ **Example**: `John Smith` + + `DD_GIT_COMMIT_AUTHOR_EMAIL` + : Commit author email.
+ **Example**: `john@example.com` + + `DD_GIT_COMMIT_AUTHOR_DATE` + : Commit author date in ISO 8601 format.
+ **Example**: `2021-03-12T16:00:28Z` + + `DD_GIT_COMMIT_COMMITTER_NAME` + : Commit committer name.
+ **Example**: `Jane Smith` + + `DD_GIT_COMMIT_COMMITTER_EMAIL` + : Commit committer email.
+ **Example**: `jane@example.com` + + `DD_GIT_COMMIT_COMMITTER_DATE` + : Commit committer date in ISO 8601 format.
+ **Example**: `2021-03-12T16:00:28Z` + +4. If no CI provider environment variables are found, tests results are sent with no Git metadata. + +## The tests wall time is empty + +If you cannot see the tests wall time it is likely that the CI provider metadata is missing. To confirm this is the case, open a test execution in the [**Test Runs**][4] section, and check if the `ci.pipeline.id`, `ci.pipeline.name`, `ci.pipeline.number`, or `ci.job.url` tags are missing. If these tags are not populated, then nothing shows in the wall time column. + +1. Tracers use the environment variables set by the CI provider to collect this information. See [Running tests inside a container][7] for a list of environment variables that the tracer attempts to read for each supported CI provider. Make sure that the environment variables have the expected values set. +2. Check that you are running your tests in a supported CI provider. For a list of supported CI providers, see [Running tests inside a container][7]. Only these CI providers can extract the information to enrich the test metadata with CI information. +3. If you still don't see the wall time, contact [Datadog support][2] for help. + +## The tests wall time is not what is expected + +### How wall time is calculated +The wall time is defined as the time difference between the start time of the first test and the end time of the last test for the given pipeline. + +This is done using the following algorithm: + +1. Compute a hash based on CI information to group the tests. + 1. If the tests include `ci.job.url`, use this tag to calculate the hash. + 2. If the tests don't include `ci.job.url`, use `ci.pipeline.id` + `ci.pipeline.name` + `ci.pipeline.number` to calculate the hash. +2. The calculated wall time is associated to a given hash. **Note**: If there are multiple jobs that execute tests, the wall time is calculated for each job, and the maximum from all calculated wall times is shown. + +### Possible issues with wall time calculation +If you're using a library for testing time-dependent code, like [timecop][8] for Ruby or [FreezeGun][9] for Python, it is possible that test timestamps are wrong, and therefore calculated wall times. If this is the case, make sure that modifications to time are rolled back before finishing your tests. + +## The test status numbers are not what is expected + +The test status numbers are calculated based on the unique tests that were collected. The uniqueness of a test is defined not only by its suite and name, but by its test parameters and test configurations as well. + +### The numbers are lower than expected + +If the numbers are lower than expected, it is likely that either the library or the tool you are using to collect test data cannot collect test parameters and/or some test configurations. + +1. If you are uploading JUnit test report files: + 1. If you are running the same tests in different environment configurations, [make sure you are setting those configuration tags during the upload][10]. + 2. If you are running parameterized tests, it's very likely that the JUnit report does not have that information. [Try using a native library to report test data][3]. +2. If you still don't see the expected results, [contact Datadog support][2] for troubleshooting help. + +### The passed/failed/skipped numbers are different than expected + +If the same test is collected several times for the same commit but with different status, the aggregated result follows the algorithm in the table below: + +| **Test Status - First Try** | **Test Status - Retry #1** | **Result** | +|-----------------------------|----------------------------|------------| +| `Passed` | `Passed` | `Passed` | +| `Passed` | `Failed` | `Passed` | +| `Passed` | `Skipped` | `Passed` | +| `Failed` | `Passed` | `Passed` | +| `Failed` | `Failed` | `Failed` | +| `Failed` | `Skipped` | `Failed` | +| `Skipped` | `Passed` | `Passed` | +| `Skipped` | `Failed` | `Failed` | +| `Skipped` | `Skipped` | `Skipped` | + +## The default branch is not correct + +### How it impacts the product + +The default branch is used to power some features of the products, namely: + +- Default branches list on the Tests page: This list only displays default branches. Setting the wrong default branch can result in missing or incorrect data in the default branches list. + +- Wall time comparison for non-default branches: On the Tests page, in the Branches view, the **VS Default** column is calculated by comparing wall time for the current branch against wall time for the default branch. + +- New flaky tests: Tests that are not currently classified as flaky in the default branch. If the default branch is not properly set, this could lead to a wrong number of detected new flaky tests. + +- Pipelines list: The pipelines list only displays default branches. Setting the wrong default branch can result in missing or incorrect data in the pipelines list. + +### How to fix the default branch + +If you have admin access, you can update it from the [Repository Settings Page][11]. + + + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://www.jenkins.io/doc/book/system-administration/viewing-logs/ +[2]: /help/ +[3]: /continuous_integration/tests/ +[4]: https://app.datadoghq.com/ci/test-runs +[5]: https://app.datadoghq.com/ci/test-services +[6]: /tracing/troubleshooting/tracer_debug_logs +[7]: /continuous_integration/tests/containers/ +[8]: https://github.com/travisjeffery/timecop +[9]: https://github.com/spulec/freezegun +[10]: /continuous_integration/tests/junit_upload/?tabs=linux#collecting-environment-configuration-metadata +[11]: https://app.datadoghq.com/ci/settings/repository +[12]: /continuous_integration/intelligent_test_runner/ \ No newline at end of file From 9fd338c9e55ad6af6348bac5424a9606b3816f32 Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 14 Dec 2023 10:20:20 -0800 Subject: [PATCH 11/12] DOCS-6873 Static Analysis URL Update (#20913) * Update CODEOWNERS + Doc Links * Link Fix --- .github/CODEOWNERS | 7 +++++-- content/en/developers/ide_integrations/idea/_index.md | 8 ++++---- content/en/dora_metrics/_index.md | 2 +- content/en/static_analysis/_index.md | 6 +++--- content/en/static_analysis/rules/_index.md | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6658b8560c8a4..ed89df04060db 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -99,8 +99,11 @@ content/en/synthetics/*.md @Datadog/synthet content/en/continuous_testing/*.md @Datadog/synthetics-ct @Datadog/documentation content/en/mobile_app_testing/*.md @Datadog/synthetics-mobile @Datadog/documentation -# CI Visibility +# Software Delivery content/en/continuous_integration/tests/*.md @Datadog/ci-app-libraries @Datadog/documentation content/en/continuous_integration/pipelines/*.md @Datadog/ci-app-backend @Datadog/documentation -content/en/continuous_integration/static_analysis/rules/_index.md @Datadog/static-analysis @Datadog/documentation +content/en/static_analysis/*.md @Datadog/static-analysis @Datadog/documentation +content/en/static_analysis/rules/_index.md @Datadog/static-analysis @Datadog/documentation +content/en/quality_gates/_index.md @Datadog/ci-app-backend @Datadog/documentation +content/en/dora_metrics/_index.md @Datadog/ci-app-backend @Datadog/documentation \ No newline at end of file diff --git a/content/en/developers/ide_integrations/idea/_index.md b/content/en/developers/ide_integrations/idea/_index.md index 5b7adc9cbf49f..65789fd2b9e94 100644 --- a/content/en/developers/ide_integrations/idea/_index.md +++ b/content/en/developers/ide_integrations/idea/_index.md @@ -10,7 +10,7 @@ further_reading: - link: "/integrations/guide/source-code-integration/" tag: "Documentation" text: "Learn about Source Code Integration." -- link: "/continuous_integration/static_analysis/?tab=githubactions" +- link: "/static_analysis/?tab=githubactions" tag: "Documentation" text: "Learn about Static Analysis." - link: "https://www.jetbrains.com/lp/toolbox/" @@ -223,6 +223,6 @@ You can give feedback in the [discussion forum][1], or send an e-mail to [team-i [10]: /watchdog/insights [11]: mailto:team-ide-integration@datadoghq.com [12]: /continuous_integration/explorer/?tab=testruns -[13]: /continuous_integration/static_analysis/?tab=githubactions -[14]: /continuous_integration/static_analysis/rules/#python-rules -[15]: /continuous_integration/static_analysis/rules/#docker-rules +[13]: /static_analysis/?tab=githubactions +[14]: /static_analysis/rules/#python-rules +[15]: /static_analysis/rules/#docker-rules diff --git a/content/en/dora_metrics/_index.md b/content/en/dora_metrics/_index.md index 739e7ca275289..8d4db4b31acd8 100644 --- a/content/en/dora_metrics/_index.md +++ b/content/en/dora_metrics/_index.md @@ -12,7 +12,7 @@ further_reading: - link: "/continuous_integration/pipelines" tag: "Documentation" text: "Learn about Pipeline Visibility" -- link: "/continuous_integration/static_analysis" +- link: "/static_analysis" tag: "Documentation" text: "Learn about Static Analysis" - link: "/tracing/service_catalog" diff --git a/content/en/static_analysis/_index.md b/content/en/static_analysis/_index.md index f5f71e7dbf45e..ccb1b7e3cc063 100644 --- a/content/en/static_analysis/_index.md +++ b/content/en/static_analysis/_index.md @@ -76,14 +76,14 @@ Configure your [Datadog API and application keys][4] and run Static Analysis in To run Static Analysis with CircleCI, [follow these instructions for setting up a CircleCI Orb][101]. -[101]: /continuous_integration/static_analysis/circleci_orbs +[101]: /static_analysis/circleci_orbs {{% /tab %}} {{% tab "GitHub Actions" %}} To run Static Analysis with GitHub, [follow these instructions for setting up a GitHub Action][101]. -[101]: /continuous_integration/static_analysis/github_actions/ +[101]: /static_analysis/github_actions/ {{% /tab %}} {{% tab "Other" %}} @@ -235,5 +235,5 @@ bar = 2 [3]: /integrations/github/ [4]: /account_management/api-app-keys/ [5]: https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif -[6]: /continuous_integration/static_analysis/rules +[6]: /static_analysis/rules [103]: /getting_started/site/ diff --git a/content/en/static_analysis/rules/_index.md b/content/en/static_analysis/rules/_index.md index 541d8cb33e215..28a9254cd350c 100644 --- a/content/en/static_analysis/rules/_index.md +++ b/content/en/static_analysis/rules/_index.md @@ -1520,4 +1520,4 @@ Rules to identify potential security hotspots in Node. This may include false po {{< partial name="whats-next/whats-next.html" >}} -[1]: /continuous_integration/static_analysis +[1]: /static_analysis From c580efe121eb239d3b90d3d1f4d3cfe75307a52d Mon Sep 17 00:00:00 2001 From: Austin Lai <76412946+alai97@users.noreply.github.com> Date: Thu, 14 Dec 2023 10:21:06 -0800 Subject: [PATCH 12/12] Ready to Merge --- local/bin/py/build/configurations/pull_config_preview.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local/bin/py/build/configurations/pull_config_preview.yaml b/local/bin/py/build/configurations/pull_config_preview.yaml index 90d444307c516..ade397a4fbe1f 100644 --- a/local/bin/py/build/configurations/pull_config_preview.yaml +++ b/local/bin/py/build/configurations/pull_config_preview.yaml @@ -1,6 +1,6 @@ --- - config: - cache_enabled: false + cache_enabled: true - data: - org_name: jenkinsci