From 881d5b03cf3625a32866be9a0f61ed45b02e4679 Mon Sep 17 00:00:00 2001 From: Srijan Saurav <68371686+srijan-deepsource@users.noreply.github.com> Date: Mon, 6 Nov 2023 17:02:01 +0530 Subject: [PATCH 1/6] chore: add an end to end parsing test (#10) Changes: - Add end to end parsing test - Fix assets being copied in the Dockerfile - Explicitly log the info passed to sentry.raise_info - Add instruction about adding fixture for parsing test in readme - Change workdir - fix dependencies installation in the image --- .deepsource.toml | 1 + .gitignore | 3 + Dockerfile | 7 +- README.md | 12 +- sarif-parser/src/sarif_parser/__init__.py | 18 +- sarif-parser/tests/cli_test.py | 23 +- sentry.py | 12 + tests/fixtures/reports/kube-linter.sarif | 1011 +++++++++++++++++++++ tests/test_report_parsing.py | 52 ++ tox.ini | 2 +- 10 files changed, 1127 insertions(+), 14 deletions(-) create mode 100644 tests/fixtures/reports/kube-linter.sarif create mode 100644 tests/test_report_parsing.py diff --git a/.deepsource.toml b/.deepsource.toml index 3e3816c5..d6380be4 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -7,6 +7,7 @@ name = "python" [analyzers.meta] runtime_version = "3.x.x" + max_line_length = 100 type_checker = "mypy" [[analyzers]] diff --git a/.gitignore b/.gitignore index e121797a..27fb9029 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ venv* **/*.egg-info **/build **/dist +coverage.xml +.env +**/.DS_Store diff --git a/Dockerfile b/Dockerfile index b3fedf8e..45de8a5c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,8 +7,11 @@ RUN mkdir -p /home/runner /app /artifacts /toolbox \ RUN apk add --no-cache git grep -COPY ./sarif-parser /toolbox/sarif-parser +COPY . /toolbox/ +# Change working dir to toolbox since we'd be invoking community analyzer from there. +WORKDIR /toolbox -RUN pip install --no-cache-dir /toolbox/sarif-parser +# Install parser and the required dependencies +RUN pip install --no-cache-dir -r requirements.txt USER runner diff --git a/README.md b/README.md index 15c841a1..839a756f 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ The following are very important to sync analyzers with DeepSource: c. `logo.svg` file. - 2. `.deepsource/issues` directory. This contains all issues detected by the analyzer. Each issue's filemane should be `.toml` or `` with the following fields: - `title`: Title of the issue. No periods are allowed in the title. @@ -44,13 +43,16 @@ The following are very important to sync analyzers with DeepSource: 3. `CI` directory: -Put example configs of all CIs under this directory. These worlflow / CI configs should run the analyzer, create a sarif report and send it to DeepSource. -Each file should be names as `.`. Example: `github.yml`, `circleci.yml`, etc.` + Put example configs of all CIs under this directory. These worlflow / CI configs should run the analyzer, create a sarif report and send it to DeepSource. + Each file should be names as `.`. Example: `github.yml`, `circleci.yml`, etc.` 4. `utils` directory: -It should contain all the utilities required for the analyzer like issue genrator, issue-map, etc. -For example, please check out `analyzers/kube-linter/utils`. + It should contain all the utilities required for the analyzer like issue genrator, issue-map, etc. + For example, please check out `analyzers/kube-linter/utils`. + +5. Add a sample sarif report from the analyzer in `tests/fixtures` directory. The file should be named as `.sarif`. +`test_report_parsing` parses all sarif reports under the given directory and checks if the issues are parsed correctly. It is important for that particular test to pass. ### Syncing analyzers and their issues with DeepSource diff --git a/sarif-parser/src/sarif_parser/__init__.py b/sarif-parser/src/sarif_parser/__init__.py index a55b3670..749e0ef5 100644 --- a/sarif-parser/src/sarif_parser/__init__.py +++ b/sarif-parser/src/sarif_parser/__init__.py @@ -5,6 +5,8 @@ import os.path from typing import Any, TypedDict +import sentry + class Issue(TypedDict): issue_code: str @@ -104,11 +106,17 @@ def run_sarif_parser( artifacts = [filepath] # Prepare mapping from SARIF rule IDs to DeepSource issue codes - if issue_map_path is not None: - with open(issue_map_path) as file: - issue_map = json.load(file) - else: - issue_map = None + issue_map = None + if issue_map_path: + try: + with open(issue_map_path) as file: + issue_map = json.load(file) + except FileNotFoundError: + # It is not mandatory for an analyzer to have an issue map. + # But, log this as an info. + sentry.raise_info( + f"Could not find issue map at {issue_map_path} for analyzer." + ) # Run parser deepsource_issues = [] diff --git a/sarif-parser/tests/cli_test.py b/sarif-parser/tests/cli_test.py index dd926af0..265290d6 100644 --- a/sarif-parser/tests/cli_test.py +++ b/sarif-parser/tests/cli_test.py @@ -188,7 +188,28 @@ def test_cli_with_issue_map( assert out == expected_output +def test_cli_with_invalid_issue_map_path( + artifact_path: str, + capfd: pytest.CaptureFixture[str], +) -> None: + """Tests `sarif-parser` CLI, with an invalid issue_map path""" + cli([artifact_path, "--issue-map-path=some/invalid/path", "--output=/dev/stdout"]) + out, err = capfd.readouterr() + assert err == "" + + expected_output = json.dumps( + { + "issues": expected_issues, # without issues map since we have passed an invalid path + "metrics": [], + "errors": [], + "is_passed": False, + "extra_data": {}, + } + ) + assert out == expected_output + + def test_cli_file_not_found() -> None: """Tests `sarif-parser` CLI, with issue code substitution.""" with pytest.raises(FileNotFoundError): - cli(["/tmp/doesnotexist.py"]) + cli(["/some/doesnotexist.py"]) diff --git a/sentry.py b/sentry.py index d4493dfc..b3c8f46d 100644 --- a/sentry.py +++ b/sentry.py @@ -1,8 +1,17 @@ +import logging import os import sentry_sdk import sentry_sdk.utils +logger = logging.getLogger("community_analyzer") +# Configure the logging format to also include file, linenum. +logging.basicConfig( + format="%(asctime)s,%(msecs)03d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s", + datefmt="%Y-%m-%d:%H:%M:%S", + level=logging.DEBUG, +) + def initialize() -> None: """Initialize sentry.""" @@ -32,3 +41,6 @@ def raise_info(message: str, context: dict[str, object] | None = None) -> None: scope.set_extra(context_name, context_value) # Capture the message sentry_sdk.capture_message(message) + + # Add a log for this + logger.info(message, extra=context) diff --git a/tests/fixtures/reports/kube-linter.sarif b/tests/fixtures/reports/kube-linter.sarif new file mode 100644 index 00000000..68527fd3 --- /dev/null +++ b/tests/fixtures/reports/kube-linter.sarif @@ -0,0 +1,1011 @@ +{ + "version": "2.1.0", + "$schema": "https://json.schemastore.org/sarif-2.1.0-rtm.5.json", + "runs": [ + { + "tool": { + "driver": { + "informationUri": "https://github.com/stackrox/kube-linter", + "name": "kube-linter", + "rules": [ + { + "id": "dangling-service", + "shortDescription": { + "text": "Indicates when services do not have any associated deployments." + }, + "fullDescription": { + "text": "Confirm that your service's selector correctly matches the labels on one of your deployments." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=dangling-services", + "help": { + "text": "Check: dangling-service\nDescription: Indicates when services do not have any associated deployments.\nRemediation: Confirm that your service's selector correctly matches the labels on one of your deployments.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=dangling-services" + } + }, + { + "id": "deprecated-service-account-field", + "shortDescription": { + "text": "Indicates when deployments use the deprecated serviceAccount field." + }, + "fullDescription": { + "text": "Use the serviceAccountName field instead. If you must specify serviceAccount, ensure values for serviceAccount and serviceAccountName match." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=deprecated-service-account-field", + "help": { + "text": "Check: deprecated-service-account-field\nDescription: Indicates when deployments use the deprecated serviceAccount field.\nRemediation: Use the serviceAccountName field instead. If you must specify serviceAccount, ensure values for serviceAccount and serviceAccountName match.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=deprecated-service-account-field" + } + }, + { + "id": "docker-sock", + "shortDescription": { + "text": "Alert on deployments with docker.sock mounted in containers. " + }, + "fullDescription": { + "text": "Ensure the Docker socket is not mounted inside any containers by removing the associated Volume and VolumeMount in deployment yaml specification. If the Docker socket is mounted inside a container it could allow processes running within the container to execute Docker commands which would effectively allow for full control of the host." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=host-mounts", + "help": { + "text": "Check: docker-sock\nDescription: Alert on deployments with docker.sock mounted in containers. \nRemediation: Ensure the Docker socket is not mounted inside any containers by removing the associated Volume and VolumeMount in deployment yaml specification. If the Docker socket is mounted inside a container it could allow processes running within the container to execute Docker commands which would effectively allow for full control of the host.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=host-mounts" + } + }, + { + "id": "drop-net-raw-capability", + "shortDescription": { + "text": "Indicates when containers do not drop NET_RAW capability" + }, + "fullDescription": { + "text": "NET_RAW makes it so that an application within the container is able to craft raw packets, use raw sockets, and bind to any address. Remove this capability in the containers under containers security contexts." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=verify-container-capabilities", + "help": { + "text": "Check: drop-net-raw-capability\nDescription: Indicates when containers do not drop NET_RAW capability\nRemediation: NET_RAW makes it so that an application within the container is able to craft raw packets, use raw sockets, and bind to any address. Remove this capability in the containers under containers security contexts.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=verify-container-capabilities" + } + }, + { + "id": "duplicate-env-var", + "shortDescription": { + "text": "Check that duplicate named env vars aren't passed to a deployment like." + }, + "fullDescription": { + "text": "Confirm that your DeploymentLike doesn't have duplicate env vars names." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=duplicate-environment-variables", + "help": { + "text": "Check: duplicate-env-var\nDescription: Check that duplicate named env vars aren't passed to a deployment like.\nRemediation: Confirm that your DeploymentLike doesn't have duplicate env vars names.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=duplicate-environment-variables" + } + }, + { + "id": "env-var-secret", + "shortDescription": { + "text": "Indicates when objects use a secret in an environment variable." + }, + "fullDescription": { + "text": "Do not use raw secrets in environment variables. Instead, either mount the secret as a file or use a secretKeyRef. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets for details." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=environment-variables", + "help": { + "text": "Check: env-var-secret\nDescription: Indicates when objects use a secret in an environment variable.\nRemediation: Do not use raw secrets in environment variables. Instead, either mount the secret as a file or use a secretKeyRef. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets for details.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=environment-variables" + } + }, + { + "id": "host-ipc", + "shortDescription": { + "text": "Alert on pods/deployment-likes with sharing host's IPC namespace" + }, + "fullDescription": { + "text": "Ensure the host's IPC namespace is not shared." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=host-ipc", + "help": { + "text": "Check: host-ipc\nDescription: Alert on pods/deployment-likes with sharing host's IPC namespace\nRemediation: Ensure the host's IPC namespace is not shared.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=host-ipc" + } + }, + { + "id": "host-network", + "shortDescription": { + "text": "Alert on pods/deployment-likes with sharing host's network namespace" + }, + "fullDescription": { + "text": "Ensure the host's network namespace is not shared." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=host-network", + "help": { + "text": "Check: host-network\nDescription: Alert on pods/deployment-likes with sharing host's network namespace\nRemediation: Ensure the host's network namespace is not shared.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=host-network" + } + }, + { + "id": "host-pid", + "shortDescription": { + "text": "Alert on pods/deployment-likes with sharing host's process namespace" + }, + "fullDescription": { + "text": "Ensure the host's process namespace is not shared." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=host-pid", + "help": { + "text": "Check: host-pid\nDescription: Alert on pods/deployment-likes with sharing host's process namespace\nRemediation: Ensure the host's process namespace is not shared.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=host-pid" + } + }, + { + "id": "invalid-target-ports", + "shortDescription": { + "text": "Indicates when deployments or services are using port names that are violating specifications." + }, + "fullDescription": { + "text": "Ensure that port naming is in conjunction with the specification. For more information, please look at the Kubernetes Service specification on this page: https://kubernetes.io/docs/reference/_print/#ServiceSpec. And additional information about IANA Service naming can be found on the following page: https://www.rfc-editor.org/rfc/rfc6335.html#section-5.1." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=target-port", + "help": { + "text": "Check: invalid-target-ports\nDescription: Indicates when deployments or services are using port names that are violating specifications.\nRemediation: Ensure that port naming is in conjunction with the specification. For more information, please look at the Kubernetes Service specification on this page: https://kubernetes.io/docs/reference/_print/#ServiceSpec. And additional information about IANA Service naming can be found on the following page: https://www.rfc-editor.org/rfc/rfc6335.html#section-5.1.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=target-port" + } + }, + { + "id": "latest-tag", + "shortDescription": { + "text": "Indicates when a deployment-like object is running a container with an invalid container image" + }, + "fullDescription": { + "text": "Use a container image with a specific tag other than latest." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=latest-tag", + "help": { + "text": "Check: latest-tag\nDescription: Indicates when a deployment-like object is running a container with an invalid container image\nRemediation: Use a container image with a specific tag other than latest.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=latest-tag" + } + }, + { + "id": "mismatching-selector", + "shortDescription": { + "text": "Indicates when deployment selectors fail to match the pod template labels." + }, + "fullDescription": { + "text": "Confirm that your deployment selector correctly matches the labels in its pod template." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=mismatching-selector", + "help": { + "text": "Check: mismatching-selector\nDescription: Indicates when deployment selectors fail to match the pod template labels.\nRemediation: Confirm that your deployment selector correctly matches the labels in its pod template.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=mismatching-selector" + } + }, + { + "id": "no-anti-affinity", + "shortDescription": { + "text": "Indicates when deployments with multiple replicas fail to specify inter-pod anti-affinity, to ensure that the orchestrator attempts to schedule replicas on different nodes." + }, + "fullDescription": { + "text": "Specify anti-affinity in your pod specification to ensure that the orchestrator attempts to schedule replicas on different nodes. Using podAntiAffinity, specify a labelSelector that matches pods for the deployment, and set the topologyKey to kubernetes.io/hostname. Refer to https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity for details." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=anti-affinity-not-specified", + "help": { + "text": "Check: no-anti-affinity\nDescription: Indicates when deployments with multiple replicas fail to specify inter-pod anti-affinity, to ensure that the orchestrator attempts to schedule replicas on different nodes.\nRemediation: Specify anti-affinity in your pod specification to ensure that the orchestrator attempts to schedule replicas on different nodes. Using podAntiAffinity, specify a labelSelector that matches pods for the deployment, and set the topologyKey to kubernetes.io/hostname. Refer to https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity for details.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=anti-affinity-not-specified" + } + }, + { + "id": "no-extensions-v1beta", + "shortDescription": { + "text": "Indicates when objects use deprecated API versions under extensions/v1beta." + }, + "fullDescription": { + "text": "Migrate using the apps/v1 API versions for the objects. Refer to https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/ for details." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=disallowed-api-objects", + "help": { + "text": "Check: no-extensions-v1beta\nDescription: Indicates when objects use deprecated API versions under extensions/v1beta.\nRemediation: Migrate using the apps/v1 API versions for the objects. Refer to https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/ for details.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=disallowed-api-objects" + } + }, + { + "id": "no-read-only-root-fs", + "shortDescription": { + "text": "Indicates when containers are running without a read-only root filesystem." + }, + "fullDescription": { + "text": "Set readOnlyRootFilesystem to true in the container securityContext." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=read-only-root-filesystems", + "help": { + "text": "Check: no-read-only-root-fs\nDescription: Indicates when containers are running without a read-only root filesystem.\nRemediation: Set readOnlyRootFilesystem to true in the container securityContext.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=read-only-root-filesystems" + } + }, + { + "id": "non-existent-service-account", + "shortDescription": { + "text": "Indicates when pods reference a service account that is not found." + }, + "fullDescription": { + "text": "Create the missing service account, or refer to an existing service account." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=non-existent-service-account", + "help": { + "text": "Check: non-existent-service-account\nDescription: Indicates when pods reference a service account that is not found.\nRemediation: Create the missing service account, or refer to an existing service account.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=non-existent-service-account" + } + }, + { + "id": "pdb-max-unavailable", + "shortDescription": { + "text": "Indicates when a PodDisruptionBudget has a maxUnavailable value that will always prevent disruptions of pods created by related deployment-like objects." + }, + "fullDescription": { + "text": "Change the PodDisruptionBudget to have maxUnavailable set to a value greater than 0. Refer to https://kubernetes.io/docs/tasks/run-application/configure-pdb/ for more information." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=no-pod-disruptions-allowed---maxunavailable", + "help": { + "text": "Check: pdb-max-unavailable\nDescription: Indicates when a PodDisruptionBudget has a maxUnavailable value that will always prevent disruptions of pods created by related deployment-like objects.\nRemediation: Change the PodDisruptionBudget to have maxUnavailable set to a value greater than 0. Refer to https://kubernetes.io/docs/tasks/run-application/configure-pdb/ for more information.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=no-pod-disruptions-allowed---maxunavailable" + } + }, + { + "id": "pdb-min-available", + "shortDescription": { + "text": "Indicates when a PodDisruptionBudget sets a minAvailable value that will always prevent disruptions of pods created by related deployment-like objects." + }, + "fullDescription": { + "text": "Change the PodDisruptionBudget to have minAvailable set to a number lower than the number of replicas in the related deployment-like objects. Refer to https://kubernetes.io/docs/tasks/run-application/configure-pdb/ for more information." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=no-pod-disruptions-allowed---minavailable", + "help": { + "text": "Check: pdb-min-available\nDescription: Indicates when a PodDisruptionBudget sets a minAvailable value that will always prevent disruptions of pods created by related deployment-like objects.\nRemediation: Change the PodDisruptionBudget to have minAvailable set to a number lower than the number of replicas in the related deployment-like objects. Refer to https://kubernetes.io/docs/tasks/run-application/configure-pdb/ for more information.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=no-pod-disruptions-allowed---minavailable" + } + }, + { + "id": "privilege-escalation-container", + "shortDescription": { + "text": "Alert on containers of allowing privilege escalation that could gain more privileges than its parent process." + }, + "fullDescription": { + "text": "Ensure containers do not allow privilege escalation by setting allowPrivilegeEscalation=false, privileged=false and removing CAP_SYS_ADMIN capability. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for more details." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=privilege-escalation-on-containers", + "help": { + "text": "Check: privilege-escalation-container\nDescription: Alert on containers of allowing privilege escalation that could gain more privileges than its parent process.\nRemediation: Ensure containers do not allow privilege escalation by setting allowPrivilegeEscalation=false, privileged=false and removing CAP_SYS_ADMIN capability. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for more details.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=privilege-escalation-on-containers" + } + }, + { + "id": "privileged-container", + "shortDescription": { + "text": "Indicates when deployments have containers running in privileged mode." + }, + "fullDescription": { + "text": "Do not run your container as privileged unless it is required." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=privileged-containers", + "help": { + "text": "Check: privileged-container\nDescription: Indicates when deployments have containers running in privileged mode.\nRemediation: Do not run your container as privileged unless it is required.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=privileged-containers" + } + }, + { + "id": "run-as-non-root", + "shortDescription": { + "text": "Indicates when containers are not set to runAsNonRoot." + }, + "fullDescription": { + "text": "Set runAsUser to a non-zero number and runAsNonRoot to true in your pod or container securityContext. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for details." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=run-as-non-root-user", + "help": { + "text": "Check: run-as-non-root\nDescription: Indicates when containers are not set to runAsNonRoot.\nRemediation: Set runAsUser to a non-zero number and runAsNonRoot to true in your pod or container securityContext. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for details.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=run-as-non-root-user" + } + }, + { + "id": "sensitive-host-mounts", + "shortDescription": { + "text": "Alert on deployments with sensitive host system directories mounted in containers" + }, + "fullDescription": { + "text": "Ensure sensitive host system directories are not mounted in containers by removing those Volumes and VolumeMounts." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=host-mounts", + "help": { + "text": "Check: sensitive-host-mounts\nDescription: Alert on deployments with sensitive host system directories mounted in containers\nRemediation: Ensure sensitive host system directories are not mounted in containers by removing those Volumes and VolumeMounts.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=host-mounts" + } + }, + { + "id": "ssh-port", + "shortDescription": { + "text": "Indicates when deployments expose port 22, which is commonly reserved for SSH access." + }, + "fullDescription": { + "text": "Ensure that non-SSH services are not using port 22. Confirm that any actual SSH servers have been vetted." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=ports", + "help": { + "text": "Check: ssh-port\nDescription: Indicates when deployments expose port 22, which is commonly reserved for SSH access.\nRemediation: Ensure that non-SSH services are not using port 22. Confirm that any actual SSH servers have been vetted.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=ports" + } + }, + { + "id": "unsafe-sysctls", + "shortDescription": { + "text": "Alert on deployments specifying unsafe sysctls that may lead to severe problems like wrong behavior of containers" + }, + "fullDescription": { + "text": "Ensure container does not allow unsafe allocation of system resources by removing unsafe sysctls configurations. For more details see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=unsafe-sysctls", + "help": { + "text": "Check: unsafe-sysctls\nDescription: Alert on deployments specifying unsafe sysctls that may lead to severe problems like wrong behavior of containers\nRemediation: Ensure container does not allow unsafe allocation of system resources by removing unsafe sysctls configurations. For more details see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=unsafe-sysctls" + } + }, + { + "id": "unset-cpu-requirements", + "shortDescription": { + "text": "Indicates when containers do not have CPU requests and limits set." + }, + "fullDescription": { + "text": "Set CPU requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=cpu-requirements", + "help": { + "text": "Check: unset-cpu-requirements\nDescription: Indicates when containers do not have CPU requests and limits set.\nRemediation: Set CPU requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=cpu-requirements" + } + }, + { + "id": "unset-memory-requirements", + "shortDescription": { + "text": "Indicates when containers do not have memory requests and limits set." + }, + "fullDescription": { + "text": "Set memory requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details." + }, + "helpUri": "https://docs.kubelinter.io/#/generated/templates?id=memory-requirements", + "help": { + "text": "Check: unset-memory-requirements\nDescription: Indicates when containers do not have memory requests and limits set.\nRemediation: Set memory requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details.\nTemplate: https://docs.kubelinter.io/#/generated/templates?id=memory-requirements" + } + } + ], + "version": "0.6.4" + } + }, + "invocations": [ + { + "endTimeUtc": "2023-11-03T11:18:21.394592Z", + "executionSuccessful": false, + "workingDirectory": { + "uri": "file:///Users/sauravsrijan/work/helm-charts" + } + } + ], + "results": [ + { + "ruleId": "no-read-only-root-fs", + "ruleIndex": 14, + "message": { + "text": "container \"kube-scheduler\" does not have a read-only root file system\nobject: \u003cno namespace\u003e/test-release-kube-scheduler apps/v1, Kind=Deployment" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/kube-scheduler/templates/deployment.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-kube-scheduler", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "Deployment", + "fullyQualifiedName": "apps/v1, Kind=Deployment", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "run-as-non-root", + "ruleIndex": 20, + "message": { + "text": "container \"kube-scheduler\" is not set to runAsNonRoot\nobject: \u003cno namespace\u003e/test-release-kube-scheduler apps/v1, Kind=Deployment" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/kube-scheduler/templates/deployment.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-kube-scheduler", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "Deployment", + "fullyQualifiedName": "apps/v1, Kind=Deployment", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "latest-tag", + "ruleIndex": 10, + "message": { + "text": "The container \"wget\" is using an invalid container image, \"busybox\". Please use images that are not blocked by the `BlockList` criteria : [\".*:(latest)$\" \"^[^:]*$\" \"(.*/[^:]+)$\"]\nobject: \u003cno namespace\u003e/test-release-runner-test-connection /v1, Kind=Pod" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/tests/test-connection.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-test-connection", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "v1", + "kind": "GVK/Version" + }, + { + "name": "Pod", + "fullyQualifiedName": "/v1, Kind=Pod", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "no-read-only-root-fs", + "ruleIndex": 14, + "message": { + "text": "container \"wget\" does not have a read-only root file system\nobject: \u003cno namespace\u003e/test-release-runner-test-connection /v1, Kind=Pod" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/tests/test-connection.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-test-connection", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "v1", + "kind": "GVK/Version" + }, + { + "name": "Pod", + "fullyQualifiedName": "/v1, Kind=Pod", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "run-as-non-root", + "ruleIndex": 20, + "message": { + "text": "container \"wget\" is not set to runAsNonRoot\nobject: \u003cno namespace\u003e/test-release-runner-test-connection /v1, Kind=Pod" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/tests/test-connection.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-test-connection", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "v1", + "kind": "GVK/Version" + }, + { + "name": "Pod", + "fullyQualifiedName": "/v1, Kind=Pod", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "unset-cpu-requirements", + "ruleIndex": 24, + "message": { + "text": "container \"wget\" has cpu request 0\nobject: \u003cno namespace\u003e/test-release-runner-test-connection /v1, Kind=Pod" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/tests/test-connection.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-test-connection", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "v1", + "kind": "GVK/Version" + }, + { + "name": "Pod", + "fullyQualifiedName": "/v1, Kind=Pod", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "unset-cpu-requirements", + "ruleIndex": 24, + "message": { + "text": "container \"wget\" has cpu limit 0\nobject: \u003cno namespace\u003e/test-release-runner-test-connection /v1, Kind=Pod" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/tests/test-connection.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-test-connection", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "v1", + "kind": "GVK/Version" + }, + { + "name": "Pod", + "fullyQualifiedName": "/v1, Kind=Pod", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "unset-memory-requirements", + "ruleIndex": 25, + "message": { + "text": "container \"wget\" has memory request 0\nobject: \u003cno namespace\u003e/test-release-runner-test-connection /v1, Kind=Pod" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/tests/test-connection.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-test-connection", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "v1", + "kind": "GVK/Version" + }, + { + "name": "Pod", + "fullyQualifiedName": "/v1, Kind=Pod", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "unset-memory-requirements", + "ruleIndex": 25, + "message": { + "text": "container \"wget\" has memory limit 0\nobject: \u003cno namespace\u003e/test-release-runner-test-connection /v1, Kind=Pod" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/tests/test-connection.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-test-connection", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "v1", + "kind": "GVK/Version" + }, + { + "name": "Pod", + "fullyQualifiedName": "/v1, Kind=Pod", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "env-var-secret", + "ruleIndex": 5, + "message": { + "text": "environment variable TASK_IMAGE_PULL_SECRET_NAME in container \"runner\" found\nobject: \u003cno namespace\u003e/test-release-runner apps/v1, Kind=Deployment" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/deployment.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "Deployment", + "fullyQualifiedName": "apps/v1, Kind=Deployment", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "env-var-secret", + "ruleIndex": 5, + "message": { + "text": "environment variable TASK_ARTIFACT_SECRET_NAME in container \"runner\" found\nobject: \u003cno namespace\u003e/test-release-runner apps/v1, Kind=Deployment" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/deployment.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "Deployment", + "fullyQualifiedName": "apps/v1, Kind=Deployment", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "no-read-only-root-fs", + "ruleIndex": 14, + "message": { + "text": "container \"runner\" does not have a read-only root file system\nobject: \u003cno namespace\u003e/test-release-runner apps/v1, Kind=Deployment" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/deployment.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "Deployment", + "fullyQualifiedName": "apps/v1, Kind=Deployment", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "run-as-non-root", + "ruleIndex": 20, + "message": { + "text": "container \"runner\" is not set to runAsNonRoot\nobject: \u003cno namespace\u003e/test-release-runner apps/v1, Kind=Deployment" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/deployment.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "Deployment", + "fullyQualifiedName": "apps/v1, Kind=Deployment", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "no-read-only-root-fs", + "ruleIndex": 14, + "message": { + "text": "container \"runner-rqlite\" does not have a read-only root file system\nobject: \u003cno namespace\u003e/test-release-runner-rqlite apps/v1, Kind=StatefulSet" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/rqlite-statefulset.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-rqlite", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "StatefulSet", + "fullyQualifiedName": "apps/v1, Kind=StatefulSet", + "kind": "GVK/Kind" + } + ] + } + ] + }, + { + "ruleId": "run-as-non-root", + "ruleIndex": 20, + "message": { + "text": "container \"runner-rqlite\" is not set to runAsNonRoot\nobject: \u003cno namespace\u003e/test-release-runner-rqlite apps/v1, Kind=StatefulSet" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "charts/runner/templates/rqlite-statefulset.yaml" + }, + "region": { + "startLine": 1 + } + }, + "logicalLocations": [ + { + "name": "test-release-runner-rqlite", + "kind": "Object Name" + }, + { + "name": "", + "kind": "Object Namespace" + }, + { + "name": "apps", + "kind": "GVK/Group" + }, + { + "name": "v1", + "fullyQualifiedName": "apps/v1", + "kind": "GVK/Version" + }, + { + "name": "StatefulSet", + "fullyQualifiedName": "apps/v1, Kind=StatefulSet", + "kind": "GVK/Kind" + } + ] + } + ] + } + ] + } + ] +} diff --git a/tests/test_report_parsing.py b/tests/test_report_parsing.py new file mode 100644 index 00000000..d7ac9a7a --- /dev/null +++ b/tests/test_report_parsing.py @@ -0,0 +1,52 @@ +import json +import os +import tempfile +from contextlib import contextmanager +from pathlib import Path +from typing import Any, Dict, Iterator + +import run_community_analyzer + + +def make_artifact(report_path: str, workdir: str = "") -> str: + """Return an artifact file for the given report, with the given workdir.""" + artifact_path = tempfile.NamedTemporaryFile().name + # skipcq: PTC-W0064 # Report path is safe + with open(report_path) as report_file: + data = report_file.read() + with open(artifact_path, "w") as artifact_file: + json.dump({"data": data, "metadata": {"work_dir": workdir}}, artifact_file) + return artifact_path + + +@contextmanager +def parse_single_artifact( + report_path: str, report_name: str +) -> Iterator[Dict[str, Any]]: + """Run community analyzer on a single artifact and return the deepsource result object.""" + artifact_path = make_artifact(report_path) + toolbox_path = tempfile.gettempdir() + os.environ["ARTIFACTS_PATH"] = artifact_path + os.environ["TOOLBOX_PATH"] = toolbox_path + output_path = Path(toolbox_path, "analysis_results.json").as_posix() + run_community_analyzer.main([f"--analyzer={report_name}"]) + with open(output_path) as output_file: + yield json.load(output_file) + + os.remove(artifact_path) + os.remove(output_path) + + +def test_sarif_parser() -> None: + """End to end test to make sure the SARIF parser throws no errors while parsing reports.""" + # We parse all reports in `tests/fixtures/reports` and try to make a deepsource report out of it. + # There shouldn't be any errors while parsing the reports. + # All test reports are present in the `tests/fixtures/reports` directory. + reports_base_dir = Path.joinpath(Path(__file__).parent, "fixtures", "reports") + reports = os.listdir(reports_base_dir) + for report in reports: + report_tool = report.removesuffix(".sarif") + report_path = Path(reports_base_dir, report).as_posix() + with parse_single_artifact(report_path, report_tool) as result: + assert result + assert result["issues"] is not None diff --git a/tox.ini b/tox.ini index 9c418ba0..0694b300 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,7 @@ envlist = py311,py311-mypy [testenv] deps = -rrequirements-dev.txt setenv = PYTHONPATH=. -commands = pytest --cov=./ --cov-report=xml +commands = pytest --cov=./ --cov-report=xml --cov-branch [testenv:py311-mypy] description = Type check with mypy From 3ed5cbe65ac0acd5052504ede7b224b265a50af0 Mon Sep 17 00:00:00 2001 From: Srijan Saurav <68371686+srijan-deepsource@users.noreply.github.com> Date: Mon, 13 Nov 2023 17:15:31 +0530 Subject: [PATCH 2/6] fix: don't duplicate issues when same artifact is reported again (#12) Changes: - Check the artifact result's hash before parsing. Ignore the artifact if the hash is same. - Raise sentry info alerts for unsanitised issues - fix type hints - add missing tests --- .gitignore | 1 + README.md | 2 +- sarif-parser/src/sarif_parser/__init__.py | 43 ++++++- sarif-parser/tests/sarif_parser_test.py | 43 ------- .../tests/{cli_test.py => test_cli.py} | 0 sarif-parser/tests/test_sarif_parser.py | 114 ++++++++++++++++++ ...zer_test.py => test_community_analyzer.py} | 0 tests/test_duplicate_artifacts.py | 56 +++++++++ 8 files changed, 211 insertions(+), 48 deletions(-) delete mode 100644 sarif-parser/tests/sarif_parser_test.py rename sarif-parser/tests/{cli_test.py => test_cli.py} (100%) create mode 100644 sarif-parser/tests/test_sarif_parser.py rename tests/{community_analyzer_test.py => test_community_analyzer.py} (100%) create mode 100644 tests/test_duplicate_artifacts.py diff --git a/.gitignore b/.gitignore index 27fb9029..b6e90c57 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ venv* coverage.xml .env **/.DS_Store +.vscode diff --git a/README.md b/README.md index 839a756f..32d0003f 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Push a tag after merging all the changes to the default (master) branch. The `Sy ### The test suite There are minimal tests for the `run_community_analyzer.py` wrapper in -`tests/community_analyzer_test.py` that do sanity checks, to ensure that the +`tests/test_community_analyzer.py` that do sanity checks, to ensure that the issue map is being respected, etc. For the SARIF parser itself, the test suite expects you to create two files in diff --git a/sarif-parser/src/sarif_parser/__init__.py b/sarif-parser/src/sarif_parser/__init__.py index 749e0ef5..3b37cb1c 100644 --- a/sarif-parser/src/sarif_parser/__init__.py +++ b/sarif-parser/src/sarif_parser/__init__.py @@ -1,9 +1,10 @@ """sarif-parser - Parse SARIF reports and covert them to DeepSource issues.""" from __future__ import annotations +import hashlib import json import os.path -from typing import Any, TypedDict +from typing import Any, Sequence, TypedDict, Union import sentry @@ -73,6 +74,15 @@ def parse( issue_code = issue["ruleId"] if issue_code in issue_map: issue_code = issue_map[issue_code]["issue_code"] + else: + # This issue isn't sanitised. Send an alert. + sentry.raise_info( + f"Could not find issue code for rule {issue_code} in issue map.", + context={ + "tool": run.get("tool", {}).get("driver", {}).get("name"), + "version": run.get("tool", {}).get("driver", {}).get("version"), + }, + ) deepsource_issue = Issue( issue_code=issue_code, @@ -90,9 +100,21 @@ def parse( return deepsource_issues +def results_hash(sarif_data: dict[str, Any]) -> str: + """Returns a hash of the results in the SARIF file.""" + # Extract results from SARIF daa. We take hash only for results. + run_results = {} + for idx, result in enumerate(sarif_data["runs"]): + run_results[idx] = result["results"] + results_str = json.dumps(run_results, sort_keys=True) + + # Calculate a checksum of the results + return hashlib.sha256(results_str.encode(), usedforsecurity=False).hexdigest() + + def run_sarif_parser( - filepath: str, - output_path: str, + filepath: Union[str, os.PathLike[str]], + output_path: Union[str, os.PathLike[str]], issue_map_path: str | None, ) -> None: """Parse SARIF files from given filepath, and save JSON output in output path.""" @@ -101,7 +123,11 @@ def run_sarif_parser( raise FileNotFoundError(f"{filepath} does not exist.") if os.path.isdir(filepath): - artifacts = [os.path.join(filepath, file) for file in os.listdir(filepath)] + # Get list of files in directory, sorted by name in the reversed order + artifacts: Sequence[str | os.PathLike[str]] = sorted( + (os.path.join(filepath, file) for file in os.listdir(filepath)), + reverse=True, + ) else: artifacts = [filepath] @@ -120,11 +146,20 @@ def run_sarif_parser( # Run parser deepsource_issues = [] + artifact_hashes = set() for artifact_path in artifacts: with open(artifact_path) as file: # skipcq: PTC-W6004 -- nothing sensitive here artifact = json.load(file) sarif_data = json.loads(artifact["data"]) + sarif_hash = results_hash(sarif_data) + + if sarif_hash in artifact_hashes: + # Skip this artifact, as it is a duplicate + continue + else: + artifact_hashes.add(sarif_hash) + work_dir = artifact["metadata"]["work_dir"] issues = parse(sarif_data, work_dir, issue_map) deepsource_issues.extend(issues) diff --git a/sarif-parser/tests/sarif_parser_test.py b/sarif-parser/tests/sarif_parser_test.py deleted file mode 100644 index af5f3fd0..00000000 --- a/sarif-parser/tests/sarif_parser_test.py +++ /dev/null @@ -1,43 +0,0 @@ -import json -import os.path - -import pytest -import sarif_parser - - -def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: - """Generates all sarif_parser tests based on files in the sarif_files folder.""" - test_files_path = os.path.join(os.path.dirname(__file__), "sarif_files") - - test_params, test_names = [], [] - for file_name in os.listdir(test_files_path): - if not file_name.endswith(".sarif"): - continue - - deepsource_file_name = file_name + ".json" - deepsource_file_path = os.path.join(test_files_path, deepsource_file_name) - if not os.path.isfile(deepsource_file_path): - raise AssertionError( - f"Output file {deepsource_file_name!r} for {file_name!r} doesn't exist" - ) - - sarif_file_path = os.path.join(test_files_path, file_name) - test_params.append((sarif_file_path, deepsource_file_path)) - test_names.append(file_name) - - metafunc.parametrize( - ("sarif_file_path", "deepsource_file_path"), - test_params, - ids=test_names, - ) - - -def test_sarif_parser(sarif_file_path: str, deepsource_file_path: str) -> None: - """Tests parsing of various SARIF outputs into DeepSource issues.""" - with open(deepsource_file_path) as file: - expected_output = json.load(file) - - with open(sarif_file_path) as sarif_file: - sarif_data = json.load(sarif_file) - - assert sarif_parser.parse(sarif_data) == expected_output diff --git a/sarif-parser/tests/cli_test.py b/sarif-parser/tests/test_cli.py similarity index 100% rename from sarif-parser/tests/cli_test.py rename to sarif-parser/tests/test_cli.py diff --git a/sarif-parser/tests/test_sarif_parser.py b/sarif-parser/tests/test_sarif_parser.py new file mode 100644 index 00000000..9eed03dc --- /dev/null +++ b/sarif-parser/tests/test_sarif_parser.py @@ -0,0 +1,114 @@ +import json +import os.path +from pathlib import Path +from unittest.mock import MagicMock, call, patch + +import pytest +import sarif_parser + + +def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: + """Generates all sarif_parser tests based on files in the sarif_files folder.""" + test_files_path = os.path.join(os.path.dirname(__file__), "sarif_files") + + test_params, test_names = [], [] + for file_name in os.listdir(test_files_path): + if not file_name.endswith(".sarif"): + continue + + deepsource_file_name = file_name + ".json" + deepsource_file_path = os.path.join(test_files_path, deepsource_file_name) + if not os.path.isfile(deepsource_file_path): + raise AssertionError( + f"Output file {deepsource_file_name!r} for {file_name!r} doesn't exist" + ) + + sarif_file_path = os.path.join(test_files_path, file_name) + test_params.append((sarif_file_path, deepsource_file_path)) + test_names.append(file_name) + + metafunc.parametrize( + ("sarif_file_path", "deepsource_file_path"), + test_params, + ids=test_names, + ) + + +def test_sarif_parser(sarif_file_path: str, deepsource_file_path: str) -> None: + """Tests parsing of various SARIF outputs into DeepSource issues.""" + # skipcq: PTC-W6004 -- nothing sensitive here + with open(deepsource_file_path) as file: + expected_output = json.load(file) + + with open(sarif_file_path) as sarif_file: + sarif_data = json.load(sarif_file) + + assert sarif_parser.parse(sarif_data) == expected_output + + +@patch("sentry.raise_info") +# skipcq: PYL-W0613 +def test_sarif_parser_no_issue_map( + mocked_run: MagicMock, + sarif_file_path: str, + deepsource_file_path: str, + tmp_path: Path, +) -> None: + """Assert that sentry.raise_info is called when issue map is not found.""" + artifacts_path = tmp_path / "artifacts" + artifacts_path.mkdir() + # Create an artifact # skipcq: PTC-W6004 -- nothing sensitive here + with open(sarif_file_path) as fin, open( + artifacts_path / "artifact1.sarif", "w" + ) as fout: + json.dump({"metadata": {"work_dir": "."}, "data": fin.read()}, fout) + + sarif_parser.run_sarif_parser( + artifacts_path, tmp_path / "result.json", "some/random/path" + ) + + no_issue_map_call = call( + "Could not find issue map at some/random/path for analyzer." + ) + # since no issue map is found, there would also be calls for unsanitised issues. + single_unsanitised_issue_call = call( + "Could not find issue code for rule name-not-defined in issue map.", + context={"tool": "mypy", "version": "0.910"}, + ) + + assert mocked_run.has_calls([no_issue_map_call, single_unsanitised_issue_call]) + + +def test_artifact_hashing( + sarif_file_path: str, deepsource_file_path: str, tmp_path: Path +) -> None: + """End to end tests for when same artifacts are present in the directory.""" + artifacts_path = tmp_path / "artifacts" + artifacts_path.mkdir() + # Create an artifact # skipcq: PTC-W6004 -- nothing sensitive here + with open(sarif_file_path) as fin, open( + artifacts_path / "artifact1.sarif", "w" + ) as fout: + json.dump({"metadata": {"work_dir": "."}, "data": fin.read()}, fout) + + sarif_parser.run_sarif_parser( + artifacts_path, tmp_path / "result.json", "some/random/path" + ) + + old_results = json.load(open(tmp_path / "result.json")) + + # Now, put one more artifact in the directory + # This is duplicate. # skipcq: PTC-W6004 + with open(sarif_file_path) as fin, open( + artifacts_path / "artifact2.sarif", "w" + ) as fout: + json.dump({"metadata": {"work_dir": "."}, "data": fin.read()}, fout) + + # Run the sarif parser again + sarif_parser.run_sarif_parser( + artifacts_path, tmp_path / "result.json", "some/random/path" + ) + + # make sure that the results are same + new_results = json.load(open(tmp_path / "result.json")) + assert old_results == new_results diff --git a/tests/community_analyzer_test.py b/tests/test_community_analyzer.py similarity index 100% rename from tests/community_analyzer_test.py rename to tests/test_community_analyzer.py diff --git a/tests/test_duplicate_artifacts.py b/tests/test_duplicate_artifacts.py new file mode 100644 index 00000000..50549d92 --- /dev/null +++ b/tests/test_duplicate_artifacts.py @@ -0,0 +1,56 @@ +import json +import os +import pathlib +import shutil +from contextlib import contextmanager +from typing import Any, Dict, Iterator + +import run_community_analyzer + + +@contextmanager +def patch_env_values( + toolbox_path: pathlib.Path, artifacts_path: pathlib.Path +) -> Iterator[None]: + """Context manager to patch the ARTIFACTS_PATH environment variable""" + old_artifacts_path = os.getenv("ARTIFACTS_PATH") + old_toolbox_path = os.getenv("TOOLBOX_PATH") + os.environ["ARTIFACTS_PATH"] = str(artifacts_path) + os.environ["TOOLBOX_PATH"] = str(toolbox_path) + try: + yield + finally: + os.environ["ARTIFACTS_PATH"] = old_artifacts_path or "" + os.environ["TOOLBOX_PATH"] = old_toolbox_path or "" + + +def test_duplicate_artifacts(tmp_path: pathlib.Path) -> None: + """Make sure results are not duplicated when same artifacts are reported more than""" + # create a temporary directory to store duplicate artifacts + toolbox_path = tmp_path / "toolbox" + artifacts_dir = tmp_path / "artifacts" + toolbox_path.mkdir() + artifacts_dir.mkdir() + + # Copy the artifact from `./test_artifacts` to the temporary directory + artifact_path = pathlib.Path(__file__).parent / "test_artifacts" / "kubelinter_1" + shutil.copy(artifact_path, artifacts_dir / "artifact_1") + shutil.copy(artifact_path, artifacts_dir / "artifact_2") + shutil.copy(artifact_path, artifacts_dir / "artifact_3") + + # Run the community analyzer on the artifact directory + with patch_env_values(toolbox_path, artifacts_dir): + run_community_analyzer.main(["--analyzer=kube-linter"]) + + # Make sure there are no duplicates in the results + with open(toolbox_path / "analysis_results.json") as fp: + analysis_results = json.load(fp) + issues_raised = analysis_results["issues"] + + issues_set = {str(issue) for issue in issues_raised} + + # assert that all the issues raised are unique + assert len(issues_raised) == len(issues_set) + # Make sure the issues are same + for issue in issues_raised: + assert str(issue) in issues_set From 15da294bef0390f2e645b434321844d6d256b0bc Mon Sep 17 00:00:00 2001 From: Srijan Saurav <68371686+srijan-deepsource@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:24:48 +0530 Subject: [PATCH 3/6] chore: add armory (#13) Armory is an in-house github action to validate the Analyzer directories and issues. It highlights the issues in the PRs that can lead to unexpected behaviours during analyzer syncs. --------- Signed-off-by: Srijan Saurav <68371686+srijan-deepsource@users.noreply.github.com> --- .github/workflows/armory.yaml | 18 ++++++++++++++++++ .../infer/.deepsource/issues/INFER-W0001.toml | 1 + .../.deepsource/issues/KUBELIN-W1001.toml | 1 + .../.deepsource/issues/KUBELIN-W1002.toml | 1 + .../.deepsource/issues/KUBELIN-W1003.toml | 1 + .../.deepsource/issues/KUBELIN-W1004.toml | 1 + .../.deepsource/issues/KUBELIN-W1005.toml | 1 + .../.deepsource/issues/KUBELIN-W1006.toml | 1 + .../.deepsource/issues/KUBELIN-W1007.toml | 1 + .../.deepsource/issues/KUBELIN-W1008.toml | 1 + .../.deepsource/issues/KUBELIN-W1009.toml | 1 + .../.deepsource/issues/KUBELIN-W1010.toml | 1 + .../.deepsource/issues/KUBELIN-W1011.toml | 1 + .../.deepsource/issues/KUBELIN-W1012.toml | 1 + .../.deepsource/issues/KUBELIN-W1013.toml | 1 + .../.deepsource/issues/KUBELIN-W1014.toml | 1 + .../.deepsource/issues/KUBELIN-W1015.toml | 1 + .../.deepsource/issues/KUBELIN-W1016.toml | 1 + .../.deepsource/issues/KUBELIN-W1017.toml | 1 + .../.deepsource/issues/KUBELIN-W1018.toml | 1 + .../.deepsource/issues/KUBELIN-W1019.toml | 1 + .../.deepsource/issues/KUBELIN-W1020.toml | 1 + .../.deepsource/issues/KUBELIN-W1021.toml | 1 + .../.deepsource/issues/KUBELIN-W1022.toml | 1 + .../.deepsource/issues/KUBELIN-W1023.toml | 1 + .../.deepsource/issues/KUBELIN-W1024.toml | 1 + .../.deepsource/issues/KUBELIN-W1025.toml | 1 + .../.deepsource/issues/KUBELIN-W1026.toml | 1 + .../.deepsource/issues/KUBELIN-W1027.toml | 1 + .../.deepsource/issues/KUBELIN-W1028.toml | 1 + .../.deepsource/issues/KUBELIN-W1029.toml | 1 + .../.deepsource/issues/KUBELIN-W1030.toml | 1 + .../.deepsource/issues/KUBELIN-W1031.toml | 1 + .../.deepsource/issues/KUBELIN-W1032.toml | 1 + .../.deepsource/issues/KUBELIN-W1033.toml | 1 + .../.deepsource/issues/KUBELIN-W1034.toml | 1 + .../.deepsource/issues/KUBELIN-W1035.toml | 1 + .../.deepsource/issues/KUBELIN-W1036.toml | 1 + .../.deepsource/issues/KUBELIN-W1037.toml | 1 + .../.deepsource/issues/KUBELIN-W1038.toml | 1 + .../.deepsource/issues/KUBELIN-W1039.toml | 1 + .../.deepsource/issues/KUBELIN-W1040.toml | 1 + .../.deepsource/issues/KUBELIN-W1041.toml | 1 + .../.deepsource/issues/KUBELIN-W1042.toml | 1 + .../.deepsource/issues/KUBELIN-W1043.toml | 1 + .../.deepsource/issues/KUBELIN-W1044.toml | 1 + .../.deepsource/issues/KUBELIN-W1045.toml | 2 ++ .../.deepsource/issues/KUBELIN-W1046.toml | 1 + .../.deepsource/issues/KUBELIN-W1047.toml | 1 + .../.deepsource/issues/KUBELIN-W1048.toml | 1 + .../.deepsource/issues/KUBELIN-W1049.toml | 1 + .../.deepsource/issues/KUBELIN-W1050.toml | 1 + .../.deepsource/issues/KUBELIN-W1051.toml | 1 + analyzers/kube-linter/utils/issue_gen.py | 5 +++-- 54 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/armory.yaml diff --git a/.github/workflows/armory.yaml b/.github/workflows/armory.yaml new file mode 100644 index 00000000..d5f02b07 --- /dev/null +++ b/.github/workflows/armory.yaml @@ -0,0 +1,18 @@ +name: armory + +on: [push] + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/checkout@v3 + with: + repository: deepsourcecorp/armory + ref: master + token: ${{ secrets.DS_ARMORY_TOKEN }} + path: .github/actions/armory + - name: Run Armory + uses: ./.github/actions/armory diff --git a/analyzers/infer/.deepsource/issues/INFER-W0001.toml b/analyzers/infer/.deepsource/issues/INFER-W0001.toml index 4613cbf1..e23b1787 100644 --- a/analyzers/infer/.deepsource/issues/INFER-W0001.toml +++ b/analyzers/infer/.deepsource/issues/INFER-W0001.toml @@ -1,5 +1,6 @@ title = "infer-title" +verbose_name = "infer-verbose-name" severity = "major" category = "antipattern" weight = 70 diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1001.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1001.toml index 42e2e552..c68d105c 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1001.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1001.toml @@ -11,3 +11,4 @@ Indicates when a subject (Group/User/ServiceAccount) has create access to Pods. ## Remediation Where possible, remove create access to pod objects in the cluster. """ +verbose_name = "access-to-create-pods" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1002.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1002.toml index ad6bd686..19a27ccd 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1002.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1002.toml @@ -11,3 +11,4 @@ Indicates when a subject (Group/User/ServiceAccount) has access to Secrets. CIS Where possible, remove get, list and watch access to secret objects in the cluster. """ +verbose_name = "access-to-secrets" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1003.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1003.toml index 4d8e9d18..f257f6d0 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1003.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1003.toml @@ -11,3 +11,4 @@ CIS Benchmark 5.1.1 Ensure that the cluster-admin role is only used where requir Create and assign a separate role that has access to specific resources/actions needed for the service account. """ +verbose_name = "cluster-admin-role-binding" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1004.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1004.toml index 9126ec18..4dbf587b 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1004.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1004.toml @@ -11,3 +11,4 @@ Indicates when HorizontalPodAutoscalers target a missing resource. Confirm that your HorizontalPodAutoscaler's scaleTargetRef correctly matches one of your deployments. """ +verbose_name = "dangling-horizontalpodautoscaler" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1005.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1005.toml index 501dd5f3..d5c4cd0f 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1005.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1005.toml @@ -11,3 +11,4 @@ Indicates when ingress do not have any associated services. Confirm that your ingress's backend correctly matches the name and port on one of your services. """ +verbose_name = "dangling-ingress" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1006.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1006.toml index f876e3ad..81319272 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1006.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1006.toml @@ -11,3 +11,4 @@ Indicates when networkpolicies do not have any associated deployments. Confirm that your networkPolicy's podselector correctly matches the labels on one of your deployments. """ +verbose_name = "dangling-networkpolicy" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1007.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1007.toml index af8bed07..a411db98 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1007.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1007.toml @@ -11,3 +11,4 @@ Indicates when NetworkPolicyPeer in Egress/Ingress rules -in the Spec of Network Confirm that your NetworkPolicy's Ingress/Egress peer's podselector correctly matches the labels on one of your deployments. """ +verbose_name = "dangling-networkpolicypeer-podselector" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1008.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1008.toml index 497b4f54..1ff21845 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1008.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1008.toml @@ -11,3 +11,4 @@ Indicates when services do not have any associated deployments. Confirm that your service's selector correctly matches the labels on one of your deployments. """ +verbose_name = "dangling-service" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1009.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1009.toml index 591a86a4..6db2ee72 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1009.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1009.toml @@ -11,3 +11,4 @@ Indicates when pods use the default service account. Create a dedicated service account for your pod. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ for details. """ +verbose_name = "default-service-account" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1010.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1010.toml index 1529009b..bd8f7fd3 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1010.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1010.toml @@ -11,3 +11,4 @@ Indicates when deployments use the deprecated serviceAccount field. Use the serviceAccountName field instead. If you must specify serviceAccount, ensure values for serviceAccount and serviceAccountName match. """ +verbose_name = "deprecated-service-account-field" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1011.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1011.toml index 264db205..fbd32dd4 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1011.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1011.toml @@ -11,3 +11,4 @@ Alert on deployments that have no specified dnsConfig options Specify dnsconfig options in your Pod specification to ensure the expected DNS setting on the Pod. Refer to https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config for details. """ +verbose_name = "dnsconfig-options" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1012.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1012.toml index 04318ed5..1fc73a82 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1012.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1012.toml @@ -11,3 +11,4 @@ Alert on deployments with docker.sock mounted in containers. Ensure the Docker socket is not mounted inside any containers by removing the associated Volume and VolumeMount in deployment yaml specification. If the Docker socket is mounted inside a container it could allow processes running within the container to execute Docker commands which would effectively allow for full control of the host. """ +verbose_name = "docker-sock" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1013.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1013.toml index c3cc2380..9822ce79 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1013.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1013.toml @@ -11,3 +11,4 @@ Indicates when containers do not drop NET_RAW capability NET_RAW makes it so that an application within the container is able to craft raw packets, use raw sockets, and bind to any address. Remove this capability in the containers under containers security contexts. """ +verbose_name = "drop-net-raw-capability" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1014.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1014.toml index b92463bf..a14de2a2 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1014.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1014.toml @@ -11,3 +11,4 @@ Check that duplicate named env vars aren't passed to a deployment like. Confirm that your DeploymentLike doesn't have duplicate env vars names. """ +verbose_name = "duplicate-env-var" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1015.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1015.toml index e15d8d90..8db420ff 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1015.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1015.toml @@ -11,3 +11,4 @@ Indicates when objects use a secret in an environment variable. Do not use raw secrets in environment variables. Instead, either mount the secret as a file or use a secretKeyRef. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets for details. """ +verbose_name = "env-var-secret" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1016.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1016.toml index 051304de..ef1757cb 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1016.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1016.toml @@ -11,3 +11,4 @@ Alert on services for forbidden types Ensure containers are not exposed through a forbidden service type such as NodePort or LoadBalancer. """ +verbose_name = "exposed-services" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1017.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1017.toml index 5437daa1..3e18d611 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1017.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1017.toml @@ -11,3 +11,4 @@ Alert on pods/deployment-likes with sharing host's IPC namespace Ensure the host's IPC namespace is not shared. """ +verbose_name = "host-ipc" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1018.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1018.toml index 6a7b40be..e703e897 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1018.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1018.toml @@ -10,3 +10,4 @@ Alert on pods/deployment-likes with sharing host's network namespace ## Remediation Ensure the host's network namespace is not shared. """ +verbose_name = "host-network" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1019.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1019.toml index 0d9ea7c4..de0da2f7 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1019.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1019.toml @@ -11,3 +11,4 @@ Alert on pods/deployment-likes with sharing host's process namespace Ensure the host's process namespace is not shared. """ +verbose_name = "host-pid" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1020.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1020.toml index 4e95a538..63b1ce46 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1020.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1020.toml @@ -11,3 +11,4 @@ Indicates when a HorizontalPodAutoscaler specifies less than three minReplicas Increase the number of replicas in the HorizontalPodAutoscaler to at least three to increase fault tolerance. """ +verbose_name = "hpa-minimum-three-replicas" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1021.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1021.toml index 666fec7e..b6e51cc9 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1021.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1021.toml @@ -11,3 +11,4 @@ Indicates when deployments or services are using port names that are violating s Ensure that port naming is in conjunction with the specification. For more information, please look at the Kubernetes Service specification on this page: https://kubernetes.io/docs/reference/_print/#ServiceSpec. And additional information about IANA Service naming can be found on the following page: https://www.rfc-editor.org/rfc/rfc6335.html#section-5.1. """ +verbose_name = "invalid-target-ports" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1022.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1022.toml index 255100f7..31b8b96e 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1022.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1022.toml @@ -11,3 +11,4 @@ Indicates when a deployment-like object is running a container with an invalid c Use a container image with a specific tag other than latest. """ +verbose_name = "latest-tag" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1023.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1023.toml index 9b6a1149..d8086c8d 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1023.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1023.toml @@ -11,3 +11,4 @@ Indicates when a deployment uses less than three replicas Increase the number of replicas in the deployment to at least three to increase the fault tolerance of the deployment. """ +verbose_name = "minimum-three-replicas" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1024.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1024.toml index a6c078ef..8178d0f3 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1024.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1024.toml @@ -11,3 +11,4 @@ Indicates when deployment selectors fail to match the pod template labels. Confirm that your deployment selector correctly matches the labels in its pod template. """ +verbose_name = "mismatching-selector" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1025.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1025.toml index ebd54b07..78c3f49e 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1025.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1025.toml @@ -11,3 +11,4 @@ Indicates when deployments with multiple replicas fail to specify inter-pod anti Specify anti-affinity in your pod specification to ensure that the orchestrator attempts to schedule replicas on different nodes. Using podAntiAffinity, specify a labelSelector that matches pods for the deployment, and set the topologyKey to kubernetes.io/hostname. Refer to https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity for details. """ +verbose_name = "no-anti-affinity" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1026.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1026.toml index 43b8a268..df535ebf 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1026.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1026.toml @@ -11,3 +11,4 @@ Indicates when objects use deprecated API versions under extensions/v1beta. Migrate using the apps/v1 API versions for the objects. Refer to https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/ for details. """ +verbose_name = "no-extensions-v1beta" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1027.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1027.toml index 6dec279c..5affdfe4 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1027.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1027.toml @@ -11,3 +11,4 @@ Indicates when containers fail to specify a liveness probe. Specify a liveness probe in your container. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ for details. """ +verbose_name = "no-liveness-probe" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1028.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1028.toml index 4c191fc6..9ed12b14 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1028.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1028.toml @@ -11,3 +11,4 @@ Alert on deployments that have no node affinity defined Specify node-affinity in your pod specification to ensure that the orchestrator attempts to schedule replicas on specified nodes. Refer to https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity for details. """ +verbose_name = "no-node-affinity" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1029.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1029.toml index 29951812..6ef09387 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1029.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1029.toml @@ -11,3 +11,4 @@ Indicates when containers are running without a read-only root filesystem. Set readOnlyRootFilesystem to true in the container securityContext. """ +verbose_name = "no-read-only-root-fs" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1030.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1030.toml index 9361a294..9a31437a 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1030.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1030.toml @@ -11,3 +11,4 @@ Indicates when containers fail to specify a readiness probe. Specify a readiness probe in your container. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ for details. """ +verbose_name = "no-readiness-probe" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1031.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1031.toml index ae420614..ee99ca3f 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1031.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1031.toml @@ -11,3 +11,4 @@ Indicates when a deployment doesn't use a rolling update strategy ## Remediation Use a rolling update strategy to avoid service disruption during an update. A rolling update strategy allows for pods to be systematicaly replaced in a controlled fashion to ensure no service disruption. """ +verbose_name = "no-rolling-update-strategy" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1032.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1032.toml index 4ca8e020..cc11fef0 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1032.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1032.toml @@ -11,3 +11,4 @@ Indicates when pods reference a service account that is not found. Create the missing service account, or refer to an existing service account. """ +verbose_name = "non-existent-service-account" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1033.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1033.toml index c9df15f8..52b796e8 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1033.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1033.toml @@ -11,3 +11,4 @@ Alert on deployment-like objects that are not selected by any NetworkPolicy. Ensure pod does not accept unsafe traffic by isolating it with a NetworkPolicy. See https://cloud.redhat.com/blog/guide-to-kubernetes-ingress-network-policies for more details. """ +verbose_name = "non-isolated-pod" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1034.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1034.toml index 2d161ab0..18241cbb 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1034.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1034.toml @@ -11,3 +11,4 @@ Indicates when a PodDisruptionBudget has a maxUnavailable value that will always Change the PodDisruptionBudget to have maxUnavailable set to a value greater than 0. Refer to https://kubernetes.io/docs/tasks/run-application/configure-pdb/ for more information. """ +verbose_name = "pdb-max-unavailable" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1035.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1035.toml index 4d735fe7..b5430b61 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1035.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1035.toml @@ -11,3 +11,4 @@ Indicates when a PodDisruptionBudget sets a minAvailable value that will always Change the PodDisruptionBudget to have minAvailable set to a number lower than the number of replicas in the related deployment-like objects. Refer to https://kubernetes.io/docs/tasks/run-application/configure-pdb/ for more information. """ +verbose_name = "pdb-min-available" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1036.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1036.toml index 0db25761..b91a6f9e 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1036.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1036.toml @@ -11,3 +11,4 @@ Alert on containers of allowing privilege escalation that could gain more privil Ensure containers do not allow privilege escalation by setting allowPrivilegeEscalation=false, privileged=false and removing CAP_SYS_ADMIN capability. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for more details. """ +verbose_name = "privilege-escalation-container" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1037.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1037.toml index 3b593bda..27add470 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1037.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1037.toml @@ -10,3 +10,4 @@ Indicates when deployments have containers running in privileged mode. ## Remediation Do not run your container as privileged unless it is required. """ +verbose_name = "privileged-container" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1038.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1038.toml index bd6dcd78..6f06d21b 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1038.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1038.toml @@ -10,3 +10,4 @@ Alert on deployments with privileged ports mapped in containers. ## Remediation Ensure privileged ports [0, 1024] are not mapped within containers. """ +verbose_name = "privileged-ports" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1039.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1039.toml index 00f2a501..40945e93 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1039.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1039.toml @@ -10,3 +10,4 @@ Indicates when a deployment reads secret from environment variables. CIS Benchma ## Remediation If possible, rewrite application code to read secrets from mounted secret files, rather than from environment variables. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets for details. """ +verbose_name = "read-secret-from-env-var" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1040.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1040.toml index 6a86475e..d3ddc5a1 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1040.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1040.toml @@ -11,3 +11,4 @@ Indicates when objects do not have an email annotation with a valid email addres ## Remediation Add an email annotation to your object with the email address of the object's owner. """ +verbose_name = "required-annotation-email" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1041.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1041.toml index 595139d5..a7ee3941 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1041.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1041.toml @@ -11,3 +11,4 @@ Indicates when objects do not have an email annotation with an owner label. ## Remediation Add an email annotation to your object with the name of the object's owner. """ +verbose_name = "required-label-owner" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1042.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1042.toml index 2c859959..3a5fd70a 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1042.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1042.toml @@ -10,3 +10,4 @@ Indicates when containers are running as the root user. ## Remediation Set `runAsUser` to a non-zero number and `runAsNonRoot` to `true` in your pod or container securityContext. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for details. """ +verbose_name = "run-as-non-root" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1043.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1043.toml index 8f929efc..efba0906 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1043.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1043.toml @@ -10,3 +10,4 @@ Alert on deployments with sensitive host system directories mounted in container ## Remediation Ensure sensitive host system directories are not mounted in containers by removing those Volumes and VolumeMounts. """ +verbose_name = "sensitive-host-mounts" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1044.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1044.toml index 1abc8ba7..76013ab0 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1044.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1044.toml @@ -10,3 +10,4 @@ Indicates when deployments expose port 22, which is commonly reserved for SSH ac ## Remediation Ensure that non-SSH services are not using port 22. Confirm that any actual SSH servers have been vetted. """ +verbose_name = "ssh-port" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1045.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1045.toml index 0277f52a..b34cb62b 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1045.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1045.toml @@ -10,3 +10,5 @@ Alert on deployments with unsafe /proc mount (procMount=Unmasked) that will bypa ## Remediation Ensure container does not unsafely exposes parts of /proc by setting procMount=Default. Unmasked ProcMount bypasses the default masking behavior of the container runtime. See https://kubernetes.io/docs/concepts/security/pod-security-standards/ for more details. +""" +verbose_name = "unsafe-proc-mount" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1046.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1046.toml index dc31a103..9a4afd20 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1046.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1046.toml @@ -11,3 +11,4 @@ Alert on deployments specifying unsafe sysctls that may lead to severe problems ## Remediation Ensure that containers do not allow unsafe allocation of system resources by removing unsafe kernel parameter configurations. For more details, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ and https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime. """ +verbose_name = "unsafe-sysctls" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1047.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1047.toml index e788a782..75ad79c7 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1047.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1047.toml @@ -10,3 +10,4 @@ Indicates when containers do not have CPU requests and limits set. ## Remediation Set CPU requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details. """ +verbose_name = "unset-cpu-requirements" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1048.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1048.toml index 5f67156f..b6420405 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1048.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1048.toml @@ -11,3 +11,4 @@ Indicates when containers do not have memory requests and limits set. ## Remediation Set memory requests and limits for your container based on its requirements. Refer to https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits for details. """ +verbose_name = "unset-memory-requirements" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1049.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1049.toml index e429c6ac..5ed7fc57 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1049.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1049.toml @@ -10,3 +10,4 @@ Indicates when a resource is deployed to the default namespace. CIS Benchmark 5. ## Remediation Create namespaces for objects in your deployment. """ +verbose_name = "use-namespace" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1050.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1050.toml index 6dda954a..2933c817 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1050.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1050.toml @@ -11,3 +11,4 @@ Indicate when a wildcard is used in Role or ClusterRole rules. CIS Benchmark 5.1 ## Remediation Where possible replace any use of wildcards in clusterroles and roles with specific objects or actions. """ +verbose_name = "wildcard-in-rules" diff --git a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1051.toml b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1051.toml index a22cd5cb..ea97b6d5 100644 --- a/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1051.toml +++ b/analyzers/kube-linter/.deepsource/issues/KUBELIN-W1051.toml @@ -10,3 +10,4 @@ Indicates when containers mount a host path as writable. ## Remediation Set containers to mount host paths as readOnly, if you need to access files on the host. """ +verbose_name = "writable-host-mount" diff --git a/analyzers/kube-linter/utils/issue_gen.py b/analyzers/kube-linter/utils/issue_gen.py index 320b9d11..dfeb8e98 100644 --- a/analyzers/kube-linter/utils/issue_gen.py +++ b/analyzers/kube-linter/utils/issue_gen.py @@ -4,10 +4,11 @@ from issue_map_gen import generate_mapping, get_issue_map, get_issues_json -def get_toml_content(title, description, remediation) -> str: +def get_toml_content(title, verbose_name, description, remediation) -> str: """Return the content of the toml file.""" content = f''' title = "{title}" + verbose_name = "{verbose_name}" severity = "major" category = "antipattern" weight = 70 @@ -44,7 +45,7 @@ def update_issue_tomls() -> None: description = issue["description"] remediation = issue["remediation"] - content = get_toml_content(issue_name, description, remediation) + content = get_toml_content(issue_name, issue_name, description, remediation) with open(filepath, "w") as f: f.write(content) From fbfd5e98da284b534c933396fa9bfa41783c86a0 Mon Sep 17 00:00:00 2001 From: Srijan Saurav <68371686+srijan-deepsource@users.noreply.github.com> Date: Wed, 15 Nov 2023 18:59:24 +0530 Subject: [PATCH 4/6] chore: fail tests if the test sarif reports have unsanitised issue codes (#14) --- requirements-dev.txt | 1 + requirements.txt | 1 + tests/test_report_parsing.py | 40 +++++++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 11ceb1f7..f4ae3bab 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,3 @@ -e ./sarif-parser[dev] sentry-sdk +python-frontmatter diff --git a/requirements.txt b/requirements.txt index a1317358..46c87762 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ ./sarif-parser sentry-sdk +python-frontmatter diff --git a/tests/test_report_parsing.py b/tests/test_report_parsing.py index d7ac9a7a..79c438df 100644 --- a/tests/test_report_parsing.py +++ b/tests/test_report_parsing.py @@ -1,9 +1,12 @@ import json import os import tempfile +import tomllib as toml from contextlib import contextmanager from pathlib import Path -from typing import Any, Dict, Iterator +from typing import Any, Dict, Iterator, Set + +import frontmatter # type: ignore[import-untyped] import run_community_analyzer @@ -37,6 +40,28 @@ def parse_single_artifact( os.remove(output_path) +def get_issue_codes_for_tool(report_tool: str) -> Set[str]: + """Return a set of valid issue codes for the given report tool.""" + issues = set() + issues_dir_path = Path.joinpath( + Path(__file__).parent.parent, f"analyzers/{report_tool}/.deepsource/issues" + ).as_posix() + for issue_file in os.listdir(issues_dir_path): + issue_code, ext = issue_file.split(".", 1) + if ext == "toml": + parser = toml + else: + parser = frontmatter + issue_file_path = os.path.join(issues_dir_path, issue_file) + with open(issue_file_path) as fp: + issue_data = parser.loads(fp.read()) + archived = issue_data.get("archived", False) + if not archived: + issues.add(issue_code) + + return issues + + def test_sarif_parser() -> None: """End to end test to make sure the SARIF parser throws no errors while parsing reports.""" # We parse all reports in `tests/fixtures/reports` and try to make a deepsource report out of it. @@ -46,7 +71,20 @@ def test_sarif_parser() -> None: reports = os.listdir(reports_base_dir) for report in reports: report_tool = report.removesuffix(".sarif") + active_issues = get_issue_codes_for_tool(report_tool) report_path = Path(reports_base_dir, report).as_posix() + with parse_single_artifact(report_path, report_tool) as result: assert result assert result["issues"] is not None + missing_ids = { + issue["issue_code"] for issue in result["issues"] + } - active_issues + + if missing_ids: + raise AssertionError( + f"{report_tool} report has {len(missing_ids)} missing issue " + f"code(s): {', '.join(missing_ids)}\n" + "Please make sure you add issue files for these issue codes in the " + "respective issues directory." + ) From dfd05e56c79eecd97ce17c52c2723453b7ae7318 Mon Sep 17 00:00:00 2001 From: Srijan Saurav <68371686+srijan-deepsource@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:39:41 +0530 Subject: [PATCH 5/6] fix: always raise issues in files sent for analysis (#15) --- run_community_analyzer.py | 23 ++++++++++- sarif-parser/src/sarif_parser/__init__.py | 15 +++++-- tests/test_community_analyzer.py | 41 ++++++++++++++++++- tests/test_duplicate_artifacts.py | 14 ++++++- tests/test_report_parsing.py | 25 +++++++++--- tests/testutils.py | 48 +++++++++++++++++++++++ 6 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 tests/testutils.py diff --git a/run_community_analyzer.py b/run_community_analyzer.py index f32a87ad..be722d24 100644 --- a/run_community_analyzer.py +++ b/run_community_analyzer.py @@ -1,4 +1,5 @@ import argparse +import json import os import os.path @@ -19,6 +20,23 @@ def get_issue_map(analyzer_name: str) -> str: return os.path.join(analyzers_dir, analyzer_name, "utils", "issue_map.json") +def get_files_to_analyze() -> set[str]: + """ + Read the analysis config to get the list of files to analyze. + Always raise issues only in these files. + """ + toolbox_path = os.getenv("TOOLBOX_PATH", "/toolbox") + analysis_config_path = os.path.join(toolbox_path, "analysis_config.json") + + if not os.path.exists(analysis_config_path): + raise ValueError(f"Could not find analysis config at {analysis_config_path}.") + + with open(analysis_config_path) as file: + analysis_config = json.load(file) + + return set(analysis_config["files"]) + + def main(argv: list[str] | None = None) -> None: """Runs the CLI.""" toolbox_path = os.getenv("TOOLBOX_PATH", "/toolbox") @@ -35,7 +53,10 @@ def main(argv: list[str] | None = None) -> None: analyzer_name = args.analyzer issue_map_path = get_issue_map(analyzer_name) - run_sarif_parser(artifacts_path, output_path, issue_map_path) + modified_files = get_files_to_analyze() + run_sarif_parser( + artifacts_path, output_path, issue_map_path, modified_files=modified_files + ) if __name__ == "__main__": diff --git a/sarif-parser/src/sarif_parser/__init__.py b/sarif-parser/src/sarif_parser/__init__.py index 3b37cb1c..e7b4679a 100644 --- a/sarif-parser/src/sarif_parser/__init__.py +++ b/sarif-parser/src/sarif_parser/__init__.py @@ -34,12 +34,15 @@ def parse( sarif_data: dict[str, Any], work_dir: str = "", issue_map: dict[str, Any] | None = None, + *, + modified_files: set[str] | None = None, ) -> list[Issue]: """Parses a SARIF file and returns a list of DeepSource issues.""" if issue_map is None: issue_map = {} deepsource_issues: list[Issue] = [] + for run in sarif_data["runs"]: for issue in run["results"]: assert len(issue["locations"]) == 1 @@ -52,6 +55,10 @@ def parse( # remove leading "/" if any issue_path = issue_path.removeprefix("/") + # Check if this issue is in the list of files to analyze + if modified_files is not None and issue_path not in modified_files: + continue + start_line = location.get("contextRegion", {}).get( "startLine" ) or location.get("region", {}).get("startLine") @@ -116,6 +123,8 @@ def run_sarif_parser( filepath: Union[str, os.PathLike[str]], output_path: Union[str, os.PathLike[str]], issue_map_path: str | None, + *, + modified_files: set[str] | None = None, ) -> None: """Parse SARIF files from given filepath, and save JSON output in output path.""" # Get list of sarif files @@ -157,11 +166,11 @@ def run_sarif_parser( if sarif_hash in artifact_hashes: # Skip this artifact, as it is a duplicate continue - else: - artifact_hashes.add(sarif_hash) + + artifact_hashes.add(sarif_hash) work_dir = artifact["metadata"]["work_dir"] - issues = parse(sarif_data, work_dir, issue_map) + issues = parse(sarif_data, work_dir, issue_map, modified_files=modified_files) deepsource_issues.extend(issues) issues_dict = { diff --git a/tests/test_community_analyzer.py b/tests/test_community_analyzer.py index caa45409..24486e52 100644 --- a/tests/test_community_analyzer.py +++ b/tests/test_community_analyzer.py @@ -2,6 +2,9 @@ import os from pathlib import Path +import pytest +from testutils import extract_filepaths_from_deepsource_json, temp_analysis_config + import run_community_analyzer expected_result = { @@ -183,10 +186,21 @@ def test_community_analyzer(tmp_path: Path) -> None: """Test for `run_community_analyzer.main()`, to test `issue_map.json` parsing.""" toolbox_path = tmp_path.as_posix() artifacts_path = os.path.join(os.path.dirname(__file__), "test_artifacts") - + analysis_config_path = os.path.join(toolbox_path, "analysis_config.json") + modified_files = extract_filepaths_from_deepsource_json(expected_result) os.environ["TOOLBOX_PATH"] = toolbox_path os.environ["ARTIFACTS_PATH"] = artifacts_path - run_community_analyzer.main(["--analyzer=kube-linter"]) + + # Case: when analysis config is not present, it should raise an error. + with pytest.raises(ValueError) as exe: + run_community_analyzer.main(["--analyzer=kube-linter"]) + assert ( + str(exe.value) == f"Could not find analysis config at {analysis_config_path}." + ) + + # Case: all files from the report are present in the analysis config. + with temp_analysis_config(analysis_config_path, modified_files): + run_community_analyzer.main(["--analyzer=kube-linter"]) analysis_results = tmp_path / "analysis_results.json" assert analysis_results.exists() @@ -195,3 +209,26 @@ def test_community_analyzer(tmp_path: Path) -> None: result = json.load(file) assert result == expected_result + + # Case: only a subset of files from the report are present in the analysis config. + # Note: There are 7 issues in this file in our report fixture. + # See `expected_result`. + modified_files = [ + "charts/runner/templates/tests/test-connection.yaml", + ] + with temp_analysis_config(analysis_config_path, modified_files): + run_community_analyzer.main(["--analyzer=kube-linter"]) + + analysis_results = tmp_path / "analysis_results.json" + assert analysis_results.exists() + + with open(analysis_results) as file: + result = json.load(file) + + assert len(result["issues"]) == 7 + + for issue in result["issues"]: + assert ( + issue["location"]["path"] + == "charts/runner/templates/tests/test-connection.yaml" + ) diff --git a/tests/test_duplicate_artifacts.py b/tests/test_duplicate_artifacts.py index 50549d92..53fc4bf4 100644 --- a/tests/test_duplicate_artifacts.py +++ b/tests/test_duplicate_artifacts.py @@ -5,6 +5,8 @@ from contextlib import contextmanager from typing import Any, Dict, Iterator +from testutils import extract_filepaths_from_sarif, temp_analysis_config + import run_community_analyzer @@ -38,8 +40,18 @@ def test_duplicate_artifacts(tmp_path: pathlib.Path) -> None: shutil.copy(artifact_path, artifacts_dir / "artifact_2") shutil.copy(artifact_path, artifacts_dir / "artifact_3") + # Extract filepaths from the sarif report to be used in the analysis config + with open(artifact_path) as fp: + data = json.load(fp) + sarif_data = json.loads(data["data"]) + modified_filepath = extract_filepaths_from_sarif(sarif_data) + + temp_analysis_config_path = os.path.join(toolbox_path, "analysis_config.json") + # Run the community analyzer on the artifact directory - with patch_env_values(toolbox_path, artifacts_dir): + with patch_env_values(toolbox_path, artifacts_dir), temp_analysis_config( + temp_analysis_config_path, modified_filepath + ): run_community_analyzer.main(["--analyzer=kube-linter"]) # Make sure there are no duplicates in the results diff --git a/tests/test_report_parsing.py b/tests/test_report_parsing.py index 79c438df..4c00e0e4 100644 --- a/tests/test_report_parsing.py +++ b/tests/test_report_parsing.py @@ -7,6 +7,7 @@ from typing import Any, Dict, Iterator, Set import frontmatter # type: ignore[import-untyped] +from testutils import extract_filepaths_from_sarif, temp_analysis_config import run_community_analyzer @@ -14,7 +15,7 @@ def make_artifact(report_path: str, workdir: str = "") -> str: """Return an artifact file for the given report, with the given workdir.""" artifact_path = tempfile.NamedTemporaryFile().name - # skipcq: PTC-W0064 # Report path is safe + # skipcq: PTC-W6004 # Report path is safe with open(report_path) as report_file: data = report_file.read() with open(artifact_path, "w") as artifact_file: @@ -26,13 +27,23 @@ def make_artifact(report_path: str, workdir: str = "") -> str: def parse_single_artifact( report_path: str, report_name: str ) -> Iterator[Dict[str, Any]]: - """Run community analyzer on a single artifact and return the deepsource result object.""" + """ + Run community analyzer on a single artifact and return the deepsource result object. + """ artifact_path = make_artifact(report_path) + artifact_filepaths = extract_filepaths_from_sarif( + json.loads(json.load(open(artifact_path))["data"]) + ) toolbox_path = tempfile.gettempdir() os.environ["ARTIFACTS_PATH"] = artifact_path os.environ["TOOLBOX_PATH"] = toolbox_path output_path = Path(toolbox_path, "analysis_results.json").as_posix() - run_community_analyzer.main([f"--analyzer={report_name}"]) + + with temp_analysis_config( + Path(toolbox_path, "analysis_config.json").as_posix(), artifact_filepaths + ): + run_community_analyzer.main([f"--analyzer={report_name}"]) + with open(output_path) as output_file: yield json.load(output_file) @@ -63,9 +74,11 @@ def get_issue_codes_for_tool(report_tool: str) -> Set[str]: def test_sarif_parser() -> None: - """End to end test to make sure the SARIF parser throws no errors while parsing reports.""" - # We parse all reports in `tests/fixtures/reports` and try to make a deepsource report out of it. - # There shouldn't be any errors while parsing the reports. + """ + End to end test to make sure the SARIF parser throws no errors while parsing reports. + """ + # We parse all reports in `tests/fixtures/reports` and try to make a deepsource + # report out of it. There shouldn't be any errors while parsing the reports. # All test reports are present in the `tests/fixtures/reports` directory. reports_base_dir = Path.joinpath(Path(__file__).parent, "fixtures", "reports") reports = os.listdir(reports_base_dir) diff --git a/tests/testutils.py b/tests/testutils.py new file mode 100644 index 00000000..28b85271 --- /dev/null +++ b/tests/testutils.py @@ -0,0 +1,48 @@ +import json +import os +from contextlib import contextmanager +from typing import Any, Iterator + + +def extract_filepaths_from_sarif(sarif: dict[str, Any]) -> list[str]: + """Extracts filepaths from a SARIF file.""" + filepaths = [] + for run in sarif["runs"]: + for result in run["results"]: + filepath = result["locations"][0]["physicalLocation"]["artifactLocation"][ + "uri" + ] + + filepaths.append(filepath) + + return filepaths + + +def extract_filepaths_from_deepsource_json( + deepsource_json: dict[str, Any] +) -> list[str]: + """Extracts filepaths from a DeepSource JSON file.""" + filepaths = [] + for issue in deepsource_json["issues"]: + filepaths.append(issue["location"]["path"]) + + return filepaths + + +@contextmanager +def temp_analysis_config( + config_path: str | os.PathLike[str], files: list[str] +) -> Iterator[None]: + """ + Prepare a minimal analysis config, by only populating `files` field and place it + in the provided config path. + + Delete the config when the scope of this context manager ends. + """ + # skipcq: PTC-W6004 + with open(config_path, "w") as file: + json.dump({"files": files}, file) + + yield + + os.remove(config_path) From d16981103db1fb26fdf860593a2132bb791e7b05 Mon Sep 17 00:00:00 2001 From: Eshaan Bansal Date: Wed, 22 Nov 2023 16:30:54 +0530 Subject: [PATCH 6/6] feat: add slither (#9) Slither: https://github.com/crytic/slither --------- Co-authored-by: Srijan Saurav <68371686+srijan-deepsource@users.noreply.github.com> --- README.md | 1 + .../.deepsource/analyzer/analyzer.toml | 7 + .../.deepsource/analyzer/example_config.toml | 5 + .../slither/.deepsource/analyzer/logo.svg | 16 + .../.deepsource/analyzer/silencers.json | 10 + .../.deepsource/issues/SLITHER-W1001.toml | 31 ++ .../.deepsource/issues/SLITHER-W1002.toml | 27 ++ .../.deepsource/issues/SLITHER-W1003.toml | 40 +++ .../.deepsource/issues/SLITHER-W1004.toml | 31 ++ .../.deepsource/issues/SLITHER-W1005.toml | 29 ++ .../.deepsource/issues/SLITHER-W1006.toml | 35 +++ .../.deepsource/issues/SLITHER-W1007.toml | 24 ++ .../.deepsource/issues/SLITHER-W1008.toml | 36 +++ .../.deepsource/issues/SLITHER-W1009.toml | 19 ++ .../.deepsource/issues/SLITHER-W1010.toml | 46 +++ .../.deepsource/issues/SLITHER-W1011.toml | 43 +++ .../.deepsource/issues/SLITHER-W1012.toml | 27 ++ .../.deepsource/issues/SLITHER-W1013.toml | 32 ++ .../.deepsource/issues/SLITHER-W1014.toml | 35 +++ .../.deepsource/issues/SLITHER-W1015.toml | 35 +++ .../.deepsource/issues/SLITHER-W1016.toml | 19 ++ .../.deepsource/issues/SLITHER-W1017.toml | 28 ++ .../.deepsource/issues/SLITHER-W1018.toml | 32 ++ .../.deepsource/issues/SLITHER-W1019.toml | 41 +++ .../.deepsource/issues/SLITHER-W1020.toml | 27 ++ .../.deepsource/issues/SLITHER-W1021.toml | 39 +++ .../.deepsource/issues/SLITHER-W1022.toml | 26 ++ .../.deepsource/issues/SLITHER-W1023.toml | 35 +++ .../.deepsource/issues/SLITHER-W1024.toml | 35 +++ .../.deepsource/issues/SLITHER-W1025.toml | 33 +++ .../.deepsource/issues/SLITHER-W1026.toml | 30 ++ .../.deepsource/issues/SLITHER-W1027.toml | 33 +++ .../.deepsource/issues/SLITHER-W1028.toml | 33 +++ .../.deepsource/issues/SLITHER-W1029.toml | 31 ++ .../.deepsource/issues/SLITHER-W1030.toml | 25 ++ .../.deepsource/issues/SLITHER-W1031.toml | 31 ++ .../.deepsource/issues/SLITHER-W1032.toml | 26 ++ .../.deepsource/issues/SLITHER-W1033.toml | 26 ++ .../.deepsource/issues/SLITHER-W1034.toml | 27 ++ .../.deepsource/issues/SLITHER-W1035.toml | 27 ++ .../.deepsource/issues/SLITHER-W1036.toml | 32 ++ .../.deepsource/issues/SLITHER-W1037.toml | 29 ++ .../.deepsource/issues/SLITHER-W1038.toml | 25 ++ .../.deepsource/issues/SLITHER-W1039.toml | 39 +++ .../.deepsource/issues/SLITHER-W1040.toml | 30 ++ .../.deepsource/issues/SLITHER-W1041.toml | 38 +++ .../.deepsource/issues/SLITHER-W1042.toml | 36 +++ .../.deepsource/issues/SLITHER-W1043.toml | 36 +++ .../.deepsource/issues/SLITHER-W1044.toml | 29 ++ .../.deepsource/issues/SLITHER-W1045.toml | 31 ++ .../.deepsource/issues/SLITHER-W1046.toml | 49 +++ .../.deepsource/issues/SLITHER-W1047.toml | 28 ++ .../.deepsource/issues/SLITHER-W1048.toml | 29 ++ .../.deepsource/issues/SLITHER-W1049.toml | 29 ++ .../.deepsource/issues/SLITHER-W1050.toml | 28 ++ .../.deepsource/issues/SLITHER-W1051.toml | 28 ++ .../.deepsource/issues/SLITHER-W1052.toml | 30 ++ .../.deepsource/issues/SLITHER-W1053.toml | 35 +++ .../.deepsource/issues/SLITHER-W1054.toml | 38 +++ .../.deepsource/issues/SLITHER-W1055.toml | 31 ++ .../.deepsource/issues/SLITHER-W1056.toml | 41 +++ .../.deepsource/issues/SLITHER-W1057.toml | 26 ++ .../.deepsource/issues/SLITHER-W1058.toml | 37 +++ .../.deepsource/issues/SLITHER-W1059.toml | 34 +++ .../.deepsource/issues/SLITHER-W1060.toml | 38 +++ .../.deepsource/issues/SLITHER-W1061.toml | 30 ++ .../.deepsource/issues/SLITHER-W1062.toml | 34 +++ .../.deepsource/issues/SLITHER-W1063.toml | 31 ++ .../.deepsource/issues/SLITHER-W1064.toml | 51 ++++ .../.deepsource/issues/SLITHER-W1065.toml | 51 ++++ .../.deepsource/issues/SLITHER-W1066.toml | 19 ++ .../.deepsource/issues/SLITHER-W1067.toml | 16 + .../.deepsource/issues/SLITHER-W1068.toml | 31 ++ .../.deepsource/issues/SLITHER-W1069.toml | 31 ++ .../.deepsource/issues/SLITHER-W1070.toml | 16 + .../.deepsource/issues/SLITHER-W1071.toml | 46 +++ .../.deepsource/issues/SLITHER-W1072.toml | 30 ++ .../.deepsource/issues/SLITHER-W1073.toml | 46 +++ .../.deepsource/issues/SLITHER-W1074.toml | 27 ++ .../.deepsource/issues/SLITHER-W1075.toml | 16 + .../.deepsource/issues/SLITHER-W1076.toml | 32 ++ .../.deepsource/issues/SLITHER-W1077.toml | 20 ++ .../.deepsource/issues/SLITHER-W1078.toml | 16 + .../.deepsource/issues/SLITHER-W1079.toml | 37 +++ .../.deepsource/issues/SLITHER-W1080.toml | 29 ++ .../.deepsource/issues/SLITHER-W1081.toml | 38 +++ .../.deepsource/issues/SLITHER-W1082.toml | 16 + .../.deepsource/issues/SLITHER-W1083.toml | 41 +++ .../.deepsource/issues/SLITHER-W1084.toml | 25 ++ .../.deepsource/issues/SLITHER-W1085.toml | 29 ++ .../.deepsource/issues/SLITHER-W1086.toml | 19 ++ .../.deepsource/issues/SLITHER-W1087.toml | 34 +++ .../.deepsource/issues/SLITHER-W1088.toml | 51 ++++ .../.deepsource/issues/SLITHER-W1089.toml | 16 + .../.deepsource/issues/SLITHER-W1090.toml | 16 + .../.deepsource/issues/SLITHER-W1091.toml | 16 + .../.deepsource/issues/SLITHER-W1092.toml | 28 ++ analyzers/slither/CI/github-actions.yaml | 49 +++ analyzers/slither/README.md | 3 + analyzers/slither/utils/__init__.py | 0 analyzers/slither/utils/constants.py | 42 +++ analyzers/slither/utils/detectors.py | 70 +++++ analyzers/slither/utils/issue_gen.py | 99 +++++++ analyzers/slither/utils/issue_map.json | 278 ++++++++++++++++++ analyzers/slither/utils/issue_map_gen.py | 56 ++++ sarif-parser/tests/sarif_files/slither.sarif | 219 ++++++++++++++ .../tests/sarif_files/slither.sarif.json | 104 +++++++ tests/fixtures/reports/slither.sarif | 219 ++++++++++++++ 108 files changed, 4036 insertions(+) create mode 100644 analyzers/slither/.deepsource/analyzer/analyzer.toml create mode 100644 analyzers/slither/.deepsource/analyzer/example_config.toml create mode 100644 analyzers/slither/.deepsource/analyzer/logo.svg create mode 100644 analyzers/slither/.deepsource/analyzer/silencers.json create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1001.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1002.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1003.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1004.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1005.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1006.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1007.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1008.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1009.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1010.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1011.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1012.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1013.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1014.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1015.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1016.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1017.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1018.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1019.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1020.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1021.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1022.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1023.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1024.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1025.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1026.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1027.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1028.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1029.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1030.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1031.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1032.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1033.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1034.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1035.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1036.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1037.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1038.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1039.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1040.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1041.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1042.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1043.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1044.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1045.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1046.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1047.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1048.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1049.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1050.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1051.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1052.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1053.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1054.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1055.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1056.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1057.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1058.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1059.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1060.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1061.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1062.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1063.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1064.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1065.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1066.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1067.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1068.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1069.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1070.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1071.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1072.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1073.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1074.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1075.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1076.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1077.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1078.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1079.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1080.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1081.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1082.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1083.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1084.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1085.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1086.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1087.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1088.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1089.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1090.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1091.toml create mode 100644 analyzers/slither/.deepsource/issues/SLITHER-W1092.toml create mode 100644 analyzers/slither/CI/github-actions.yaml create mode 100644 analyzers/slither/README.md create mode 100644 analyzers/slither/utils/__init__.py create mode 100644 analyzers/slither/utils/constants.py create mode 100644 analyzers/slither/utils/detectors.py create mode 100644 analyzers/slither/utils/issue_gen.py create mode 100644 analyzers/slither/utils/issue_map.json create mode 100644 analyzers/slither/utils/issue_map_gen.py create mode 100644 sarif-parser/tests/sarif_files/slither.sarif create mode 100644 sarif-parser/tests/sarif_files/slither.sarif.json create mode 100644 tests/fixtures/reports/slither.sarif diff --git a/README.md b/README.md index 32d0003f..af779afb 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Hub of all open-sourced third-party static analyzers supported by DeepSource. | [facebook/infer](https://github.com/facebook/infer) | v1.1.0 | Java, C++, Objective-C | | [Azure/bicep](https://github.com/Azure/bicep) | v0.20.4 | Azure Resource Manager | | [stackrox/kube-linter](https://github.com/stackrox/kube-linter) | 0.6.4 | Kubernetes, Helm | +| [crytic/slither](https://github.com/crytic/slither) | 0.10.0 | Solidity, Vyper | --- diff --git a/analyzers/slither/.deepsource/analyzer/analyzer.toml b/analyzers/slither/.deepsource/analyzer/analyzer.toml new file mode 100644 index 00000000..a250c3fe --- /dev/null +++ b/analyzers/slither/.deepsource/analyzer/analyzer.toml @@ -0,0 +1,7 @@ +# Analyzer Profile +category = "lang" +name = "Slither" +shortcode = "slither" +status = "active" +tool_latest_version = "0.10.0" +description = "Slither is a Solidity & Vyper static analysis framework developed by Crytic, a blockchain security group by Trail of Bits." diff --git a/analyzers/slither/.deepsource/analyzer/example_config.toml b/analyzers/slither/.deepsource/analyzer/example_config.toml new file mode 100644 index 00000000..98735d1f --- /dev/null +++ b/analyzers/slither/.deepsource/analyzer/example_config.toml @@ -0,0 +1,5 @@ +version = 1 + +[[analyzers]] +name = "slither" +type = "community" diff --git a/analyzers/slither/.deepsource/analyzer/logo.svg b/analyzers/slither/.deepsource/analyzer/logo.svg new file mode 100644 index 00000000..aa51f6f9 --- /dev/null +++ b/analyzers/slither/.deepsource/analyzer/logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/analyzers/slither/.deepsource/analyzer/silencers.json b/analyzers/slither/.deepsource/analyzer/silencers.json new file mode 100644 index 00000000..86351d0b --- /dev/null +++ b/analyzers/slither/.deepsource/analyzer/silencers.json @@ -0,0 +1,10 @@ +[ + { + "extension": ".sol$", + "comment_identifier": "//" + }, + { + "extension": ".vy$", + "comment_identifier": "#" + } +] \ No newline at end of file diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1001.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1001.toml new file mode 100644 index 00000000..338b221b --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1001.toml @@ -0,0 +1,31 @@ +title = "Storage abiencoderv2 array" +verbose_name = "abiencoderv2-array" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +`solc` versions `0.4.7`-`0.5.9` contain a [compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs) leading to incorrect ABI encoder usage. + + + +## Exploit Scenario + +```solidity +contract A { + uint[2][3] bad_arr = [[1, 2], [3, 4], [5, 6]]; + + /* Array of arrays passed to abi.encode is vulnerable */ + function bad() public { + bytes memory b = abi.encode(bad_arr); + } +} +``` +`abi.encode(bad_arr)` in a call to `bad()` will incorrectly encode the array as `[[1, 2], [2, 3], [3, 4]]` and lead to unintended behavior. + + +## Recommendation +Use a compiler >= `0.5.10`. + +## Learn more +[abiencoderv2-array](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-abiencoderv2-array) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1002.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1002.toml new file mode 100644 index 00000000..f199df3e --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1002.toml @@ -0,0 +1,27 @@ +title = "transferFrom uses arbitrary `from`" +verbose_name = "arbitrary-send-erc20" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect when `msg.sender` is not used as `from` in transferFrom. + + + +## Exploit Scenario + +```solidity +function a(address from, address to, uint256 amount) public { + erc20.transferFrom(from, to, am); +} +``` +Alice approves this contract to spend her ERC20 tokens. Bob can call `a` and specify Alice's address as the `from` parameter in `transferFrom`, allowing him to transfer Alice's tokens to himself. + +## Recommendation + +Use `msg.sender` as `from` in transferFrom. + + +## Learn more +[arbitrary-send-erc20](https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1003.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1003.toml new file mode 100644 index 00000000..7c225a8a --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1003.toml @@ -0,0 +1,40 @@ +title = "Modifying storage array by value" +verbose_name = "array-by-reference" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect arrays passed to a function that expects reference to a storage array + + + +## Exploit Scenario + +```solidity +contract Memory { + uint[1] public x; // storage + + function f() public { + f1(x); // update x + f2(x); // do not update x + } + + function f1(uint[1] storage arr) internal { // by reference + arr[0] = 1; + } + + function f2(uint[1] arr) internal { // by value + arr[0] = 2; + } +} +``` + +Bob calls `f()`. Bob assumes that at the end of the call `x[0]` is 2, but it is 1. +As a result, Bob's usage of the contract is incorrect. + +## Recommendation +Ensure the correct usage of `memory` and `storage` in the function parameters. Make all the locations explicit. + +## Learn more +[array-by-reference](https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1004.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1004.toml new file mode 100644 index 00000000..328eb232 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1004.toml @@ -0,0 +1,31 @@ +title = "ABI encodePacked Collision" +verbose_name = "encode-packed-collision" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect collision due to dynamic type usages in `abi.encodePacked` + + + +## Exploit Scenario + +```solidity +contract Sign { + function get_hash_for_signature(string name, string doc) external returns(bytes32) { + return keccak256(abi.encodePacked(name, doc)); + } +} +``` +Bob calls `get_hash_for_signature` with (`bob`, `This is the content`). The hash returned is used as an ID. +Eve creates a collision with the ID using (`bo`, `bThis is the content`) and compromises the system. + + +## Recommendation +Do not use more than one dynamic type in `abi.encodePacked()` +(see the [Solidity documentation](https://solidity.readthedocs.io/en/v0.5.10/abi-spec.html?highlight=abi.encodePacked#non-standard-packed-modeDynamic)). +Use `abi.encode()`, preferably. + +## Learn more +[encode-packed-collision](https://github.com/crytic/slither/wiki/Detector-Documentation#abi-encodePacked-collision) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1005.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1005.toml new file mode 100644 index 00000000..36bc1e07 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1005.toml @@ -0,0 +1,29 @@ +title = "The order of parameters in a shift instruction is incorrect" +verbose_name = "incorrect-shift" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect if the values in a shift operation are reversed + + + +## Exploit Scenario + +```solidity +contract C { + function f() internal returns (uint a) { + assembly { + a := shr(a, 8) + } + } +} +``` +The shift statement will right-shift the constant 8 by `a` bits + +## Recommendation +Swap the order of parameters. + +## Learn more +[incorrect-shift](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1006.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1006.toml new file mode 100644 index 00000000..08837f51 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1006.toml @@ -0,0 +1,35 @@ +title = "Multiple constructor schemes" +verbose_name = "multiple-constructors" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect multiple constructor definitions in the same contract (using new and old schemes). + + + +## Exploit Scenario + +```solidity +contract A { + uint x; + constructor() public { + x = 0; + } + function A() public { + x = 1; + } + + function test() public returns(uint) { + return x; + } +} +``` +In Solidity [0.4.22](https://github.com/ethereum/solidity/releases/tag/v0.4.23), a contract with both constructor schemes will compile. The first constructor will take precedence over the second, which may be unintended. + +## Recommendation +Only declare one constructor, preferably using the new scheme `constructor(...)` instead of `function (...)`. + +## Learn more +[multiple-constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1007.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1007.toml new file mode 100644 index 00000000..e33ac4b6 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1007.toml @@ -0,0 +1,24 @@ +title = "Contract's name reused" +verbose_name = "name-reused" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +If a codebase has two contracts the similar names, the compilation artifacts +will not contain one of the contracts with the duplicate name. + + + +## Exploit Scenario + +Bob's `truffle` codebase has two contracts named `ERC20`. +When `truffle compile` runs, only one of the two contracts will generate artifacts in `build/contracts`. +As a result, the second contract cannot be analyzed. + + +## Recommendation +Rename the contract. + +## Learn more +[name-reused](https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1008.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1008.toml new file mode 100644 index 00000000..62d1c473 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1008.toml @@ -0,0 +1,36 @@ +title = "Detected unprotected variables" +verbose_name = "protected-vars" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect unprotected variable that are marked protected + + + +## Exploit Scenario + +```solidity +contract Buggy{ + + /// @custom:security write-protection="onlyOwner()" + address owner; + + function set_protected() public onlyOwner(){ + owner = msg.sender; + } + + function set_not_protected() public{ + owner = msg.sender; + } +} +``` +`owner` must be always written by function using `onlyOwner` (`write-protection="onlyOwner()"`), however anyone can call `set_not_protected`. + + +## Recommendation +Add access controls to the vulnerable function + +## Learn more +[protected-vars](https://github.com/crytic/slither/wiki/Detector-Documentation#protected-variables) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1009.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1009.toml new file mode 100644 index 00000000..c282201d --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1009.toml @@ -0,0 +1,19 @@ +title = "Public mappings with nested variables" +verbose_name = "public-mappings-nested" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Prior to Solidity 0.5, a public mapping with nested structures returned [incorrect values](https://github.com/ethereum/solidity/issues/5520). + + + +## Exploit Scenario +Bob interacts with a contract that has a public mapping with nested structures. The values returned by the mapping are incorrect, breaking Bob's usage + +## Recommendation +Do not use public mapping with nested structures. + +## Learn more +[public-mappings-nested](https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1010.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1010.toml new file mode 100644 index 00000000..96e69765 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1010.toml @@ -0,0 +1,46 @@ +title = "Right-To-Left-Override control character is used" +verbose_name = "rtlo" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +An attacker can manipulate the logic of the contract by using a right-to-left-override character (`U+202E)`. + + + +## Exploit Scenario + +```solidity +contract Token +{ + + address payable o; // owner + mapping(address => uint) tokens; + + function withdraw() external returns(uint) + { + uint amount = tokens[msg.sender]; + address payable d = msg.sender; + tokens[msg.sender] = 0; + _withdraw(/*owner‮/*noitanitsed*/ d, o/*‭ + /*value */, amount); + } + + function _withdraw(address payable fee_receiver, address payable destination, uint value) internal + { + fee_receiver.transfer(1); + destination.transfer(value); + } +} +``` + +`Token` uses the right-to-left-override character when calling `_withdraw`. As a result, the fee is incorrectly sent to `msg.sender`, and the token balance is sent to the owner. + + + +## Recommendation +Special control characters must not be allowed. + +## Learn more +[rtlo](https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1011.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1011.toml new file mode 100644 index 00000000..44506f39 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1011.toml @@ -0,0 +1,43 @@ +title = "State variables shadowing" +verbose_name = "shadowing-state" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detection of state variables shadowed. + + + +## Exploit Scenario + +```solidity +contract BaseContract{ + address owner; + + modifier isOwner(){ + require(owner == msg.sender); + _; + } + +} + +contract DerivedContract is BaseContract{ + address owner; + + constructor(){ + owner = msg.sender; + } + + function withdraw() isOwner() external{ + msg.sender.transfer(this.balance); + } +} +``` +`owner` of `BaseContract` is never assigned and the modifier `isOwner` does not work. + +## Recommendation +Remove the state variable shadowing. + +## Learn more +[shadowing-state](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1012.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1012.toml new file mode 100644 index 00000000..b3c61251 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1012.toml @@ -0,0 +1,27 @@ +title = "Functions allowing anyone to destruct the contract" +verbose_name = "suicidal" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Unprotected call to a function executing `selfdestruct`/`suicide`. + + + +## Exploit Scenario + +```solidity +contract Suicidal{ + function kill() public{ + selfdestruct(msg.sender); + } +} +``` +Bob calls `kill` and destructs the contract. + +## Recommendation +Protect access to all sensitive functions. + +## Learn more +[suicidal](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1013.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1013.toml new file mode 100644 index 00000000..b9652144 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1013.toml @@ -0,0 +1,32 @@ +title = "Uninitialized state variables" +verbose_name = "uninitialized-state" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Uninitialized state variables. + + + +## Exploit Scenario + +```solidity +contract Uninitialized{ + address destination; + + function transfer() payable public{ + destination.transfer(msg.value); + } +} +``` +Bob calls `transfer`. As a result, the Ether are sent to the address `0x0` and are lost. + + +## Recommendation + +Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability. + + +## Learn more +[uninitialized-state](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1014.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1014.toml new file mode 100644 index 00000000..5c97f367 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1014.toml @@ -0,0 +1,35 @@ +title = "Uninitialized storage variables" +verbose_name = "uninitialized-storage" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +An uninitialized storage variable will act as a reference to the first state variable, and can override a critical variable. + + + +## Exploit Scenario + +```solidity +contract Uninitialized{ + address owner = msg.sender; + + struct St{ + uint a; + } + + function func() { + St st; + st.a = 0x0; + } +} +``` +Bob calls `func`. As a result, `owner` is overridden to `0`. + + +## Recommendation +Initialize all storage variables. + +## Learn more +[uninitialized-storage](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1015.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1015.toml new file mode 100644 index 00000000..ad004d5c --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1015.toml @@ -0,0 +1,35 @@ +title = "Unprotected upgradeable contract" +verbose_name = "unprotected-upgrade" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detects logic contract that can be destructed. + + + +## Exploit Scenario + +```solidity +contract Buggy is Initializable{ + address payable owner; + + function initialize() external initializer{ + require(owner == address(0)); + owner = msg.sender; + } + function kill() external{ + require(msg.sender == owner); + selfdestruct(owner); + } +} +``` +Buggy is an upgradeable contract. Anyone can call initialize on the logic contract, and destruct the contract. + + +## Recommendation +Add a constructor to ensure `initialize` cannot be called on the logic contract. + +## Learn more +[unprotected-upgrade](https://github.com/crytic/slither/wiki/Detector-Documentation#unprotected-upgradeable-contract) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1016.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1016.toml new file mode 100644 index 00000000..fafb5897 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1016.toml @@ -0,0 +1,19 @@ +title = "Use Codex to find vulnerabilities" +verbose_name = "codex" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Use [codex](https://openai.com/blog/openai-codex/) to find vulnerabilities + + + +## Exploit Scenario +N/A + +## Recommendation +Review codex's message. + +## Learn more +[codex](https://github.com/crytic/slither/wiki/Detector-Documentation#codex) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1017.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1017.toml new file mode 100644 index 00000000..70e84ce9 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1017.toml @@ -0,0 +1,28 @@ +title = "transferFrom uses arbitrary from with permit" +verbose_name = "arbitrary-send-erc20-permit" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect when `msg.sender` is not used as `from` in transferFrom and permit is used. + + + +## Exploit Scenario + +```solidity +function bad(address from, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s, address to) public { + erc20.permit(from, address(this), value, deadline, v, r, s); + erc20.transferFrom(from, to, value); +} +``` +If an ERC20 token does not implement permit and has a fallback function e.g. WETH, transferFrom allows an attacker to transfer all tokens approved for this contract. + +## Recommendation + +Ensure that the underlying ERC20 token correctly implements a permit function. + + +## Learn more +[arbitrary-send-erc20-permit](https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom-used-with-permit) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1018.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1018.toml new file mode 100644 index 00000000..5de155ac --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1018.toml @@ -0,0 +1,32 @@ +title = "Functions that send Ether to arbitrary destinations" +verbose_name = "arbitrary-send-eth" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Unprotected call to a function sending Ether to an arbitrary address. + + + +## Exploit Scenario + +```solidity +contract ArbitrarySendEth{ + address destination; + function setDestination(){ + destination = msg.sender; + } + + function withdraw() public{ + destination.transfer(this.balance); + } +} +``` +Bob calls `setDestination` and `withdraw`. As a result he withdraws the contract's balance. + +## Recommendation +Ensure that an arbitrary user cannot withdraw unauthorized funds. + +## Learn more +[arbitrary-send-eth](https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1019.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1019.toml new file mode 100644 index 00000000..0fd4e61f --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1019.toml @@ -0,0 +1,41 @@ +title = "Tainted array length assignment" +verbose_name = "controlled-array-length" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detects the direct assignment of an array's length. + + + +## Exploit Scenario + +```solidity +contract A { + uint[] testArray; // dynamic size array + + function f(uint usersCount) public { + // ... + testArray.length = usersCount; + // ... + } + + function g(uint userIndex, uint val) public { + // ... + testArray[userIndex] = val; + // ... + } +} +``` +Contract storage/state-variables are indexed by a 256-bit integer. +The user can set the array length to `2**256-1` in order to index all storage slots. +In the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired. +Note that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker. + +## Recommendation +Do not allow array lengths to be set directly set; instead, opt to add values as needed. +Otherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment. + +## Learn more +[controlled-array-length](https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1020.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1020.toml new file mode 100644 index 00000000..cd374be4 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1020.toml @@ -0,0 +1,27 @@ +title = "Controlled delegatecall destination" +verbose_name = "controlled-delegatecall" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +`Delegatecall` or `callcode` to an address controlled by the user. + + + +## Exploit Scenario + +```solidity +contract Delegatecall{ + function delegate(address to, bytes data){ + to.delegatecall(data); + } +} +``` +Bob calls `delegate` and delegates the execution to his malicious contract. As a result, Bob withdraws the funds of the contract and destructs it. + +## Recommendation +Avoid using `delegatecall`. Use only trusted destinations. + +## Learn more +[controlled-delegatecall](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1021.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1021.toml new file mode 100644 index 00000000..5fdadedf --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1021.toml @@ -0,0 +1,39 @@ +title = "Payable functions using `delegatecall` inside a loop" +verbose_name = "delegatecall-loop" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect the use of `delegatecall` inside a loop in a payable function. + + + +## Exploit Scenario + +```solidity +contract DelegatecallInLoop{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function addBalance(address a) public payable { + balances[a] += msg.value; + } + +} +``` +When calling `bad` the same `msg.value` amount will be accredited multiple times. + +## Recommendation + +Carefully check that the function called by `delegatecall` is not payable/doesn't use `msg.value`. + + +## Learn more +[delegatecall-loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1022.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1022.toml new file mode 100644 index 00000000..012ffc1e --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1022.toml @@ -0,0 +1,26 @@ +title = "Incorrect exponentiation" +verbose_name = "incorrect-exp" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect use of bitwise `xor ^` instead of exponential `**` + + + +## Exploit Scenario + +```solidity +contract Bug{ + uint UINT_MAX = 2^256 - 1; + ... +} +``` +Alice deploys a contract in which `UINT_MAX` incorrectly uses `^` operator instead of `**` for exponentiation + +## Recommendation +Use the correct operator `**` for exponentiation. + +## Learn more +[incorrect-exp](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-exponentiation) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1023.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1023.toml new file mode 100644 index 00000000..11b2bca0 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1023.toml @@ -0,0 +1,35 @@ +title = "If a `return` is incorrectly used in assembly mode" +verbose_name = "incorrect-return" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect if `return` in an assembly block halts unexpectedly the execution. + + + +## Exploit Scenario + +```solidity +contract C { + function f() internal returns (uint a, uint b) { + assembly { + return (5, 6) + } + } + + function g() returns (bool){ + f(); + return true; + } +} +``` +The return statement in `f` will cause execution in `g` to halt. +The function will return 6 bytes starting from offset 5, instead of returning a boolean. + +## Recommendation +Use the `leave` statement. + +## Learn more +[incorrect-return](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1024.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1024.toml new file mode 100644 index 00000000..4f76e229 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1024.toml @@ -0,0 +1,35 @@ +title = "msg.value inside a loop" +verbose_name = "msg-value-loop" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect the use of `msg.value` inside a loop. + + + +## Exploit Scenario + +```solidity +contract MsgValueInLoop{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i=0; i < receivers.length; i++) { + balances[receivers[i]] += msg.value; + } + } + +} +``` + + +## Recommendation + +Provide an explicit array of amounts alongside the receivers array, and check that the sum of all amounts matches `msg.value`. + + +## Learn more +[msg-value-loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1025.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1025.toml new file mode 100644 index 00000000..f6de48ce --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1025.toml @@ -0,0 +1,33 @@ +title = "Reentrancy vulnerabilities (theft of ethers)" +verbose_name = "reentrancy-eth" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ + +Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy). +Do not report reentrancies that don't involve Ether (see `reentrancy-no-eth`) + + + +## Exploit Scenario + +```solidity +function withdrawBalance(){ + // send userBalance[msg.sender] Ether to msg.sender + // if msg.sender is a contract, it will call its fallback function + if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){ + throw; + } + userBalance[msg.sender] = 0; +} +``` + +Bob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw more than its initial deposit to the contract. + +## Recommendation +Apply the [`check-effects-interactions pattern`](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy). + +## Learn more +[reentrancy-eth](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1026.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1026.toml new file mode 100644 index 00000000..04d4fbdf --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1026.toml @@ -0,0 +1,30 @@ +title = "If a `return` is used instead of a `leave`" +verbose_name = "return-leave" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Detect if a `return` is used where a `leave` should be used. + + + +## Exploit Scenario + +```solidity +contract C { + function f() internal returns (uint a, uint b) { + assembly { + return (5, 6) + } + } + +} +``` +The function will halt the execution, instead of returning a two uint. + +## Recommendation +Use the `leave` statement. + +## Learn more +[return-leave](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-assembly-return) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1027.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1027.toml new file mode 100644 index 00000000..a8dc2b13 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1027.toml @@ -0,0 +1,33 @@ +title = "Signed storage integer array compiler bug" +verbose_name = "storage-array" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +`solc` versions `0.4.7`-`0.5.9` contain [a compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs) +leading to incorrect values in signed integer arrays. + + + +## Exploit Scenario + +```solidity +contract A { + int[3] ether_balances; // storage signed integer array + function bad0() private { + // ... + ether_balances = [-1, -1, -1]; + // ... + } +} +``` +`bad0()` uses a (storage-allocated) signed integer array state variable to store the ether balances of three accounts. +`-1` is supposed to indicate uninitialized values but the Solidity bug makes these as `1`, which could be exploited by the accounts. + + +## Recommendation +Use a compiler version >= `0.5.10`. + +## Learn more +[storage-array](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1028.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1028.toml new file mode 100644 index 00000000..8fa437d3 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1028.toml @@ -0,0 +1,33 @@ +title = "Unchecked tokens transfer" +verbose_name = "unchecked-transfer" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +The return value of an external transfer/transferFrom call is not checked + + + +## Exploit Scenario + +```solidity +contract Token { + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); +} +contract MyBank{ + mapping(address => uint) balances; + Token token; + function deposit(uint amount) public{ + token.transferFrom(msg.sender, address(this), amount); + balances[msg.sender] += amount; + } +} +``` +Several tokens do not revert in case of failure and return false. If one of these tokens is used in `MyBank`, `deposit` will not revert if the transfer fails, and an attacker can call `deposit` for free.. + +## Recommendation +Use `SafeERC20`, or ensure that the transfer/transferFrom return value is checked. + +## Learn more +[unchecked-transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1029.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1029.toml new file mode 100644 index 00000000..23ddb848 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1029.toml @@ -0,0 +1,31 @@ +title = "Weak PRNG" +verbose_name = "weak-prng" +severity = "critical" +category = "antipattern" +weight = 80 +description = """ +Weak PRNG due to a modulo on `block.timestamp`, `now` or `blockhash`. These can be influenced by miners to some extent so they should be avoided. + + + +## Exploit Scenario + +```solidity +contract Game { + + uint reward_determining_number; + + function guessing() external{ + reward_determining_number = uint256(block.blockhash(10000)) % 10; + } +} +``` +Eve is a miner. Eve calls `guessing` and re-orders the block containing the transaction. +As a result, Eve wins the game. + +## Recommendation +Do not use `block.timestamp`, `now` or `blockhash` as a source of randomness + +## Learn more +[weak-prng](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1030.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1030.toml new file mode 100644 index 00000000..060f3dbf --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1030.toml @@ -0,0 +1,25 @@ +title = "Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()" +verbose_name = "domain-separator-collision" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +An ERC20 token has a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR(), causing unanticipated behavior for contracts using `permit` functionality. + + + +## Exploit Scenario + +```solidity +contract Contract{ + function some_collisions() external() {} +} +``` +`some_collision` clashes with EIP-2612's DOMAIN_SEPARATOR() and will interfere with contract's using `permit`. + +## Recommendation +Remove or rename the function that collides with DOMAIN_SEPARATOR(). + +## Learn more +[domain-separator-collision](https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1031.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1031.toml new file mode 100644 index 00000000..e0e57bd5 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1031.toml @@ -0,0 +1,31 @@ +title = "Detect dangerous enum conversion" +verbose_name = "enum-conversion" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Detect out-of-range `enum` conversion (`solc` < `0.4.5`). + + + +## Exploit Scenario + +```solidity +pragma solidity 0.4.2; +contract Test{ + + enum E{a} + + function bug(uint a) public returns(E){ + return E(a); + } +} +``` +Attackers can trigger unexpected behaviour by calling `bug(1)`. + +## Recommendation +Use a recent compiler version. If `solc` <`0.4.5` is required, check the `enum` conversion range. + +## Learn more +[enum-conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1032.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1032.toml new file mode 100644 index 00000000..b880969a --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1032.toml @@ -0,0 +1,26 @@ +title = "Incorrect ERC20 interfaces" +verbose_name = "erc20-interface" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Incorrect return values for `ERC20` functions. A contract compiled with Solidity > 0.4.22 interacting with these functions will fail to execute them, as the return value is missing. + + + +## Exploit Scenario + +```solidity +contract Token{ + function transfer(address to, uint value) external; + //... +} +``` +`Token.transfer` does not return a boolean. Bob deploys the token. Alice creates a contract that interacts with it but assumes a correct `ERC20` interface implementation. Alice's contract is unable to interact with Bob's contract. + +## Recommendation +Set the appropriate return values and types for the defined `ERC20` functions. + +## Learn more +[erc20-interface](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1033.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1033.toml new file mode 100644 index 00000000..43303948 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1033.toml @@ -0,0 +1,26 @@ +title = "Incorrect ERC721 interfaces" +verbose_name = "erc721-interface" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Incorrect return values for `ERC721` functions. A contract compiled with solidity > 0.4.22 interacting with these functions will fail to execute them, as the return value is missing. + + + +## Exploit Scenario + +```solidity +contract Token{ + function ownerOf(uint256 _tokenId) external view returns (bool); + //... +} +``` +`Token.ownerOf` does not return an address like `ERC721` expects. Bob deploys the token. Alice creates a contract that interacts with it but assumes a correct `ERC721` interface implementation. Alice's contract is unable to interact with Bob's contract. + +## Recommendation +Set the appropriate return values and vtypes for the defined `ERC721` functions. + +## Learn more +[erc721-interface](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1034.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1034.toml new file mode 100644 index 00000000..a790a767 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1034.toml @@ -0,0 +1,27 @@ +title = "Dangerous strict equalities" +verbose_name = "incorrect-equality" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Use of strict equalities that can be easily manipulated by an attacker. + + + +## Exploit Scenario + +```solidity +contract Crowdsale{ + function fund_reached() public returns(bool){ + return this.balance == 100 ether; + } +``` +`Crowdsale` relies on `fund_reached` to know when to stop the sale of tokens. +`Crowdsale` reaches 100 Ether. Bob sends 0.1 Ether. As a result, `fund_reached` is always false and the `crowdsale` never ends. + +## Recommendation +Don't use strict equality to determine if an account has enough Ether or tokens. + +## Learn more +[incorrect-equality](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1035.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1035.toml new file mode 100644 index 00000000..191a0d55 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1035.toml @@ -0,0 +1,27 @@ +title = "Contracts that lock ether" +verbose_name = "locked-ether" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Contract with a `payable` function, but without a withdrawal capacity. + + + +## Exploit Scenario + +```solidity +pragma solidity 0.4.24; +contract Locked{ + function receive() payable public{ + } +} +``` +Every Ether sent to `Locked` will be lost. + +## Recommendation +Remove the payable attribute or add a withdraw function. + +## Learn more +[locked-ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1036.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1036.toml new file mode 100644 index 00000000..94b49895 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1036.toml @@ -0,0 +1,32 @@ +title = "Deletion on mapping containing a structure" +verbose_name = "mapping-deletion" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +A deletion in a structure containing a mapping will not delete the mapping (see the [Solidity documentation](https://solidity.readthedocs.io/en/latest/types.html##delete)). The remaining data may be used to compromise the contract. + + + +## Exploit Scenario + +```solidity +struct BalancesStruct{ + address owner; + mapping(address => uint) balances; +} +mapping(address => BalancesStruct) public stackBalance; + +function remove() internal{ + delete stackBalance[msg.sender]; +} +``` +`remove` deletes an item of `stackBalance`. +The mapping `balances` is never deleted, so `remove` does not work as intended. + +## Recommendation +Use a lock mechanism instead of a deletion to disable structure containing a mapping. + +## Learn more +[mapping-deletion](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1037.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1037.toml new file mode 100644 index 00000000..42d7670b --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1037.toml @@ -0,0 +1,29 @@ +title = "State variables shadowing from abstract contracts" +verbose_name = "shadowing-abstract" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Detection of state variables shadowed from abstract contracts. + + + +## Exploit Scenario + +```solidity +contract BaseContract{ + address owner; +} + +contract DerivedContract is BaseContract{ + address owner; +} +``` +`owner` of `BaseContract` is shadowed in `DerivedContract`. + +## Recommendation +Remove the state variable shadowing. + +## Learn more +[shadowing-abstract](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1038.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1038.toml new file mode 100644 index 00000000..9b19713f --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1038.toml @@ -0,0 +1,25 @@ +title = "Comparing a variable to itself always returns true or false, depending on comparison" +verbose_name = "tautological-compare" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +A variable compared to itself is probably an error as it will always return `true` for `==`, `>=`, `<=` and always `false` for `<`, `>` and `!=`. + + + +## Exploit Scenario + +```solidity +function check(uint a) external returns(bool){ + return (a >= a); +} +``` +`check` always return true. + +## Recommendation +Remove comparison or compare to different value. + +## Learn more +[tautological-compare](https://github.com/crytic/slither/wiki/Detector-Documentation#tautological-compare) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1039.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1039.toml new file mode 100644 index 00000000..7758b600 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1039.toml @@ -0,0 +1,39 @@ +title = "Tautology or contradiction" +verbose_name = "tautology" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Detects expressions that are tautologies or contradictions. + + + +## Exploit Scenario + +```solidity +contract A { + function f(uint x) public { + // ... + if (x >= 0) { // bad -- always true + // ... + } + // ... + } + + function g(uint8 y) public returns (bool) { + // ... + return (y < 512); // bad! + // ... + } +} +``` +`x` is a `uint256`, so `x >= 0` will be always true. +`y` is a `uint8`, so `y <512` will be always true. + + +## Recommendation +Fix the incorrect comparison by changing the value type or the comparison. + +## Learn more +[tautology](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1040.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1040.toml new file mode 100644 index 00000000..1fa161ad --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1040.toml @@ -0,0 +1,30 @@ +title = "Unused write" +verbose_name = "write-after-write" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Detects variables that are written but never read and written again. + + + +## Exploit Scenario + +```solidity +contract Buggy{ + function my_func() external initializer{ + // ... + a = b; + a = c; + // .. + } +} +``` +`a` is first asigned to `b`, and then to `c`. As a result the first write does nothing. + +## Recommendation +Fix or remove the writes. + +## Learn more +[write-after-write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1041.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1041.toml new file mode 100644 index 00000000..ce1fb0e4 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1041.toml @@ -0,0 +1,38 @@ +title = "Misuse of Boolean constant" +verbose_name = "boolean-cst" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Detects the misuse of a Boolean constant. + + + +## Exploit Scenario + +```solidity +contract A { + function f(uint x) public { + // ... + if (false) { // bad! + // ... + } + // ... + } + + function g(bool b) public returns (bool) { + // ... + return (b || true); // bad! + // ... + } +} +``` +Boolean constants in code have only a few legitimate uses. +Other uses (in complex expressions, as conditionals) indicate either an error or, most likely, the persistence of faulty code. + +## Recommendation +Verify and simplify the condition. + +## Learn more +[boolean-cst](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1042.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1042.toml new file mode 100644 index 00000000..4236f639 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1042.toml @@ -0,0 +1,36 @@ +title = "Constant functions using assembly code" +verbose_name = "constant-function-asm" +severity = "major" +category = "antipattern" +weight = 60 +description = """ + +Functions declared as `constant`/`pure`/`view` using assembly code. + +`constant`/`pure`/`view` was not enforced prior to Solidity 0.5. +Starting from Solidity 0.5, a call to a `constant`/`pure`/`view` function uses the `STATICCALL` opcode, which reverts in case of state modification. + +As a result, a call to an [incorrectly labeled function may trap a contract compiled with Solidity 0.5](https://solidity.readthedocs.io/en/develop/050-breaking-changes.html#interoperability-with-older-contracts). + + + +## Exploit Scenario + +```solidity +contract Constant{ + uint counter; + function get() public view returns(uint){ + counter = counter +1; + return counter + } +} +``` +`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract that interacts with `Constant` in Solidity 0.5.0. +All the calls to `get` revert, breaking Bob's smart contract execution. + +## Recommendation +Ensure the attributes of contracts compiled prior to Solidity 0.5.0 are correct. + +## Learn more +[constant-function-asm](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1043.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1043.toml new file mode 100644 index 00000000..7ea6a1fd --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1043.toml @@ -0,0 +1,36 @@ +title = "Constant functions changing the state" +verbose_name = "constant-function-state" +severity = "major" +category = "antipattern" +weight = 60 +description = """ + +Functions declared as `constant`/`pure`/`view` change the state. + +`constant`/`pure`/`view` was not enforced prior to Solidity 0.5. +Starting from Solidity 0.5, a call to a `constant`/`pure`/`view` function uses the `STATICCALL` opcode, which reverts in case of state modification. + +As a result, a call to an [incorrectly labeled function may trap a contract compiled with Solidity 0.5](https://solidity.readthedocs.io/en/develop/050-breaking-changes.html#interoperability-with-older-contracts). + + + +## Exploit Scenario + +```solidity +contract Constant{ + uint counter; + function get() public view returns(uint){ + counter = counter +1; + return counter + } +} +``` +`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract that interacts with `Constant` in Solidity 0.5.0. +All the calls to `get` revert, breaking Bob's smart contract execution. + +## Recommendation +Ensure that attributes of contracts compiled prior to Solidity 0.5.0 are correct. + +## Learn more +[constant-function-state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1044.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1044.toml new file mode 100644 index 00000000..2bb8cb25 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1044.toml @@ -0,0 +1,29 @@ +title = "Imprecise arithmetic operations order" +verbose_name = "divide-before-multiply" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Solidity's integer division truncates. Thus, performing division before multiplication can lead to precision loss. + + + +## Exploit Scenario + +```solidity +contract A { + function f(uint n) public { + coins = (oldSupply / n) * interest; + } +} +``` +If `n` is greater than `oldSupply`, `coins` will be zero. For example, with `oldSupply = 5; n = 10, interest = 2`, coins will be zero. +If `(oldSupply * interest / n)` was used, `coins` would have been `1`. +In general, it's usually a good idea to re-arrange arithmetic to perform multiplication before division, unless the limit of a smaller type makes this dangerous. + +## Recommendation +Consider ordering multiplication before division. + +## Learn more +[divide-before-multiply](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1045.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1045.toml new file mode 100644 index 00000000..9578d51f --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1045.toml @@ -0,0 +1,31 @@ +title = "Reentrancy vulnerabilities (no theft of ethers)" +verbose_name = "reentrancy-no-eth" +severity = "major" +category = "antipattern" +weight = 60 +description = """ + +Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy). +Do not report reentrancies that involve Ether (see `reentrancy-eth`). + + + +## Exploit Scenario + +```solidity +function bug(){ + require(not_called); + if( ! (msg.sender.call() ) ){ + throw; + } + not_called = False; +} +``` + + +## Recommendation +Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy). + +## Learn more +[reentrancy-no-eth](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1046.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1046.toml new file mode 100644 index 00000000..014eea32 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1046.toml @@ -0,0 +1,49 @@ +title = "Reused base constructor" +verbose_name = "reused-constructor" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Detects if the same base constructor is called with arguments from two different locations in the same inheritance hierarchy. + + + +## Exploit Scenario + +```solidity +pragma solidity ^0.4.0; + +contract A{ + uint num = 5; + constructor(uint x) public{ + num += x; + } +} + +contract B is A{ + constructor() A(2) public { /* ... */ } +} + +contract C is A { + constructor() A(3) public { /* ... */ } +} + +contract D is B, C { + constructor() public { /* ... */ } +} + +contract E is B { + constructor() A(1) public { /* ... */ } +} +``` +The constructor of `A` is called multiple times in `D` and `E`: +- `D` inherits from `B` and `C`, both of which construct `A`. +- `E` only inherits from `B`, but `B` and `E` construct `A`. +. + +## Recommendation +Remove the duplicate constructor call. + +## Learn more +[reused-constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1047.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1047.toml new file mode 100644 index 00000000..a7c1d489 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1047.toml @@ -0,0 +1,28 @@ +title = "Dangerous usage of `tx.origin`" +verbose_name = "tx-origin" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +`tx.origin`-based protection can be abused by a malicious contract if a legitimate user interacts with the malicious contract. + + + +## Exploit Scenario + +```solidity +contract TxOrigin { + address owner = msg.sender; + + function bug() { + require(tx.origin == owner); + } +``` +Bob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls `TxOrigin` and bypasses the `tx.origin` protection. + +## Recommendation +Do not use `tx.origin` for authorization. + +## Learn more +[tx-origin](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1048.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1048.toml new file mode 100644 index 00000000..c1380921 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1048.toml @@ -0,0 +1,29 @@ +title = "Unchecked low-level calls" +verbose_name = "unchecked-lowlevel" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +The return value of a low-level call is not checked. + + + +## Exploit Scenario + +```solidity +contract MyConc{ + function my_func(address payable dst) public payable{ + dst.call.value(msg.value)(""); + } +} +``` +The return value of the low-level call is not checked, so if the call fails, the Ether will be locked in the contract. +If the low level is used to prevent blocking operations, consider logging failed calls. + + +## Recommendation +Ensure that the return value of a low-level call is checked or logged. + +## Learn more +[unchecked-lowlevel](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1049.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1049.toml new file mode 100644 index 00000000..0ab4d311 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1049.toml @@ -0,0 +1,29 @@ +title = "Unchecked send" +verbose_name = "unchecked-send" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +The return value of a `send` is not checked. + + + +## Exploit Scenario + +```solidity +contract MyConc{ + function my_func(address payable dst) public payable{ + dst.send(msg.value); + } +} +``` +The return value of `send` is not checked, so if the send fails, the Ether will be locked in the contract. +If `send` is used to prevent blocking operations, consider logging the failed `send`. + + +## Recommendation +Ensure that the return value of `send` is checked or logged. + +## Learn more +[unchecked-send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1050.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1050.toml new file mode 100644 index 00000000..e7ee685d --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1050.toml @@ -0,0 +1,28 @@ +title = "Uninitialized local variables" +verbose_name = "uninitialized-local" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +Uninitialized local variables. + + + +## Exploit Scenario + +```solidity +contract Uninitialized is Owner{ + function withdraw() payable public onlyOwner{ + address to; + to.transfer(this.balance) + } +} +``` +Bob calls `transfer`. As a result, all Ether is sent to the address `0x0` and is lost. + +## Recommendation +Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability. + +## Learn more +[uninitialized-local](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1051.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1051.toml new file mode 100644 index 00000000..5ae829ea --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1051.toml @@ -0,0 +1,28 @@ +title = "Unused return values" +verbose_name = "unused-return" +severity = "major" +category = "antipattern" +weight = 60 +description = """ +The return value of an external call is not stored in a local or state variable. + + + +## Exploit Scenario + +```solidity +contract MyConc{ + using SafeMath for uint; + function my_func(uint a, uint b) public{ + a.add(b); + } +} +``` +`MyConc` calls `add` of `SafeMath`, but does not store the result in `a`. As a result, the computation has no effect. + +## Recommendation +Ensure that all the return values of the function calls are used. + +## Learn more +[unused-return](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1052.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1052.toml new file mode 100644 index 00000000..b78ebfda --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1052.toml @@ -0,0 +1,30 @@ +title = "Modifiers that can return the default value" +verbose_name = "incorrect-modifier" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +If a modifier does not execute `_` or revert, the execution of the function will return the default value, which can be misleading for the caller. + + + +## Exploit Scenario + +```solidity +modidfier myModif(){ + if(..){ + _; + } +} +function get() myModif returns(uint){ + +} +``` +If the condition in `myModif` is false, the execution of `get()` will return 0. + +## Recommendation +All the paths in a modifier must execute `_` or revert. + +## Learn more +[incorrect-modifier](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1053.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1053.toml new file mode 100644 index 00000000..44e7587d --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1053.toml @@ -0,0 +1,35 @@ +title = "Built-in symbol shadowing" +verbose_name = "shadowing-builtin" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detection of shadowing built-in symbols using local variables, state variables, functions, modifiers, or events. + + + +## Exploit Scenario + +```solidity +pragma solidity ^0.4.24; + +contract Bug { + uint now; // Overshadows current time stamp. + + function assert(bool condition) public { + // Overshadows built-in symbol for providing assertions. + } + + function get_next_expiration(uint earlier_time) private returns (uint) { + return now + 259200; // References overshadowed timestamp. + } +} +``` +`now` is defined as a state variable, and shadows with the built-in symbol `now`. The function `assert` overshadows the built-in `assert` function. Any use of either of these built-in symbols may lead to unexpected results. + +## Recommendation +Rename the local variables, state variables, functions, modifiers, and events that shadow a builtin symbol. + +## Learn more +[shadowing-builtin](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1054.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1054.toml new file mode 100644 index 00000000..e2fea3fa --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1054.toml @@ -0,0 +1,38 @@ +title = "Local variables shadowing" +verbose_name = "shadowing-local" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detection of shadowing using local variables. + + + +## Exploit Scenario + +```solidity +pragma solidity ^0.4.24; + +contract Bug { + uint owner; + + function sensitive_function(address owner) public { + // ... + require(owner == msg.sender); + } + + function alternate_sensitive_function() public { + address owner = msg.sender; + // ... + require(owner == msg.sender); + } +} +``` +`sensitive_function.owner` shadows `Bug.owner`. As a result, the use of `owner` in `sensitive_function` might be incorrect. + +## Recommendation +Rename the local variables that shadow another component. + +## Learn more +[shadowing-local](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1055.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1055.toml new file mode 100644 index 00000000..7cda8461 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1055.toml @@ -0,0 +1,31 @@ +title = "Uninitialized function pointer calls in constructors" +verbose_name = "uninitialized-fptr-cst" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +solc versions `0.4.5`-`0.4.26` and `0.5.0`-`0.5.8` contain a compiler bug leading to unexpected behavior when calling uninitialized function pointers in constructors. + + + +## Exploit Scenario + +```solidity +contract bad0 { + + constructor() public { + /* Uninitialized function pointer */ + function(uint256) internal returns(uint256) a; + a(10); + } + +} +``` +The call to `a(10)` will lead to unexpected behavior because function pointer `a` is not initialized in the constructor. + +## Recommendation +Initialize function pointers before calling. Avoid function pointers if possible. + +## Learn more +[uninitialized-fptr-cst](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1056.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1056.toml new file mode 100644 index 00000000..222c9871 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1056.toml @@ -0,0 +1,41 @@ +title = "Local variables used prior their declaration" +verbose_name = "variable-scope" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detects the possible usage of a variable before the declaration is stepped over (either because it is later declared, or declared in another scope). + + + +## Exploit Scenario + +```solidity +contract C { + function f(uint z) public returns (uint) { + uint y = x + 9 + z; // 'z' is used pre-declaration + uint x = 7; + + if (z % 2 == 0) { + uint max = 5; + // ... + } + + // 'max' was intended to be 5, but it was mistakenly declared in a scope and not assigned (so it is zero). + for (uint i = 0; i < max; i++) { + x += 1; + } + + return x; + } +} +``` +In the case above, the variable `x` is used before its declaration, which may result in unintended consequences. +Additionally, the for-loop uses the variable `max`, which is declared in a previous scope that may not always be reached. This could lead to unintended consequences if the user mistakenly uses a variable prior to any intended declaration assignment. It also may indicate that the user intended to reference a different variable. + +## Recommendation +Move all variable declarations prior to any usage of the variable, and ensure that reaching a variable declaration does not depend on some conditional if it is used unconditionally. + +## Learn more +[variable-scope](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1057.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1057.toml new file mode 100644 index 00000000..fbe487a6 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1057.toml @@ -0,0 +1,26 @@ +title = "Constructor called not implemented" +verbose_name = "void-cst" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect the call to a constructor that is not implemented + + + +## Exploit Scenario + +```solidity +contract A{} +contract B is A{ + constructor() public A(){} +} +``` +When reading `B`'s constructor definition, we might assume that `A()` initiates the contract, but no code is executed. + +## Recommendation +Remove the constructor call. + +## Learn more +[void-cst](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1058.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1058.toml new file mode 100644 index 00000000..a293d6b0 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1058.toml @@ -0,0 +1,37 @@ +title = "Multiple calls in a loop" +verbose_name = "calls-loop" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Calls inside a loop might lead to a denial-of-service attack. + + + +## Exploit Scenario + +```solidity +contract CallsInLoop{ + + address[] destinations; + + constructor(address[] newDestinations) public{ + destinations = newDestinations; + } + + function bad() external{ + for (uint i=0; i < destinations.length; i++){ + destinations[i].transfer(i); + } + } + +} +``` +If one of the destinations has a fallback function that reverts, `bad` will always revert. + +## Recommendation +Favor [pull over push](https://github.com/ethereum/wiki/wiki/Safety#favor-pull-over-push-for-external-calls) strategy for external calls. + +## Learn more +[calls-loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1059.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1059.toml new file mode 100644 index 00000000..8133e626 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1059.toml @@ -0,0 +1,34 @@ +title = "Missing Events Access Control" +verbose_name = "events-access" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect missing events for critical access control parameters + + + +## Exploit Scenario + +```solidity +contract C { + + modifier onlyAdmin { + if (msg.sender != owner) throw; + _; + } + + function updateOwner(address newOwner) onlyAdmin external { + owner = newOwner; + } +} +``` +`updateOwner()` has no event, so it is difficult to track off-chain owner changes. + + +## Recommendation +Emit an event for critical parameter changes. + +## Learn more +[events-access](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1060.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1060.toml new file mode 100644 index 00000000..40317852 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1060.toml @@ -0,0 +1,38 @@ +title = "Missing Events Arithmetic" +verbose_name = "events-maths" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect missing events for critical arithmetic parameters. + + + +## Exploit Scenario + +```solidity +contract C { + + modifier onlyOwner { + if (msg.sender != owner) throw; + _; + } + + function setBuyPrice(uint256 newBuyPrice) onlyOwner public { + buyPrice = newBuyPrice; + } + + function buy() external { + ... // buyPrice is used to determine the number of tokens purchased + } +} +``` +`setBuyPrice()` does not emit an event, so it is difficult to track changes in the value of `buyPrice` off-chain. + + +## Recommendation +Emit an event for critical parameter changes. + +## Learn more +[events-maths](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1061.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1061.toml new file mode 100644 index 00000000..e11a297d --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1061.toml @@ -0,0 +1,30 @@ +title = "Dangerous unary expressions" +verbose_name = "incorrect-unary" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Unary expressions such as `x=+1` probably typos. + + + +## Exploit Scenario + +```Solidity +contract Bug{ + uint public counter; + + function increase() public returns(uint){ + counter=+1; + return counter; + } +} +``` +`increase()` uses `=+` instead of `+=`, so `counter` will never exceed 1. + +## Recommendation +Remove the unary expression. + +## Learn more +[incorrect-unary](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1062.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1062.toml new file mode 100644 index 00000000..0c4af81a --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1062.toml @@ -0,0 +1,34 @@ +title = "Missing Zero Address Validation" +verbose_name = "missing-zero-check" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect missing zero address validation. + + + +## Exploit Scenario + +```solidity +contract C { + + modifier onlyAdmin { + if (msg.sender != owner) throw; + _; + } + + function updateOwner(address newOwner) onlyAdmin external { + owner = newOwner; + } +} +``` +Bob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownership of the contract. + + +## Recommendation +Check that the address is not zero. + +## Learn more +[missing-zero-check](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1063.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1063.toml new file mode 100644 index 00000000..cade6fdc --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1063.toml @@ -0,0 +1,31 @@ +title = "Benign reentrancy vulnerabilities" +verbose_name = "reentrancy-benign" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ + +Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy). +Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentrancy-no-eth`). + + + +## Exploit Scenario + +```solidity +function callme(){ + if( ! (msg.sender.call()() ) ){ + throw; + } + counter += 1 +} +``` + +`callme` contains a reentrancy. The reentrancy is benign because it's exploitation would have the same effect as two consecutive calls. + +## Recommendation +Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy). + +## Learn more +[reentrancy-benign](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1064.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1064.toml new file mode 100644 index 00000000..e6a13a8c --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1064.toml @@ -0,0 +1,51 @@ +title = "Reentrancy vulnerabilities leading to out-of-order Events" +verbose_name = "reentrancy-events" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ + +Detects [reentrancies](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy) that allow manipulation of the order or value of events. + + + +## Exploit Scenario + +```solidity +contract ReentrantContract { + function f() external { + if (BugReentrancyEvents(msg.sender).counter() == 1) { + BugReentrancyEvents(msg.sender).count(this); + } + } +} +contract Counter { + uint public counter; + event Counter(uint); + +} +contract BugReentrancyEvents is Counter { + function count(ReentrantContract d) external { + counter += 1; + d.f(); + emit Counter(counter); + } +} +contract NoReentrancyEvents is Counter { + function count(ReentrantContract d) external { + counter += 1; + emit Counter(counter); + d.f(); + } +} +``` + +If the external call `d.f()` re-enters `BugReentrancyEvents`, the `Counter` events will be incorrect (`Counter(2)`, `Counter(2)`) whereas `NoReentrancyEvents` will correctly emit +(`Counter(1)`, `Counter(2)`). This may cause issues for offchain components that rely on the values of events e.g. checking for the amount deposited to a bridge. + +## Recommendation +Apply the [`check-effects-interactions` pattern](https://docs.soliditylang.org/en/latest/security-considerations.html#re-entrancy). + +## Learn more +[reentrancy-events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1065.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1065.toml new file mode 100644 index 00000000..dfe3362d --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1065.toml @@ -0,0 +1,51 @@ +title = "A low level callee may consume all callers gas unexpectedly" +verbose_name = "return-bomb" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +A low level callee may consume all callers gas unexpectedly. + + + +## Exploit Scenario + +```solidity +//Modified from https://github.com/nomad-xyz/ExcessivelySafeCall +contract BadGuy { + function youveActivateMyTrapCard() external pure returns (bytes memory) { + assembly{ + revert(0, 1000000) + } + } +} + +contract Mark { + function oops(address badGuy) public{ + bool success; + bytes memory ret; + + // Mark pays a lot of gas for this copy + //(success, ret) = badGuy.call{gas:10000}( + (success, ret) = badGuy.call( + abi.encodeWithSelector( + BadGuy.youveActivateMyTrapCard.selector + ) + ); + + // Mark may OOG here, preventing local state changes + //importantCleanup(); + } +} + +``` +After Mark calls BadGuy bytes are copied from returndata to memory, the memory expansion cost is paid. This means that when using a standard solidity call, the callee can "returnbomb" the caller, imposing an arbitrary gas cost. +Callee unexpectedly makes the caller OOG. + + +## Recommendation +Avoid unlimited implicit decoding of returndata. + +## Learn more +[return-bomb](https://github.com/crytic/slither/wiki/Detector-Documentation#return-bomb) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1066.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1066.toml new file mode 100644 index 00000000..24926176 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1066.toml @@ -0,0 +1,19 @@ +title = "Dangerous usage of `block.timestamp`" +verbose_name = "timestamp" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Dangerous usage of `block.timestamp`. `block.timestamp` can be manipulated by miners. + + + +## Exploit Scenario +"Bob's contract relies on `block.timestamp` for its randomness. Eve is a miner and manipulates `block.timestamp` to exploit Bob's contract. + +## Recommendation +Avoid relying on `block.timestamp`. + +## Learn more +[timestamp](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1067.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1067.toml new file mode 100644 index 00000000..05c37551 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1067.toml @@ -0,0 +1,16 @@ +title = "Assembly usage" +verbose_name = "assembly" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +The use of assembly is error-prone and should be avoided. + + + +## Recommendation +Do not use `evm` assembly. + +## Learn more +[assembly](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1068.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1068.toml new file mode 100644 index 00000000..117fbefe --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1068.toml @@ -0,0 +1,31 @@ +title = "Assert state change" +verbose_name = "assert-state-change" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Incorrect use of `assert()`. See Solidity best [practices](https://solidity.readthedocs.io/en/latest/control-structures.html#id4). + + + +## Exploit Scenario + +```solidity +contract A { + + uint s_a; + + function bad() public { + assert((s_a += 1) > 10); + } +} +``` +The assert in `bad()` increments the state variable `s_a` while checking for the condition. + + +## Recommendation +Use `require` for invariants modifying the state. + +## Learn more +[assert-state-change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1069.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1069.toml new file mode 100644 index 00000000..3d62c493 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1069.toml @@ -0,0 +1,31 @@ +title = "Comparison to boolean constant" +verbose_name = "boolean-equal" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detects the comparison to boolean constants. + + + +## Exploit Scenario + +```solidity +contract A { + function f(bool x) public { + // ... + if (x == true) { // bad! + // ... + } + // ... + } +} +``` +Boolean constants can be used directly and do not need to be compare to `true` or `false`. + +## Recommendation +Remove the equality to the boolean constant. + +## Learn more +[boolean-equal](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1070.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1070.toml new file mode 100644 index 00000000..7b1bb48b --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1070.toml @@ -0,0 +1,16 @@ +title = "Detects functions with high (> 11) cyclomatic complexity" +verbose_name = "cyclomatic-complexity" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detects functions with high (> 11) cyclomatic complexity. + + + +## Recommendation +Reduce cyclomatic complexity by splitting the function into several smaller subroutines. + +## Learn more +[cyclomatic-complexity](https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1071.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1071.toml new file mode 100644 index 00000000..d1eb24ff --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1071.toml @@ -0,0 +1,46 @@ +title = "Deprecated Solidity Standards" +verbose_name = "deprecated-standards" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect the usage of deprecated standards. + + + +## Exploit Scenario + +```solidity +contract ContractWithDeprecatedReferences { + // Deprecated: Change block.blockhash() -> blockhash() + bytes32 globalBlockHash = block.blockhash(0); + + // Deprecated: Change constant -> view + function functionWithDeprecatedThrow() public constant { + // Deprecated: Change msg.gas -> gasleft() + if(msg.gas == msg.value) { + // Deprecated: Change throw -> revert() + throw; + } + } + + // Deprecated: Change constant -> view + function functionWithDeprecatedReferences() public constant { + // Deprecated: Change sha3() -> keccak256() + bytes32 sha3Result = sha3("test deprecated sha3 usage"); + + // Deprecated: Change callcode() -> delegatecall() + address(this).callcode(); + + // Deprecated: Change suicide() -> selfdestruct() + suicide(address(0)); + } +} +``` + +## Recommendation +Replace all uses of deprecated symbols. + +## Learn more +[deprecated-standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1072.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1072.toml new file mode 100644 index 00000000..d158378a --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1072.toml @@ -0,0 +1,30 @@ +title = "Un-indexed ERC20 event parameters" +verbose_name = "erc20-indexed" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detects whether events defined by the `ERC20` specification that should have some parameters as `indexed` are missing the `indexed` keyword. + + + +## Exploit Scenario + +```solidity +contract ERC20Bad { + // ... + event Transfer(address from, address to, uint value); + event Approval(address owner, address spender, uint value); + + // ... +} +``` +`Transfer` and `Approval` events should have the 'indexed' keyword on their two first parameters, as defined by the `ERC20` specification. +Failure to include these keywords will exclude the parameter data in the transaction/block's bloom filter, so external tooling searching for these parameters may overlook them and fail to index logs from this token contract. + +## Recommendation +Add the `indexed` keyword to event parameters that should include it, according to the `ERC20` specification. + +## Learn more +[erc20-indexed](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1073.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1073.toml new file mode 100644 index 00000000..9b216898 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1073.toml @@ -0,0 +1,46 @@ +title = "Function initializing state variables" +verbose_name = "function-init-state" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detects the immediate initialization of state variables through function calls that are not pure/constant, or that use non-constant state variable. + + + +## Exploit Scenario + +```solidity +contract StateVarInitFromFunction { + + uint public v = set(); // Initialize from function (sets to 77) + uint public w = 5; + uint public x = set(); // Initialize from function (sets to 88) + address public shouldntBeReported = address(8); + + constructor(){ + // The constructor is run after all state variables are initialized. + } + + function set() public returns(uint) { + // If this function is being used to initialize a state variable declared + // before w, w will be zero. If it is declared after w, w will be set. + if(w == 0) { + return 77; + } + + return 88; + } +} +``` +In this case, users might intend a function to return a value a state variable can initialize with, without realizing the context for the contract is not fully initialized. +In the example above, the same function sets two different values for state variables because it checks a state variable that is not yet initialized in one case, and is initialized in the other. +Special care must be taken when initializing state variables from an immediate function call so as not to incorrectly assume the state is initialized. + + +## Recommendation +Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead. + +## Learn more +[function-init-state](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1074.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1074.toml new file mode 100644 index 00000000..021c09d5 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1074.toml @@ -0,0 +1,27 @@ +title = "Detects using-for statement usage when no function from a given library matches a given type" +verbose_name = "incorrect-using-for" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +In Solidity, it is possible to use libraries for certain types, by the `using-for` statement (`using for `). However, the Solidity compiler doesn't check whether a given library has at least one function matching a given type. If it doesn't, such a statement has no effect and may be confusing. + + + +## Exploit Scenario + +```solidity +library L { + function f(bool) public pure {} +} + +using L for uint; +``` +Such a code will compile despite the fact that `L` has no function with `uint` as its first argument. + +## Recommendation +Make sure that the libraries used in `using-for` statements have at least one function matching a type used in these statements. + +## Learn more +[incorrect-using-for](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-using-for-usage) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1075.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1075.toml new file mode 100644 index 00000000..6f9ffe30 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1075.toml @@ -0,0 +1,16 @@ +title = "Low level calls" +verbose_name = "low-level-calls" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +The use of low-level calls is error-prone. Low-level calls do not check for [code existence](https://solidity.readthedocs.io/en/v0.4.25/control-structures.html#error-handling-assert-require-revert-and-exceptions) or call success. + + + +## Recommendation +Avoid low-level calls. Check the call success. If the call is meant for a contract, check for code existence. + +## Learn more +[low-level-calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1076.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1076.toml new file mode 100644 index 00000000..2bd1e6fc --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1076.toml @@ -0,0 +1,32 @@ +title = "Missing inheritance" +verbose_name = "missing-inheritance" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect missing inheritance. + + + +## Exploit Scenario + +```solidity +interface ISomething { + function f1() external returns(uint); +} + +contract Something { + function f1() external returns(uint){ + return 42; + } +} +``` +`Something` should inherit from `ISomething`. + + +## Recommendation +Inherit from the missing interface or contract. + +## Learn more +[missing-inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1077.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1077.toml new file mode 100644 index 00000000..758b2844 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1077.toml @@ -0,0 +1,20 @@ +title = "Conformity to Solidity naming conventions" +verbose_name = "naming-convention" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ + +Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions) that should be followed. +#### Rule exceptions +- Allow constant variable name/symbol/decimals to be lowercase (`ERC20`). +- Allow `_` at the beginning of the `mixed_case` match for private variables and unused parameters. + + + +## Recommendation +Follow the Solidity [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions). + +## Learn more +[naming-convention](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1078.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1078.toml new file mode 100644 index 00000000..90cddaf6 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1078.toml @@ -0,0 +1,16 @@ +title = "If different pragma directives are used" +verbose_name = "pragma" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect whether different Solidity versions are used. + + + +## Recommendation +Use one Solidity version. + +## Learn more +[pragma](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1079.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1079.toml new file mode 100644 index 00000000..c2fc221a --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1079.toml @@ -0,0 +1,37 @@ +title = "Redundant statements" +verbose_name = "redundant-statements" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect the usage of redundant statements that have no effect. + + + +## Exploit Scenario + +```solidity +contract RedundantStatementsContract { + + constructor() public { + uint; // Elementary Type Name + bool; // Elementary Type Name + RedundantStatementsContract; // Identifier + } + + function test() public returns (uint) { + uint; // Elementary Type Name + assert; // Identifier + test; // Identifier + return 777; + } +} +``` +Each commented line references types/identifiers, but performs no action with them, so no code will be generated for such statements and they can be removed. + +## Recommendation +Remove redundant statements if they congest code but offer no value. + +## Learn more +[redundant-statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1080.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1080.toml new file mode 100644 index 00000000..44feb970 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1080.toml @@ -0,0 +1,29 @@ +title = "Incorrect Solidity version" +verbose_name = "solc-version" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ + +`solc` frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks. +We also recommend avoiding complex `pragma` statement. + + + +## Recommendation + +Deploy with any of the following Solidity versions: +- 0.8.18 + +The recommendations take into account: +- Risks related to recent releases +- Risks of complex code generation changes +- Risks of new language features +- Risks of known bugs + +Use a simple pragma version that allows any of these versions. +Consider using the latest version of Solidity for testing. + +## Learn more +[solc-version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1081.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1081.toml new file mode 100644 index 00000000..610e7d9a --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1081.toml @@ -0,0 +1,38 @@ +title = "Unimplemented functions" +verbose_name = "unimplemented-functions" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect functions that are not implemented on derived-most contracts. + + + +## Exploit Scenario + +```solidity +interface BaseInterface { + function f1() external returns(uint); + function f2() external returns(uint); +} + +interface BaseInterface2 { + function f3() external returns(uint); +} + +contract DerivedContract is BaseInterface, BaseInterface2 { + function f1() external returns(uint){ + return 42; + } +} +``` +`DerivedContract` does not implement `BaseInterface.f2` or `BaseInterface2.f3`. +As a result, the contract will not properly compile. +All unimplemented functions must be implemented on a contract that is meant to be used. + +## Recommendation +Implement all unimplemented functions in any contract you intend to use directly (not simply inherit from). + +## Learn more +[unimplemented-functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1082.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1082.toml new file mode 100644 index 00000000..f36dd132 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1082.toml @@ -0,0 +1,16 @@ +title = "Unused state variables" +verbose_name = "unused-state" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Unused state variable. + + + +## Recommendation +Remove unused state variables. + +## Learn more +[unused-state](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1083.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1083.toml new file mode 100644 index 00000000..ea56f798 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1083.toml @@ -0,0 +1,41 @@ +title = "Costly operations in a loop" +verbose_name = "costly-loop" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Costly operations inside a loop might waste gas, so optimizations are justified. + + + +## Exploit Scenario + +```solidity +contract CostlyOperationsInLoop{ + + uint loop_count = 100; + uint state_variable=0; + + function bad() external{ + for (uint i=0; i < loop_count; i++){ + state_variable++; + } + } + + function good() external{ + uint local_variable = state_variable; + for (uint i=0; i < loop_count; i++){ + local_variable++; + } + state_variable = local_variable; + } +} +``` +Incrementing `state_variable` in a loop incurs a lot of gas because of expensive `SSTOREs`, which might lead to an `out-of-gas`. + +## Recommendation +Use a local variable to hold the loop computation result. + +## Learn more +[costly-loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1084.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1084.toml new file mode 100644 index 00000000..d4901e59 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1084.toml @@ -0,0 +1,25 @@ +title = "Functions that are not used" +verbose_name = "dead-code" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Functions that are not sued. + + + +## Exploit Scenario + +```solidity +contract Contract{ + function dead_code() internal() {} +} +``` +`dead_code` is not used in the contract, and make the code's review more difficult. + +## Recommendation +Remove unused functions. + +## Learn more +[dead-code](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1085.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1085.toml new file mode 100644 index 00000000..4dd1fc84 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1085.toml @@ -0,0 +1,29 @@ +title = "Reentrancy vulnerabilities through send and transfer" +verbose_name = "reentrancy-unlimited-gas" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ + +Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy). +Only report reentrancy that is based on `transfer` or `send`. + + + +## Exploit Scenario + +```solidity +function callme(){ + msg.sender.transfer(balances[msg.sender]): + balances[msg.sender] = 0; +} +``` + +`send` and `transfer` do not protect from reentrancies in case of gas price changes. + +## Recommendation +Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy). + +## Learn more +[reentrancy-unlimited-gas](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1086.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1086.toml new file mode 100644 index 00000000..e64ae075 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1086.toml @@ -0,0 +1,19 @@ +title = "Variable names are too similar" +verbose_name = "similar-names" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ +Detect variables with names that are too similar. + + + +## Exploit Scenario +Bob uses several variables with similar names. As a result, his code is difficult to review. + +## Recommendation +Prevent variables from having similar names. + +## Learn more +[similar-names](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1087.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1087.toml new file mode 100644 index 00000000..e7f2d3c3 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1087.toml @@ -0,0 +1,34 @@ +title = "Conformance to numeric notation best practices" +verbose_name = "too-many-digits" +severity = "minor" +category = "antipattern" +weight = 40 +description = """ + +Literals with many digits are difficult to read and review. + + + + +## Exploit Scenario + +```solidity +contract MyContract{ + uint 1_ether = 10000000000000000000; +} +``` + +While `1_ether` looks like `1 ether`, it is `10 ether`. As a result, it's likely to be used incorrectly. + + +## Recommendation + +Use: +- [Ether suffix](https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#ether-units), +- [Time suffix](https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#time-units), or +- [The scientific notation](https://solidity.readthedocs.io/en/latest/types.html#rational-and-integer-literals) + + +## Learn more +[too-many-digits](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1088.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1088.toml new file mode 100644 index 00000000..0aa84f2a --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1088.toml @@ -0,0 +1,51 @@ +title = "Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it" +verbose_name = "cache-array-length" +severity = "major" +category = "performance" +weight = 60 +description = """ +Detects `for` loops that use `length` member of some storage array in their loop condition and don't modify it. + + + +## Exploit Scenario + +```solidity +contract C +{ + uint[] array; + + function f() public + { + for (uint i = 0; i < array.length; i++) + { + // code that does not modify length of `array` + } + } +} +``` +Since the `for` loop in `f` doesn't modify `array.length`, it is more gas efficient to cache it in some local variable and use that variable instead, like in the following example: + +```solidity +contract C +{ + uint[] array; + + function f() public + { + uint array_length = array.length; + for (uint i = 0; i < array_length; i++) + { + // code that does not modify length of `array` + } + } +} +``` + + +## Recommendation +Cache the lengths of storage arrays if they are used and not modified in `for` loops. + +## Learn more +[cache-array-length](https://github.com/crytic/slither/wiki/Detector-Documentation#cache-array-length) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1089.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1089.toml new file mode 100644 index 00000000..1231efd0 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1089.toml @@ -0,0 +1,16 @@ +title = "State variables that could be declared constant" +verbose_name = "constable-states" +severity = "major" +category = "performance" +weight = 60 +description = """ +State variables that are not updated following deployment should be declared constant to save gas. + + + +## Recommendation +Add the `constant` attribute to state variables that never change. + +## Learn more +[constable-states](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1090.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1090.toml new file mode 100644 index 00000000..daac9c27 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1090.toml @@ -0,0 +1,16 @@ +title = "Public function that could be declared external" +verbose_name = "external-function" +severity = "major" +category = "performance" +weight = 60 +description = """ +`public` functions that are never called by the contract should be declared `external`, and its immutable parameters should be located in `calldata` to save gas. + + + +## Recommendation +Use the `external` attribute for functions never called from the contract, and change the location of immutable parameters to `calldata` to save gas. + +## Learn more +[external-function](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1091.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1091.toml new file mode 100644 index 00000000..d99413b7 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1091.toml @@ -0,0 +1,16 @@ +title = "State variables that could be declared immutable" +verbose_name = "immutable-states" +severity = "major" +category = "performance" +weight = 60 +description = """ +State variables that are not updated following deployment should be declared immutable to save gas. + + + +## Recommendation +Add the `immutable` attribute to state variables that never change or are set only in the constructor. + +## Learn more +[immutable-states](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable) on Slither's wiki. +""" diff --git a/analyzers/slither/.deepsource/issues/SLITHER-W1092.toml b/analyzers/slither/.deepsource/issues/SLITHER-W1092.toml new file mode 100644 index 00000000..ba1cfbc0 --- /dev/null +++ b/analyzers/slither/.deepsource/issues/SLITHER-W1092.toml @@ -0,0 +1,28 @@ +title = "Contract reads its own variable using `this`" +verbose_name = "var-read-using-this" +severity = "major" +category = "performance" +weight = 60 +description = """ +The contract reads its own variable using `this`, adding overhead of an unnecessary STATICCALL. + + + +## Exploit Scenario + +```solidity +contract C { + mapping(uint => address) public myMap; + function test(uint x) external returns(address) { + return this.myMap(x); + } +} +``` + + +## Recommendation +Read the variable directly from storage instead of calling the contract. + +## Learn more +[var-read-using-this](https://github.com/crytic/slither/wiki/Detector-Documentation#public-variable-read-in-external-context) on Slither's wiki. +""" diff --git a/analyzers/slither/CI/github-actions.yaml b/analyzers/slither/CI/github-actions.yaml new file mode 100644 index 00000000..d621bb80 --- /dev/null +++ b/analyzers/slither/CI/github-actions.yaml @@ -0,0 +1,49 @@ +# ref: https://github.com/crytic/slither-action#how-to-use-1 +# A copy-paste Github Actions config to run Slither and report the artifact to DeepSource +name: Slither Analysis + +on: + # Note that both `push` and `pull_request` triggers should be present for GitHub to consistently present slither + # SARIF reports. + push: + branches: [ main, master ] + pull_request: + +jobs: + scan: + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + env: + DEEPSOURCE_DSN: ${{ secrets.DEEPSOURCE_DSN }} + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Run Slither + uses: crytic/slither-action@v0.3.0 + id: slither + with: + # The following is the latest version of slither-analyzer supported by DeepSource + slither-version: 0.10.0 + # The following makes slither produce scan analysis in SARIF format + sarif: ./slither.sarif + # required to let the SARIF upload step run even if Slither finds issues + continue-on-error: true + + - name: Upload SARIF report files to DeepSource + run: | + # Install the CLI + curl https://deepsource.io/cli | sh + + # Send the report to DeepSource + ./bin/deepsource report --analyzer slither --analyzer-type community --value-file ${{ steps.slither.outputs.sarif }} + + # Ensure the workflow eventually fails if files did not pass slither checks. + - name: Verify slither-action succeeded + shell: bash + run: | + echo "If this step fails, slither found issues. Check the output of the scan step above." + [[ "${{ steps.slither.outcome }}" == "success" ]] diff --git a/analyzers/slither/README.md b/analyzers/slither/README.md new file mode 100644 index 00000000..fdf96ee7 --- /dev/null +++ b/analyzers/slither/README.md @@ -0,0 +1,3 @@ +## community-analyzers/slither + +[crytic/slither](https://github.com/crytic/slither) \ No newline at end of file diff --git a/analyzers/slither/utils/__init__.py b/analyzers/slither/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/analyzers/slither/utils/constants.py b/analyzers/slither/utils/constants.py new file mode 100644 index 00000000..35f0ac3f --- /dev/null +++ b/analyzers/slither/utils/constants.py @@ -0,0 +1,42 @@ +import os + +from slither.detectors.abstract_detector import ( + DetectorClassification, + classification_txt, +) + +__all__ = [ + "ISSUE_MAP_FILE", + "ISSUE_PREFIX", + "DEEPSOURCE_SEVERITY_WEIGHT_MAP", + "SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_SEVERITY_MAP", + "SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_CATEGORY_MAP", +] + +# path to the `issue_map.json` located in the same directory as this script +ISSUE_MAP_FILE = os.path.join(os.path.dirname(__file__), "issue_map.json") +ISSUE_PREFIX = "SLITHER-W" + + +DEEPSOURCE_SEVERITY_WEIGHT_MAP = { + "minor": 40, + "major": 60, + "critical": 80, +} + + +SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_SEVERITY_MAP = { + classification_txt[DetectorClassification.LOW]: "minor", + classification_txt[DetectorClassification.MEDIUM]: "major", + classification_txt[DetectorClassification.HIGH]: "critical", + classification_txt[DetectorClassification.INFORMATIONAL]: "minor", + classification_txt[DetectorClassification.OPTIMIZATION]: "major", +} + +SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_CATEGORY_MAP = { + classification_txt[DetectorClassification.LOW]: "antipattern", + classification_txt[DetectorClassification.MEDIUM]: "antipattern", + classification_txt[DetectorClassification.HIGH]: "antipattern", + classification_txt[DetectorClassification.INFORMATIONAL]: "antipattern", + classification_txt[DetectorClassification.OPTIMIZATION]: "performance", +} diff --git a/analyzers/slither/utils/detectors.py b/analyzers/slither/utils/detectors.py new file mode 100644 index 00000000..09bf9a68 --- /dev/null +++ b/analyzers/slither/utils/detectors.py @@ -0,0 +1,70 @@ +import inspect +from typing import Dict, List, Type, TypedDict + +from slither.detectors import all_detectors +from slither.detectors.abstract_detector import AbstractDetector +from slither.utils.command_line import output_detectors_json + +__all__ = ["get_all_detector_classes", "get_all_detector_json"] + + +class DetectorJson(TypedDict): + """ + Represents a Slither detector. + ref: https://github.com/crytic/slither/blob/master/slither/utils/command_line.py#L368 + """ + + rule_id: str # custom param + index: int + check: str + title: str + impact: str + confidence: str + wiki_url: str + description: str + exploit_scenario: str + recommendation: str + + +def _gen_rule_id(detector_class: Type[AbstractDetector]) -> str: + """ + Generate unique rule ID for a Slither detector. + ref: https://github.com/crytic/slither/blob/master/slither/utils/output.py#L91-L97 + """ + impact = detector_class.IMPACT.value + confidence = detector_class.CONFIDENCE.value + check_name = detector_class.ARGUMENT + return f"{impact}-{confidence}-{check_name}" + + +def get_all_detector_classes() -> List[Type[AbstractDetector]]: + """ + Returns list of classes for all of Slither's detectors. + ref: https://github.com/crytic/slither/blob/master/tests/utils.py#L7 + """ + detectors = [getattr(all_detectors, name) for name in dir(all_detectors)] + return [ + d for d in detectors if inspect.isclass(d) and issubclass(d, AbstractDetector) + ] + + +def get_all_detector_json() -> List[Dict[str, DetectorJson]]: + """ + Returns list of `DetectorJson` dicts for all of Slither's detectors. + ref: https://github.com/crytic/slither/blob/master/slither/utils/command_line.py#L321 + """ + detectors_classes = get_all_detector_classes() + detectors_jsons = output_detectors_json(detectors_classes) + detector_class2json_map = { + next( + (d for d in detectors_classes if d.ARGUMENT == detector_json["check"]) + ): detector_json + for detector_json in detectors_jsons + } + return [ + { + **detector_json, + "rule_id": _gen_rule_id(detector_class), + } + for detector_class, detector_json in detector_class2json_map.items() + ] diff --git a/analyzers/slither/utils/issue_gen.py b/analyzers/slither/utils/issue_gen.py new file mode 100644 index 00000000..d08a50c7 --- /dev/null +++ b/analyzers/slither/utils/issue_gen.py @@ -0,0 +1,99 @@ +import os +from textwrap import dedent + +from constants import ( + DEEPSOURCE_SEVERITY_WEIGHT_MAP, + SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_CATEGORY_MAP, + SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_SEVERITY_MAP, +) +from detectors import get_all_detector_json +from issue_map_gen import generate_mapping, get_issue_map + + +def _get_toml_path(issue_code: str) -> str: + """Returns the file path to a issue toml for given `issue_code`.""" + return os.path.join( + os.path.dirname(os.path.dirname(__file__)), + f".deepsource/issues/{issue_code}.toml", + ) + + +def get_toml_content( + title: str, + verbose_name: str, + severity: str, + category: str, + weight: int, + description: str, + exploit_scenario: str, + recommendation: str, + learn_more: str, +) -> str: + """Return the content of the toml file.""" + exploit_scenario_section = ( + f"\n\n## Exploit Scenario\n{exploit_scenario}" if exploit_scenario else "" + ) + recommendation_section = ( + f"\n\n## Recommendation\n{recommendation}" if recommendation else "" + ) + learn_more_section = f"\n\n## Learn more\n{learn_more} on Slither's wiki." + + content = f'''title = "{title}" +verbose_name = "{verbose_name}" +severity = "{severity}" +category = "{category}" +weight = {weight} +description = """ +{description} + +{exploit_scenario_section}{recommendation_section}{learn_more_section} +""" + ''' + + return dedent(content) + + +def update_issue_tomls() -> None: + """Create issue toml files.""" + # Generates mapping if doesn't exist and then read it + generate_mapping() + mapping = get_issue_map() + + detectors = get_all_detector_json() + + # For each Slither detector, + # create a DeepSource equivalent .toml issue file + for detector in detectors: + rule_id = detector["rule_id"] + issue_code = mapping[rule_id]["issue_code"] + + filepath = _get_toml_path(issue_code) + + title = detector["title"].removesuffix(".") + check_name = detector["check"] + impact = detector["impact"] + wiki_url = detector["wiki_url"] + description = detector["description"] + exploit_scenario = dedent(detector["exploit_scenario"]) + recommendation = dedent(detector["recommendation"]) + severity = SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_SEVERITY_MAP[impact] + category = SLITHER_DETECTOR_CLASSIFICATION_DEEPSOURCE_CATEGORY_MAP[impact] + weight = DEEPSOURCE_SEVERITY_WEIGHT_MAP[severity] + + content = get_toml_content( + title=title, + verbose_name=check_name, + severity=severity, + category=category, + weight=weight, + description=description, + exploit_scenario=exploit_scenario, + recommendation=recommendation, + learn_more=f"[{check_name}]({wiki_url})", + ) + with open(filepath, "w") as f: + f.write(content) + + +if __name__ == "__main__": + update_issue_tomls() diff --git a/analyzers/slither/utils/issue_map.json b/analyzers/slither/utils/issue_map.json new file mode 100644 index 00000000..ad37f3d6 --- /dev/null +++ b/analyzers/slither/utils/issue_map.json @@ -0,0 +1,278 @@ +{ + "0-0-abiencoderv2-array": { + "issue_code": "SLITHER-W1001" + }, + "0-0-arbitrary-send-erc20": { + "issue_code": "SLITHER-W1002" + }, + "0-0-array-by-reference": { + "issue_code": "SLITHER-W1003" + }, + "0-0-encode-packed-collision": { + "issue_code": "SLITHER-W1004" + }, + "0-0-incorrect-shift": { + "issue_code": "SLITHER-W1005" + }, + "0-0-multiple-constructors": { + "issue_code": "SLITHER-W1006" + }, + "0-0-name-reused": { + "issue_code": "SLITHER-W1007" + }, + "0-0-protected-vars": { + "issue_code": "SLITHER-W1008" + }, + "0-0-public-mappings-nested": { + "issue_code": "SLITHER-W1009" + }, + "0-0-rtlo": { + "issue_code": "SLITHER-W1010" + }, + "0-0-shadowing-state": { + "issue_code": "SLITHER-W1011" + }, + "0-0-suicidal": { + "issue_code": "SLITHER-W1012" + }, + "0-0-uninitialized-state": { + "issue_code": "SLITHER-W1013" + }, + "0-0-uninitialized-storage": { + "issue_code": "SLITHER-W1014" + }, + "0-0-unprotected-upgrade": { + "issue_code": "SLITHER-W1015" + }, + "0-2-codex": { + "issue_code": "SLITHER-W1016" + }, + "0-1-arbitrary-send-erc20-permit": { + "issue_code": "SLITHER-W1017" + }, + "0-1-arbitrary-send-eth": { + "issue_code": "SLITHER-W1018" + }, + "0-1-controlled-array-length": { + "issue_code": "SLITHER-W1019" + }, + "0-1-controlled-delegatecall": { + "issue_code": "SLITHER-W1020" + }, + "0-1-delegatecall-loop": { + "issue_code": "SLITHER-W1021" + }, + "0-1-incorrect-exp": { + "issue_code": "SLITHER-W1022" + }, + "0-1-incorrect-return": { + "issue_code": "SLITHER-W1023" + }, + "0-1-msg-value-loop": { + "issue_code": "SLITHER-W1024" + }, + "0-1-reentrancy-eth": { + "issue_code": "SLITHER-W1025" + }, + "0-1-return-leave": { + "issue_code": "SLITHER-W1026" + }, + "0-1-storage-array": { + "issue_code": "SLITHER-W1027" + }, + "0-1-unchecked-transfer": { + "issue_code": "SLITHER-W1028" + }, + "0-1-weak-prng": { + "issue_code": "SLITHER-W1029" + }, + "1-0-domain-separator-collision": { + "issue_code": "SLITHER-W1030" + }, + "1-0-enum-conversion": { + "issue_code": "SLITHER-W1031" + }, + "1-0-erc20-interface": { + "issue_code": "SLITHER-W1032" + }, + "1-0-erc721-interface": { + "issue_code": "SLITHER-W1033" + }, + "1-0-incorrect-equality": { + "issue_code": "SLITHER-W1034" + }, + "1-0-locked-ether": { + "issue_code": "SLITHER-W1035" + }, + "1-0-mapping-deletion": { + "issue_code": "SLITHER-W1036" + }, + "1-0-shadowing-abstract": { + "issue_code": "SLITHER-W1037" + }, + "1-0-tautological-compare": { + "issue_code": "SLITHER-W1038" + }, + "1-0-tautology": { + "issue_code": "SLITHER-W1039" + }, + "1-0-write-after-write": { + "issue_code": "SLITHER-W1040" + }, + "1-1-boolean-cst": { + "issue_code": "SLITHER-W1041" + }, + "1-1-constant-function-asm": { + "issue_code": "SLITHER-W1042" + }, + "1-1-constant-function-state": { + "issue_code": "SLITHER-W1043" + }, + "1-1-divide-before-multiply": { + "issue_code": "SLITHER-W1044" + }, + "1-1-reentrancy-no-eth": { + "issue_code": "SLITHER-W1045" + }, + "1-1-reused-constructor": { + "issue_code": "SLITHER-W1046" + }, + "1-1-tx-origin": { + "issue_code": "SLITHER-W1047" + }, + "1-1-unchecked-lowlevel": { + "issue_code": "SLITHER-W1048" + }, + "1-1-unchecked-send": { + "issue_code": "SLITHER-W1049" + }, + "1-1-uninitialized-local": { + "issue_code": "SLITHER-W1050" + }, + "1-1-unused-return": { + "issue_code": "SLITHER-W1051" + }, + "2-0-incorrect-modifier": { + "issue_code": "SLITHER-W1052" + }, + "2-0-shadowing-builtin": { + "issue_code": "SLITHER-W1053" + }, + "2-0-shadowing-local": { + "issue_code": "SLITHER-W1054" + }, + "2-0-uninitialized-fptr-cst": { + "issue_code": "SLITHER-W1055" + }, + "2-0-variable-scope": { + "issue_code": "SLITHER-W1056" + }, + "2-0-void-cst": { + "issue_code": "SLITHER-W1057" + }, + "2-1-calls-loop": { + "issue_code": "SLITHER-W1058" + }, + "2-1-events-access": { + "issue_code": "SLITHER-W1059" + }, + "2-1-events-maths": { + "issue_code": "SLITHER-W1060" + }, + "2-1-incorrect-unary": { + "issue_code": "SLITHER-W1061" + }, + "2-1-missing-zero-check": { + "issue_code": "SLITHER-W1062" + }, + "2-1-reentrancy-benign": { + "issue_code": "SLITHER-W1063" + }, + "2-1-reentrancy-events": { + "issue_code": "SLITHER-W1064" + }, + "2-1-return-bomb": { + "issue_code": "SLITHER-W1065" + }, + "2-1-timestamp": { + "issue_code": "SLITHER-W1066" + }, + "3-0-assembly": { + "issue_code": "SLITHER-W1067" + }, + "3-0-assert-state-change": { + "issue_code": "SLITHER-W1068" + }, + "3-0-boolean-equal": { + "issue_code": "SLITHER-W1069" + }, + "3-0-cyclomatic-complexity": { + "issue_code": "SLITHER-W1070" + }, + "3-0-deprecated-standards": { + "issue_code": "SLITHER-W1071" + }, + "3-0-erc20-indexed": { + "issue_code": "SLITHER-W1072" + }, + "3-0-function-init-state": { + "issue_code": "SLITHER-W1073" + }, + "3-0-incorrect-using-for": { + "issue_code": "SLITHER-W1074" + }, + "3-0-low-level-calls": { + "issue_code": "SLITHER-W1075" + }, + "3-0-missing-inheritance": { + "issue_code": "SLITHER-W1076" + }, + "3-0-naming-convention": { + "issue_code": "SLITHER-W1077" + }, + "3-0-pragma": { + "issue_code": "SLITHER-W1078" + }, + "3-0-redundant-statements": { + "issue_code": "SLITHER-W1079" + }, + "3-0-solc-version": { + "issue_code": "SLITHER-W1080" + }, + "3-0-unimplemented-functions": { + "issue_code": "SLITHER-W1081" + }, + "3-0-unused-state": { + "issue_code": "SLITHER-W1082" + }, + "3-1-costly-loop": { + "issue_code": "SLITHER-W1083" + }, + "3-1-dead-code": { + "issue_code": "SLITHER-W1084" + }, + "3-1-reentrancy-unlimited-gas": { + "issue_code": "SLITHER-W1085" + }, + "3-1-similar-names": { + "issue_code": "SLITHER-W1086" + }, + "3-1-too-many-digits": { + "issue_code": "SLITHER-W1087" + }, + "4-0-cache-array-length": { + "issue_code": "SLITHER-W1088" + }, + "4-0-constable-states": { + "issue_code": "SLITHER-W1089" + }, + "4-0-external-function": { + "issue_code": "SLITHER-W1090" + }, + "4-0-immutable-states": { + "issue_code": "SLITHER-W1091" + }, + "4-0-var-read-using-this": { + "issue_code": "SLITHER-W1092" + } +} \ No newline at end of file diff --git a/analyzers/slither/utils/issue_map_gen.py b/analyzers/slither/utils/issue_map_gen.py new file mode 100644 index 00000000..a25d5b0b --- /dev/null +++ b/analyzers/slither/utils/issue_map_gen.py @@ -0,0 +1,56 @@ +import itertools +import json +from typing import Dict, Generator + +from constants import ISSUE_MAP_FILE, ISSUE_PREFIX +from detectors import get_all_detector_json + +__all__ = ["get_issue_map", "generate_mapping"] + + +def _get_next_code(mapping: Dict[str, Dict[str, str]]) -> Generator[int]: + """Return the next available issue code.""" + num_issues = len(mapping.keys()) # get the number of issues already in the mapping + next_code = 1001 + num_issues # issue code series starts from `1001` + yield from itertools.count(next_code) + + +def get_issue_map() -> Dict[str, Dict[str, str]]: + """Return the issue map.""" + with open(ISSUE_MAP_FILE, "r") as f: + return json.load(f) + + +def get_mapping() -> Dict[str, Dict[str, str]]: + """Generates and returns a dict mapping of DeepSource assigned issue codes to Slither's detector names.""" + # Example mapping: + # { + # "0-0-abiencoderv2-array": {"issue_code": "SLITHER-W0001"}, + # } + issue_map = get_issue_map() + generate_code = _get_next_code(issue_map) + detectors = get_all_detector_json() + + if len(detectors) > len(issue_map): + # if the no. of issues in the mapping is less than the no. of detectors, + # then generate the mapping only for the new detectors + for detector in detectors: + if detector["rule_id"] not in issue_map: + next_code = next(generate_code) + issue_map[detector["rule_id"]] = { + "issue_code": f"{ISSUE_PREFIX}{next_code}" + } + + return issue_map + + +def generate_mapping() -> None: + """Generates and dumps a dict mapping of DeepSource assigned issue codes to Slither's detector names in `issue_map.json` file.""" + issue_map = get_mapping() + # dump mapping into file + with open(ISSUE_MAP_FILE, "w") as f: + json.dump(issue_map, f, indent=4) + + +if __name__ == "__main__": + generate_mapping() diff --git a/sarif-parser/tests/sarif_files/slither.sarif b/sarif-parser/tests/sarif_files/slither.sarif new file mode 100644 index 00000000..2384b665 --- /dev/null +++ b/sarif-parser/tests/sarif_files/slither.sarif @@ -0,0 +1,219 @@ +{ + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Slither", + "informationUri": "https://github.com/crytic/slither", + "version": "0.10.0", + "rules": [ + { + "id": "0-0-uninitialized-state", + "name": "uninitialized-state", + "properties": { + "precision": "very-high", + "security-severity": "8.0" + }, + "shortDescription": { + "text": "Uninitialized state variables" + }, + "help": { + "text": "\nInitialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability.\n" + } + }, + { + "id": "3-0-solc-version", + "name": "solc-version", + "properties": { + "precision": "very-high", + "security-severity": "0.0" + }, + "shortDescription": { + "text": "Incorrect versions of Solidity" + }, + "help": { + "text": "\nDeploy with any of the following Solidity versions:\n- 0.8.18\n\nThe recommendations take into account:\n- Risks related to recent releases\n- Risks of complex code generation changes\n- Risks of new language features\n- Risks of known bugs\n\nUse a simple pragma version that allows any of these versions.\nConsider using the latest version of Solidity for testing." + } + }, + { + "id": "3-0-naming-convention", + "name": "naming-convention", + "properties": { + "precision": "very-high", + "security-severity": "0.0" + }, + "shortDescription": { + "text": "Conformance to Solidity naming conventions" + }, + "help": { + "text": "Follow the Solidity [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions)." + } + }, + { + "id": "4-0-constable-states", + "name": "constable-states", + "properties": { + "precision": "very-high", + "security-severity": "0.0" + }, + "shortDescription": { + "text": "State variables that could be declared constant" + }, + "help": { + "text": "Add the `constant` attribute to state variables that never change." + } + } + ] + } + }, + "results": [ + { + "ruleId": "0-0-uninitialized-state", + "message": { + "text": "ERC20Buggy._totalSupply (ERC20.sol#4) is never initialized. It is used in:\n\t- ERC20Buggy.totalSupply() (ERC20.sol#37-39)\n", + "markdown": "[ERC20Buggy._totalSupply](ERC20.sol#L4) is never initialized. It is used in:\n\t- [ERC20Buggy.totalSupply()](ERC20.sol#L37-L39)\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 4, + "endLine": 4 + } + } + } + ], + "partialFingerprints": { + "id": "7b17182a44bd3c13866e3e4e585393fc09a25a2e6715512184572d49f8bf8df5" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Variable ERC20Buggy._balanceOf (ERC20.sol#5) is not in mixedCase\n", + "markdown": "Variable [ERC20Buggy._balanceOf](ERC20.sol#L5) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 5, + "endLine": 5 + } + } + } + ], + "partialFingerprints": { + "id": "02e6097efd3009dcc27b8a5527eebbc4721e969ab7956639b08a21eee86c73b7" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Variable ERC20Buggy._allowance (ERC20.sol#6) is not in mixedCase\n", + "markdown": "Variable [ERC20Buggy._allowance](ERC20.sol#L6) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 6, + "endLine": 6 + } + } + } + ], + "partialFingerprints": { + "id": "6032a0270bf2adbbcd0067c061e63c3a73c6f09d90d0a46cad330394988cb9b9" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Parameter ERC20Buggy.approve(address,uint256)._spender (ERC20.sol#24) is not in mixedCase\n", + "markdown": "Parameter [ERC20Buggy.approve(address,uint256)._spender](ERC20.sol#L24) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 24, + "endLine": 24 + } + } + } + ], + "partialFingerprints": { + "id": "6b595b8907c5207c1885cc0ac0852e8ccbda8f149c200fc6b584ad003187fc2c" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Variable ERC20Buggy._totalSupply (ERC20.sol#4) is not in mixedCase\n", + "markdown": "Variable [ERC20Buggy._totalSupply](ERC20.sol#L4) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 4, + "endLine": 4 + } + } + } + ], + "partialFingerprints": { + "id": "9a6a5111def54fca1801e2b40299e74a855a80a7813ffdb0d19ee923cc1f032f" + } + }, + { + "ruleId": "4-0-constable-states", + "message": { + "text": "ERC20Buggy._totalSupply (ERC20.sol#4) should be constant \n", + "markdown": "[ERC20Buggy._totalSupply](ERC20.sol#L4) should be constant \n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 4, + "endLine": 4 + } + } + } + ], + "partialFingerprints": { + "id": "f6a9d2e5c554c22bd038ce28139c911c7a0893017d8e9054cbaaf6a084b71c39" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/sarif-parser/tests/sarif_files/slither.sarif.json b/sarif-parser/tests/sarif_files/slither.sarif.json new file mode 100644 index 00000000..93a2375e --- /dev/null +++ b/sarif-parser/tests/sarif_files/slither.sarif.json @@ -0,0 +1,104 @@ +[ + { + "issue_code": "0-0-uninitialized-state", + "issue_text": "ERC20Buggy._totalSupply (ERC20.sol#4) is never initialized. It is used in:\n\t- ERC20Buggy.totalSupply() (ERC20.sol#37-39)\n", + "location": { + "path": "ERC20.sol", + "position": { + "begin": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 1 + } + } + } + }, + { + "issue_code": "3-0-naming-convention", + "issue_text": "Variable ERC20Buggy._balanceOf (ERC20.sol#5) is not in mixedCase\n", + "location": { + "path": "ERC20.sol", + "position": { + "begin": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 1 + } + } + } + }, + { + "issue_code": "3-0-naming-convention", + "issue_text": "Variable ERC20Buggy._allowance (ERC20.sol#6) is not in mixedCase\n", + "location": { + "path": "ERC20.sol", + "position": { + "begin": { + "line": 6, + "column": 1 + }, + "end": { + "line": 6, + "column": 1 + } + } + } + }, + { + "issue_code": "3-0-naming-convention", + "issue_text": "Parameter ERC20Buggy.approve(address,uint256)._spender (ERC20.sol#24) is not in mixedCase\n", + "location": { + "path": "ERC20.sol", + "position": { + "begin": { + "line": 24, + "column": 1 + }, + "end": { + "line": 24, + "column": 1 + } + } + } + }, + { + "issue_code": "3-0-naming-convention", + "issue_text": "Variable ERC20Buggy._totalSupply (ERC20.sol#4) is not in mixedCase\n", + "location": { + "path": "ERC20.sol", + "position": { + "begin": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 1 + } + } + } + }, + { + "issue_code": "4-0-constable-states", + "issue_text": "ERC20Buggy._totalSupply (ERC20.sol#4) should be constant \n", + "location": { + "path": "ERC20.sol", + "position": { + "begin": { + "line": 4, + "column": 1 + }, + "end": { + "line": 4, + "column": 1 + } + } + } + } +] \ No newline at end of file diff --git a/tests/fixtures/reports/slither.sarif b/tests/fixtures/reports/slither.sarif new file mode 100644 index 00000000..2384b665 --- /dev/null +++ b/tests/fixtures/reports/slither.sarif @@ -0,0 +1,219 @@ +{ + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Slither", + "informationUri": "https://github.com/crytic/slither", + "version": "0.10.0", + "rules": [ + { + "id": "0-0-uninitialized-state", + "name": "uninitialized-state", + "properties": { + "precision": "very-high", + "security-severity": "8.0" + }, + "shortDescription": { + "text": "Uninitialized state variables" + }, + "help": { + "text": "\nInitialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability.\n" + } + }, + { + "id": "3-0-solc-version", + "name": "solc-version", + "properties": { + "precision": "very-high", + "security-severity": "0.0" + }, + "shortDescription": { + "text": "Incorrect versions of Solidity" + }, + "help": { + "text": "\nDeploy with any of the following Solidity versions:\n- 0.8.18\n\nThe recommendations take into account:\n- Risks related to recent releases\n- Risks of complex code generation changes\n- Risks of new language features\n- Risks of known bugs\n\nUse a simple pragma version that allows any of these versions.\nConsider using the latest version of Solidity for testing." + } + }, + { + "id": "3-0-naming-convention", + "name": "naming-convention", + "properties": { + "precision": "very-high", + "security-severity": "0.0" + }, + "shortDescription": { + "text": "Conformance to Solidity naming conventions" + }, + "help": { + "text": "Follow the Solidity [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions)." + } + }, + { + "id": "4-0-constable-states", + "name": "constable-states", + "properties": { + "precision": "very-high", + "security-severity": "0.0" + }, + "shortDescription": { + "text": "State variables that could be declared constant" + }, + "help": { + "text": "Add the `constant` attribute to state variables that never change." + } + } + ] + } + }, + "results": [ + { + "ruleId": "0-0-uninitialized-state", + "message": { + "text": "ERC20Buggy._totalSupply (ERC20.sol#4) is never initialized. It is used in:\n\t- ERC20Buggy.totalSupply() (ERC20.sol#37-39)\n", + "markdown": "[ERC20Buggy._totalSupply](ERC20.sol#L4) is never initialized. It is used in:\n\t- [ERC20Buggy.totalSupply()](ERC20.sol#L37-L39)\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 4, + "endLine": 4 + } + } + } + ], + "partialFingerprints": { + "id": "7b17182a44bd3c13866e3e4e585393fc09a25a2e6715512184572d49f8bf8df5" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Variable ERC20Buggy._balanceOf (ERC20.sol#5) is not in mixedCase\n", + "markdown": "Variable [ERC20Buggy._balanceOf](ERC20.sol#L5) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 5, + "endLine": 5 + } + } + } + ], + "partialFingerprints": { + "id": "02e6097efd3009dcc27b8a5527eebbc4721e969ab7956639b08a21eee86c73b7" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Variable ERC20Buggy._allowance (ERC20.sol#6) is not in mixedCase\n", + "markdown": "Variable [ERC20Buggy._allowance](ERC20.sol#L6) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 6, + "endLine": 6 + } + } + } + ], + "partialFingerprints": { + "id": "6032a0270bf2adbbcd0067c061e63c3a73c6f09d90d0a46cad330394988cb9b9" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Parameter ERC20Buggy.approve(address,uint256)._spender (ERC20.sol#24) is not in mixedCase\n", + "markdown": "Parameter [ERC20Buggy.approve(address,uint256)._spender](ERC20.sol#L24) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 24, + "endLine": 24 + } + } + } + ], + "partialFingerprints": { + "id": "6b595b8907c5207c1885cc0ac0852e8ccbda8f149c200fc6b584ad003187fc2c" + } + }, + { + "ruleId": "3-0-naming-convention", + "message": { + "text": "Variable ERC20Buggy._totalSupply (ERC20.sol#4) is not in mixedCase\n", + "markdown": "Variable [ERC20Buggy._totalSupply](ERC20.sol#L4) is not in mixedCase\n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 4, + "endLine": 4 + } + } + } + ], + "partialFingerprints": { + "id": "9a6a5111def54fca1801e2b40299e74a855a80a7813ffdb0d19ee923cc1f032f" + } + }, + { + "ruleId": "4-0-constable-states", + "message": { + "text": "ERC20Buggy._totalSupply (ERC20.sol#4) should be constant \n", + "markdown": "[ERC20Buggy._totalSupply](ERC20.sol#L4) should be constant \n" + }, + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "ERC20.sol" + }, + "region": { + "startLine": 4, + "endLine": 4 + } + } + } + ], + "partialFingerprints": { + "id": "f6a9d2e5c554c22bd038ce28139c911c7a0893017d8e9054cbaaf6a084b71c39" + } + } + ] + } + ] +} \ No newline at end of file