├── .circleci └── config.yml ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── docs └── index.rst ├── requirements.txt ├── requirements_dev.txt ├── setup.cfg ├── setup.py ├── swc_registry ├── __init__.py ├── get_entry_info.py └── swc-definition.json └── tests ├── __init__.py └── test_get_entry_info.py /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | test: 4 | docker: 5 | - image: python:3.5 6 | steps: 7 | - checkout 8 | - run: 9 | name: Tests runner 10 | working_directory: swc_registry/ 11 | command: | 12 | pip install -r ../requirements.txt 13 | pip install -r ../requirements_dev.txt 14 | pytest ../tests/ 15 | deploy: 16 | docker: 17 | - image: python:3.5 18 | steps: 19 | - checkout 20 | - run: 21 | name: init .pypirc 22 | command: | 23 | echo -e "[pypi]" >> ~/.pypirc 24 | echo -e "username = $PYPI_USERNAME" >> ~/.pypirc 25 | echo -e "password = $PYPI_PASSWORD" >> ~/.pypirc 26 | - run: 27 | name: create packages 28 | command: | 29 | pip install -r requirements.txt 30 | bumpversion patch 31 | python setup.py sdist bdist_wheel 32 | - run: 33 | name: upload to pypi 34 | command: | 35 | pip install -r requirements.txt 36 | twine upload dist/* 37 | - run: 38 | name: Push changes 39 | command: | 40 | git config --global user.email "$GIT_USER_EMAIL" 41 | git config --global user.name "$GIT_USER" 42 | git add . && git commit -am "Changed the package version [skip ci]" && git push -q ${REPO_URL} 43 | workflows: 44 | version: 2 45 | build-test-and-deploy: 46 | jobs: 47 | - test 48 | - deploy: 49 | filters: 50 | branches: 51 | only: master 52 | requires: 53 | - test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | __pycache__/ 3 | .coverage 4 | MANIFEST 5 | coverage.xml 6 | nosetests.xml 7 | junit-report.xml 8 | pylint.txt 9 | toy.py 10 | .cache/ 11 | cover/ 12 | build/ 13 | docs/_build 14 | requests.egg-info/ 15 | *.pyc 16 | *.swp 17 | *.egg 18 | env/ 19 | dist 20 | *.egg-info/ 21 | .eggs/ 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 SWC-registry-python 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include swc_registry/swc-definition.json 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Python SWC Registry Library 2 | 3 | 4 | [![CircleCI](https://circleci.com/gh/SmartContractSecurity/SWC-registry-python.svg?style=svg)](https://circleci.com/gh/SmartContractSecurity/SWC-registry-python) 5 | [![Documentation Status](https://readthedocs.org/projects/swc-registry-python/badge/?version=latest)](https://swc-registry-python.readthedocs.io/en/latest/?badge=latest) 6 | 7 | 8 | ## Description 9 | Python library for accessing SWC-registry content. 10 | 11 | ## Installation 12 | 13 | ```console 14 | $ pip install -U swc-registry 15 | ``` 16 | 17 | ## Example 18 | ```python 19 | from swc_registry import SWC 20 | 21 | swc = SWC('SWC-100') 22 | print(swc.title) 23 | 24 | // Function Default Visibility 25 | ``` 26 | 27 | 28 | ## Behaviour 29 | 30 | On first use of the SWC methods, the SWC registry is initialized from file (swc-definition.json) out cache. If user wants to get the latest information about SWC-registry he needs to pass the second argument of SWC class. 31 | 32 | ### Get latest version 33 | ```python 34 | from swc_registry import SWC 35 | 36 | swc = SWC('SWC-100', get_last=True) 37 | print(swc.title) 38 | 39 | // Function Default Visibility 40 | ``` 41 | ## Contribution 42 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Getting Started with swc-registry-python 2 | ======================================== 3 | 4 | SWC-registry-python is a python package for accessing SWC-registry content. 5 | 6 | 7 | Quick start 8 | ----------- 9 | 10 | Assuming you have Python already: 11 | 12 | .. sourcecode:: bash 13 | 14 | $ pip install swc-registry 15 | 16 | Check the package work: 17 | 18 | .. sourcecode:: python 19 | 20 | from swc_registry import SWC 21 | 22 | swc = SWC('SWC-100') 23 | print(swc.title) 24 | 25 | // Function Default Visibility 26 | 27 | 28 | Get the latest content of SWC-registry 29 | -------------------------------------- 30 | 31 | On first use of the SWC methods, the SWC registry is initialized from file (swc-definition.json) out cache. If user wants to get the latest information about SWC-registry he needs to pass the second argument of SWC class. 32 | 33 | .. sourcecode:: python 34 | 35 | from swc_registry import SWC 36 | 37 | swc = SWC('SWC-100', True) 38 | print(swc.title) 39 | 40 | // Function Default Visibility -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.20.1 2 | pytest==4.0.1 3 | twine==1.12.1 4 | bumpversion==0.5.3 5 | -------------------------------------------------------------------------------- /requirements_dev.txt: -------------------------------------------------------------------------------- 1 | pytest==5.3.4 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.0.11 3 | 4 | [bumpversion:file:setup.py] 5 | 6 | [bumpversion:file:swc_registry/__init__.py] 7 | 8 | [aliases] 9 | test = pytest 10 | 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import sys 5 | 6 | from setuptools import setup 7 | from setuptools.command.install import install 8 | 9 | 10 | setup( 11 | name="swc-registry", 12 | version="0.0.11", 13 | url="https://github.com/SmartContractSecurity/SWC-registry-python", 14 | author="SmartContractSecurity", 15 | author_email="ersul4ik@gmail.com", 16 | description="The python library for accessing SWC-registry content.", 17 | long_description=open("README.md").read(), 18 | long_description_content_type="text/markdown", 19 | packages=["swc_registry"], 20 | include_package_data=True, 21 | install_requires=["requests==2.20.1"], 22 | classifiers=[ 23 | "Programming Language :: Python", 24 | "Programming Language :: Python :: 3", 25 | "Programming Language :: Python :: 3.3", 26 | "Programming Language :: Python :: 3.4", 27 | ], 28 | setup_requires=["pytest-runner"], 29 | tests_require=["pytest"], 30 | 31 | ) -------------------------------------------------------------------------------- /swc_registry/__init__.py: -------------------------------------------------------------------------------- 1 | from swc_registry.get_entry_info import SWC 2 | 3 | __version__ = "0.0.11" 4 | __author__ = "SmartContractSecurity" 5 | __all__ = [] 6 | -------------------------------------------------------------------------------- /swc_registry/get_entry_info.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import json 4 | 5 | 6 | class SWCException(Exception): 7 | pass 8 | 9 | 10 | class Singleton(type): 11 | _instances = {} 12 | 13 | def __call__(cls, *args, **kwargs): 14 | if cls not in cls._instances: 15 | cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) 16 | return cls._instances[cls] 17 | 18 | 19 | class SWCRegistry(object, metaclass=Singleton): 20 | """ 21 | Registry class takes care of loading and downloading the swc registry 22 | """ 23 | 24 | def __init__(self): 25 | self._content = None 26 | 27 | @staticmethod 28 | def _get_latest_version(): 29 | try: 30 | url = ( 31 | "https://raw.githubusercontent.com/SmartContractSecurity/SWC-registry/master/export/swc-definition" 32 | ".json" 33 | ) 34 | response = requests.get(url).json() 35 | return response 36 | except requests.exceptions.RequestException: 37 | return None 38 | 39 | def _load_from_file(self): 40 | path_file_content = os.path.join( 41 | os.path.dirname(__file__), "swc-definition.json" 42 | ) 43 | with open(path_file_content, "r", encoding="utf-8") as f: 44 | self._content = json.load(f) 45 | 46 | def update(self): 47 | self._content = SWCRegistry._get_latest_version() 48 | 49 | @property 50 | def content(self): 51 | if self._content is None: 52 | self._load_from_file() 53 | return self._content 54 | 55 | def __repr__(self): 56 | return "".format(len(self.content.keys())) 57 | 58 | 59 | class SWC: 60 | """ 61 | SWC class contains information on an SWC entry 62 | 63 | Example usage: 64 | swc = SWC('SWC-100') 65 | print(swc.title) 66 | """ 67 | 68 | def __init__(self, swc_id, get_last=False): 69 | self.swc_id = swc_id 70 | if get_last: 71 | SWCRegistry().update() 72 | 73 | @property 74 | def _swc_content(self): 75 | return SWCRegistry().content 76 | 77 | @property 78 | def _content(self): 79 | entries = self._swc_content 80 | current_entry = entries.get(self.swc_id) 81 | if not current_entry: 82 | raise SWCException("SWC with ID {} does not exist".format(self.swc_id)) 83 | content = current_entry.get("content", {}) 84 | return content 85 | 86 | @property 87 | def title(self) -> str: 88 | content = self._content 89 | title = content.get("Title", "") 90 | return title 91 | 92 | @property 93 | def relationships(self) -> str: 94 | content = self._content 95 | relationships = content.get("Relationships", "") 96 | return relationships 97 | 98 | @property 99 | def description(self) -> str: 100 | content = self._content 101 | description = content.get("Description", "") 102 | return description 103 | 104 | @property 105 | def remediation(self) -> str: 106 | content = self._content 107 | remediation = content.get("Remediation", "") 108 | return remediation 109 | 110 | def __repr__(self): 111 | return "".format(self) 112 | -------------------------------------------------------------------------------- /swc_registry/swc-definition.json: -------------------------------------------------------------------------------- 1 | { 2 | "SWC-100": { 3 | "markdown": "# Title \nFunction Default Visibility\n\n## Relationships \n[CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html)\n\n## Description \n\nFunctions that do not have a function visibility type specified are `public` by default. This can lead to a vulnerability if a developer forgot to set the visibility and a malicious user is able to make unauthorized or unintended state changes. \n\n## Remediation\n\nFunctions can be specified as being `external`, `public`, `internal` or `private`. It is recommended to make a conscious decision on which visibility type is appropriate for a function. This can dramatically reduce the attack surface of a contract system. \n\n## References \n- [Ethereum Smart Contract Best Practices - Explicitly mark visibility in functions and state variables](https://consensys.github.io/smart-contract-best-practices/recommendations/#explicitly-mark-visibility-in-functions-and-state-variables)\n- [SigmaPrime - Visibility](https://github.com/sigp/solidity-security-blog#visibility)\n\n", 4 | "content": { 5 | "Title": "Function Default Visibility", 6 | "Relationships": "[CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html)", 7 | "Description": "Functions that do not have a function visibility type specified are `public` by default. This can lead to a vulnerability if a developer forgot to set the visibility and a malicious user is able to make unauthorized or unintended state changes.", 8 | "Remediation": "Functions can be specified as being `external`, `public`, `internal` or `private`. It is recommended to make a conscious decision on which visibility type is appropriate for a function. This can dramatically reduce the attack surface of a contract system." 9 | } 10 | }, 11 | "SWC-101": { 12 | "markdown": "# Title \nInteger Overflow and Underflow\n\n## Relationships\n[CWE-682: Incorrect Calculation](https://cwe.mitre.org/data/definitions/682.html) \n\n## Description \n\nAn overflow/underflow happens when an arithmetic operation reaches the maximum or minimum size of a type. For instance if a number is stored in the uint8 type, it means that the number is stored in a 8 bits unsigned number ranging from 0 to 2^8-1. In computer programming, an integer overflow occurs when an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of bits – either larger than the maximum or lower than the minimum representable value.\n\n## Remediation\n\nIt is recommended to use vetted safe math libraries for arithmetic operations consistently throughout the smart contract system.\n\n## References \n- [Ethereum Smart Contract Best Practices - Integer Overflow and Underflow](https://consensys.github.io/smart-contract-best-practices/known_attacks/#integer-overflow-and-underflow)\n", 13 | "content": { 14 | "Title": "Integer Overflow and Underflow", 15 | "Relationships": "[CWE-682: Incorrect Calculation](https://cwe.mitre.org/data/definitions/682.html)", 16 | "Description": "An overflow/underflow happens when an arithmetic operation reaches the maximum or minimum size of a type. For instance if a number is stored in the uint8 type, it means that the number is stored in a 8 bits unsigned number ranging from 0 to 2^8-1. In computer programming, an integer overflow occurs when an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of bits – either larger than the maximum or lower than the minimum representable value.", 17 | "Remediation": "It is recommended to use vetted safe math libraries for arithmetic operations consistently throughout the smart contract system." 18 | } 19 | }, 20 | "SWC-102": { 21 | "markdown": "# Title \nOutdated Compiler Version\n\n## Relationships\n[CWE-937: Using Components with Known Vulnerabilities](http://cwe.mitre.org/data/definitions/937.html)\n\n## Description \n\nUsing an outdated compiler version can be problematic especially if there are publicly disclosed bugs and issues that affect the current compiler version.\n\n## Remediation\n\nIt is recommended to use a recent version of the Solidity compiler. \n\n## References \n- [Solidity Release Notes](https://github.com/ethereum/solidity/releases)\n- [Etherscan Solidity Bug Info](https://etherscan.io/solcbuginfo)\n", 22 | "content": { 23 | "Title": "Outdated Compiler Version", 24 | "Relationships": "[CWE-937: Using Components with Known Vulnerabilities](http://cwe.mitre.org/data/definitions/937.html)", 25 | "Description": "Using an outdated compiler version can be problematic especially if there are publicly disclosed bugs and issues that affect the current compiler version.", 26 | "Remediation": "It is recommended to use a recent version of the Solidity compiler." 27 | } 28 | }, 29 | "SWC-103": { 30 | "markdown": "# Title \nFloating Pragma \n\n## Relationships\n[CWE-664: Improper Control of a Resource Through its Lifetime](https://cwe.mitre.org/data/definitions/664.html)\n\n## Description \n\nContracts should be deployed with the same compiler version and flags that they have been tested with thoroughly. Locking the pragma helps to ensure that contracts do not accidentally get deployed using, for example, an outdated compiler version that might introduce bugs that affect the contract system negatively.\n\n## Remediation\n\nLock the pragma version and also consider known bugs (https://github.com/ethereum/solidity/releases) for the compiler version that is chosen. \n\nPragma statements can be allowed to float when a contract is intended for consumption by other developers, as in the case with contracts in a library or EthPM package. Otherwise, the developer would need to manually update the pragma in order to compile locally.\n\n## References \n- [Ethereum Smart Contract Best Practices - Lock pragmas to specific compiler version](https://consensys.github.io/smart-contract-best-practices/recommendations/#lock-pragmas-to-specific-compiler-version)\n\n\n", 31 | "content": { 32 | "Title": "Floating Pragma", 33 | "Relationships": "[CWE-664: Improper Control of a Resource Through its Lifetime](https://cwe.mitre.org/data/definitions/664.html)", 34 | "Description": "Contracts should be deployed with the same compiler version and flags that they have been tested with thoroughly. Locking the pragma helps to ensure that contracts do not accidentally get deployed using, for example, an outdated compiler version that might introduce bugs that affect the contract system negatively.", 35 | "Remediation": "Lock the pragma version and also consider known bugs (https://github.com/ethereum/solidity/releases) for the compiler version that is chosen. \n\n\nPragma statements can be allowed to float when a contract is intended for consumption by other developers, as in the case with contracts in a library or EthPM package. Otherwise, the developer would need to manually update the pragma in order to compile locally." 36 | } 37 | }, 38 | "SWC-104": { 39 | "markdown": "# Title \nUnchecked Call Return Value\n\n## Relationships\n[CWE-252: Unchecked Return Value](https://cwe.mitre.org/data/definitions/252.html)\n\n## Description \n\nThe return value of a message call is not checked. Execution will resume even if the called contract throws an exception. If the call fails accidentally or an attacker forces the call to fail, this may cause unexpected behaviour in the subsequent program logic.\n\n## Remediation\n\nIf you choose to use low-level call methods, make sure to handle the possibility that the call will fail by checking the return value.\n\n## References \n- [Ethereum Smart Contract Best Practices - Handle errors in external calls](https://consensys.github.io/smart-contract-best-practices/recommendations/#handle-errors-in-external-calls)\n", 40 | "content": { 41 | "Title": "Unchecked Call Return Value", 42 | "Relationships": "[CWE-252: Unchecked Return Value](https://cwe.mitre.org/data/definitions/252.html)", 43 | "Description": "The return value of a message call is not checked. Execution will resume even if the called contract throws an exception. If the call fails accidentally or an attacker forces the call to fail, this may cause unexpected behaviour in the subsequent program logic.", 44 | "Remediation": "If you choose to use low-level call methods, make sure to handle the possibility that the call will fail by checking the return value." 45 | } 46 | }, 47 | "SWC-105": { 48 | "markdown": "# Title \nUnprotected Ether Withdrawal\n\n## Relationships\n[CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html)\n\n## Description \n\nDue to missing or insufficient access controls, malicious parties can withdraw some or all Ether from the contract account.\n\nThis bug is sometimes caused by unintentionally exposing initialization functions. By wrongly naming a function intended to be a constructor, the constructor code ends up in the runtime byte code and can be called by anyone to re-initialize the contract.\n\n## Remediation\n\nImplement controls so withdrawals can only be triggered by authorized parties or according to the specs of the smart contract system.\n\n## References \n\n- [Rubixi smart contract](https://etherscan.io/address/0xe82719202e5965Cf5D9B6673B7503a3b92DE20be#code)\n", 49 | "content": { 50 | "Title": "Unprotected Ether Withdrawal", 51 | "Relationships": "[CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html)", 52 | "Description": "Due to missing or insufficient access controls, malicious parties can withdraw some or all Ether from the contract account.\n\n\nThis bug is sometimes caused by unintentionally exposing initialization functions. By wrongly naming a function intended to be a constructor, the constructor code ends up in the runtime byte code and can be called by anyone to re-initialize the contract.", 53 | "Remediation": "Implement controls so withdrawals can only be triggered by authorized parties or according to the specs of the smart contract system." 54 | } 55 | }, 56 | "SWC-106": { 57 | "markdown": "# Title \nUnprotected SELFDESTRUCT Instruction\n\n## Relationships\n[CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html)\n\n## Description \n\nDue to missing or insufficient access controls, malicious parties can self-destruct the contract.\n\n## Remediation\n\nConsider removing the self-destruct functionality unless it is absolutely required. If there is a valid use-case, it is recommended to implement a multisig scheme so that multiple parties must approve the self-destruct action.\n\n## References \n- [Parity \"I accidentally killed it\" bug](https://www.parity.io/a-postmortem-on-the-parity-multi-sig-library-self-destruct/)\n", 58 | "content": { 59 | "Title": "Unprotected SELFDESTRUCT Instruction", 60 | "Relationships": "[CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html)", 61 | "Description": "Due to missing or insufficient access controls, malicious parties can self-destruct the contract.", 62 | "Remediation": "Consider removing the self-destruct functionality unless it is absolutely required. If there is a valid use-case, it is recommended to implement a multisig scheme so that multiple parties must approve the self-destruct action." 63 | } 64 | }, 65 | "SWC-107": { 66 | "markdown": "# Title \nReentrancy\n\n## Relationships\n[CWE-841: Improper Enforcement of Behavioral Workflow](https://cwe.mitre.org/data/definitions/841.html)\n\n## Description\n\nOne of the major dangers of calling external contracts is that they can take over the control flow. In the reentrancy attack (a.k.a. recursive call attack), a malicious contract calls back into the calling contract before the first invocation of the function is finished. This may cause the different invocations of the function to interact in undesirable ways.\n\n## Remediation\n\nThe best practices to avoid Reentrancy weaknesses are: \n\n- Use `transfer()` instead of `contract.call()` to transfer Ether to untrusted addresses. \n- When using low-level calls, make sure all internal state changes are performed before the call is executed.\n\n## References \n\n- [Ethereum Smart Contract Best Practices - Reentrancy](https://consensys.github.io/smart-contract-best-practices/known_attacks/#reentrancy)\n", 67 | "content": { 68 | "Title": "Reentrancy", 69 | "Relationships": "[CWE-841: Improper Enforcement of Behavioral Workflow](https://cwe.mitre.org/data/definitions/841.html)", 70 | "Description": "One of the major dangers of calling external contracts is that they can take over the control flow. In the reentrancy attack (a.k.a. recursive call attack), a malicious contract calls back into the calling contract before the first invocation of the function is finished. This may cause the different invocations of the function to interact in undesirable ways.", 71 | "Remediation": "The best practices to avoid Reentrancy weaknesses are: \n\n\n- Use `transfer()` instead of `contract.call()` to transfer Ether to untrusted addresses. \n- When using low-level calls, make sure all internal state changes are performed before the call is executed." 72 | } 73 | }, 74 | "SWC-108": { 75 | "markdown": "# Title \nState Variable Default Visibility \n\n## Relationships\n[CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html)\n\n## Description \n\nLabeling the visibility explicitly makes it easier to catch incorrect assumptions about who can access the variable.\n\n## Remediation\n\nVariables can be specified as being `public`, `internal` or `private`. Explicitly define visibility for all state variables.\n\n## References \n- [Ethereum Smart Contract Best Practices - Explicitly mark visibility in functions and state variables](https://consensys.github.io/smart-contract-best-practices/recommendations/#explicitly-mark-visibility-in-functions-and-state-variables)\n", 76 | "content": { 77 | "Title": "State Variable Default Visibility", 78 | "Relationships": "[CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html)", 79 | "Description": "Labeling the visibility explicitly makes it easier to catch incorrect assumptions about who can access the variable.", 80 | "Remediation": "Variables can be specified as being `public`, `internal` or `private`. Explicitly define visibility for all state variables." 81 | } 82 | }, 83 | "SWC-109": { 84 | "markdown": "# Title\nUninitialized Storage Pointer\n\n## Relationships\n[CWE-824: Access of Uninitialized Pointer](https://cwe.mitre.org/data/definitions/824.html)\n\n## Description\nUninitialized local storage variables can point to unexpected storage locations in the contract, which can lead to intentional or unintentional vulnerabilities.\n\n## Remediation\nCheck if the contract requires a storage object as in many situations this is actually not the case. If a local variable is sufficient mark the storage location of the variable explicitly with the `memory` attribute. If a storage variable is needed then initialise is upon declaration and additionally specific the storage location `storage`.\n\n**Note**: As of compiler version 0.5.0 and higher this issue has been systematically resolved as contracts with uninitialised storage pointers do no longer compile. \n\n## References\n- [SigmaPrime - Unintialised Storage Pointers](https://github.com/sigp/solidity-security-blog#unintialised-storage-pointers-1)\n", 85 | "content": { 86 | "Title": "Uninitialized Storage Pointer", 87 | "Relationships": "[CWE-824: Access of Uninitialized Pointer](https://cwe.mitre.org/data/definitions/824.html)", 88 | "Description": "Uninitialized local storage variables can point to unexpected storage locations in the contract, which can lead to intentional or unintentional vulnerabilities.", 89 | "Remediation": "Check if the contract requires a storage object as in many situations this is actually not the case. If a local variable is sufficient mark the storage location of the variable explicitly with the `memory` attribute. If a storage variable is needed then initialise is upon declaration and additionally specific the storage location `storage`.\n\n\n**Note**: As of compiler version 0.5.0 and higher this issue has been systematically resolved as contracts with uninitialised storage pointers do no longer compile." 90 | } 91 | }, 92 | "SWC-110": { 93 | "markdown": "# Title \nAssert Violation\n\n## Relationships\n\n[CWE-670: Always-Incorrect Control Flow Implementation](https://cwe.mitre.org/data/definitions/670.html)\n\n## Description \n\nThe Solidity `assert()` function is meant to assert invariants. Properly functioning code should *never* reach a failing assert statement. A reachable assertion can mean one of two things:\n\n1. A bug exists in the contract that allows it to enter an invalid state;\n2. The `assert` statement is used incorrectly, e.g. to validate inputs.\n\n## Remediation\n\nConsider whether the condition checked in the `assert()` is actually an invariant. If not, replace the `assert()` statement with a `require()` statement.\n\nIf the exception is indeed caused by unexpected behaviour of the code, fix the underlying bug(s) that allow the assertion to be violated.\n\n## References\n\n- [The use of revert(), assert(), and require() in Solidity, and the new REVERT opcode in the EVM](https://media.consensys.net/when-to-use-revert-assert-and-require-in-solidity-61fb2c0e5a57)\n", 94 | "content": { 95 | "Title": "Assert Violation", 96 | "Relationships": "[CWE-670: Always-Incorrect Control Flow Implementation](https://cwe.mitre.org/data/definitions/670.html)", 97 | "Description": "The Solidity `assert()` function is meant to assert invariants. Properly functioning code should *never* reach a failing assert statement. A reachable assertion can mean one of two things:\n\n\n1. A bug exists in the contract that allows it to enter an invalid state;\n1. The `assert` statement is used incorrectly, e.g. to validate inputs.", 98 | "Remediation": "Consider whether the condition checked in the `assert()` is actually an invariant. If not, replace the `assert()` statement with a `require()` statement.\n\n\nIf the exception is indeed caused by unexpected behaviour of the code, fix the underlying bug(s) that allow the assertion to be violated." 99 | } 100 | }, 101 | "SWC-111": { 102 | "markdown": "# Title\nUse of Deprecated Solidity Functions\n\n## Relationships\n[CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html)\n\n## Description\n\nSeveral functions and operators in Solidity are deprecated. Using them leads to reduced code quality. With new major versions of the Solidity compiler, deprecated functions and operators may result in side effects and compile errors.\n\n## Remediation\n\nSolidity provides alternatives to the deprecated constructions. Most of them are aliases, thus replacing old constructions will not break current behavior. For example, `sha3` can be replaced with `keccak256`.\n\n| Deprecated | Alternative |\n|-------------------------|-------------------------|\n| `suicide(address)` | `selfdestruct(address)` |\n| `block.blockhash(uint)` | `blockhash(uint)` |\n| `sha3(...)` | `keccak256(...)` |\n| `callcode(...)` | `delegatecall(...)` |\n| `throw` | `revert()` |\n| `msg.gas` | `gasleft` |\n| `constant` | `view` |\n| `var` | corresponding type name |\n\n## References\n\n* [List of global variables and functions, as of Solidity 0.4.25](https://solidity.readthedocs.io/en/v0.4.25/miscellaneous.html#global-variables)\n* [Error handling: Assert, Require, Revert and Exceptions](https://solidity.readthedocs.io/en/v0.4.25/control-structures.html#error-handling-assert-require-revert-and-exceptions)\n* [View functions](https://solidity.readthedocs.io/en/v0.4.25/contracts.html#view-functions)\n* [Untyped declaration is deprecated as of Solidity 0.4.20](https://github.com/ethereum/solidity/releases/tag/v0.4.20)\n* [Solidity compiler changelog](https://github.com/ethereum/solidity/releases)\n", 103 | "content": { 104 | "Title": "Use of Deprecated Solidity Functions", 105 | "Relationships": "[CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html)", 106 | "Description": "Several functions and operators in Solidity are deprecated. Using them leads to reduced code quality. With new major versions of the Solidity compiler, deprecated functions and operators may result in side effects and compile errors.", 107 | "Remediation": "Solidity provides alternatives to the deprecated constructions. Most of them are aliases, thus replacing old constructions will not break current behavior. For example, `sha3` can be replaced with `keccak256`.\n\n\n| Deprecated | Alternative | \n|: ---------:| ---------:| \n| `suicide(address)` | `selfdestruct(address)` | \n| `block.blockhash(uint)` | `blockhash(uint)` | \n| `sha3(...)` | `keccak256(...)` | \n| `callcode(...)` | `delegatecall(...)` | \n| `throw` | `revert()` | \n| `msg.gas` | `gasleft` | \n| `constant` | `view` | \n| `var` | corresponding type name |" 108 | } 109 | }, 110 | "SWC-112": { 111 | "markdown": "# Title \nDelegatecall to Untrusted Callee\n\n## Relationships\n[CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html)\n\n## Description \n\nThere exists a special variant of a message call, named `delegatecall` which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and `msg.sender` and `msg.value` do not change their values. This allows a smart contract to dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract.\n\nCalling into untrusted contracts is very dangerous, as the code at the target address can change any storage values of the caller and has full control over the caller's balance.\n\n## Remediation\n\nUse `delegatecall` with caution and make sure to never call into untrusted contracts. If the target address is derived from user input ensure to check it against a whitelist of trusted contracts.\n\n## References\n\n- [Solidity Documentation - Delegatecall / Callcode and Libraries](https://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries)\n- [How to Secure Your Smart Contracts: 6 Solidity Vulnerabilities and how to avoid them (Part 1) - Delegate Call](https://medium.com/loom-network/how-to-secure-your-smart-contracts-6-solidity-vulnerabilities-and-how-to-avoid-them-part-1-c33048d4d17d)\n- [Solidity Security: Comprehensive list of known attack vectors and common anti-patterns - Delegatecall](https://blog.sigmaprime.io/solidity-security.html#delegatecall)\n", 112 | "content": { 113 | "Title": "Delegatecall to Untrusted Callee", 114 | "Relationships": "[CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html)", 115 | "Description": "There exists a special variant of a message call, named `delegatecall` which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and `msg.sender` and `msg.value` do not change their values. This allows a smart contract to dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract.\n\n\nCalling into untrusted contracts is very dangerous, as the code at the target address can change any storage values of the caller and has full control over the caller's balance.", 116 | "Remediation": "Use `delegatecall` with caution and make sure to never call into untrusted contracts. If the target address is derived from user input ensure to check it against a whitelist of trusted contracts." 117 | } 118 | }, 119 | "SWC-113": { 120 | "markdown": "# Title \n\nDoS with Failed Call \n\n## Relationships\n\n[CWE-703: Improper Check or Handling of Exceptional Conditions](https://cwe.mitre.org/data/definitions/703.html)\n\n## Description \n\nExternal calls can fail accidentally or deliberately, which can cause a DoS condition in the contract. To minimize the damage caused by such failures, it is better to isolate each external call into its own transaction that can be initiated by the recipient of the call. This is especially relevant for payments, where it is better to let users withdraw funds rather than push funds to them automatically (this also reduces the chance of problems with the gas limit).\n\n## Remediation\n\nIt is recommended to follow call best practices:\n\n- Avoid combining multiple calls in a single transaction, especially when calls are executed as part of a loop\n- Always assume that external calls can fail\n- Implement the contract logic to handle failed calls\n\n## References\n\n- [ConsenSys Smart Contract Best Practices](https://consensys.github.io/smart-contract-best-practices/recommendations/#favor-pull-over-push-for-external-calls)\n", 121 | "content": { 122 | "Title": "DoS with Failed Call", 123 | "Relationships": "[CWE-703: Improper Check or Handling of Exceptional Conditions](https://cwe.mitre.org/data/definitions/703.html)", 124 | "Description": "External calls can fail accidentally or deliberately, which can cause a DoS condition in the contract. To minimize the damage caused by such failures, it is better to isolate each external call into its own transaction that can be initiated by the recipient of the call. This is especially relevant for payments, where it is better to let users withdraw funds rather than push funds to them automatically (this also reduces the chance of problems with the gas limit).", 125 | "Remediation": "It is recommended to follow call best practices:\n\n\n- Avoid combining multiple calls in a single transaction, especially when calls are executed as part of a loop\n- Always assume that external calls can fail\n- Implement the contract logic to handle failed calls" 126 | } 127 | }, 128 | "SWC-114": { 129 | "markdown": "# Title\nTransaction Order Dependence\n\n## Relationships\n[CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')](https://cwe.mitre.org/data/definitions/362.html)\n\n## Description\nThe Ethereum network processes transactions in blocks with new blocks getting confirmed around every 17 seconds. The miners look at transactions they have received and select which transactions to include in a block, based who has paid a high enough gas price to be included. Additionally, when transactions are sent to the Ethereum network they are forwarded to each node for processing. Thus, a person who is running an Ethereum node can tell which transactions are going to occur before they are finalized.A race condition vulnerability occurs when code depends on the order of the transactions submitted to it.\n\nThe simplest example of a race condition is when a smart contract give a reward for submitting information. Say a contract will give out 1 token to the first person who solves a math problem. Alice solves the problem and submits the answer to the network with a standard gas price. Eve runs an Ethereum node and can see the answer to the math problem in the transaction that Alice submitted to the network. So Eve submits the answer to the network with a much higher gas price and thus it gets processed and committed before Alice's transaction. Eve receives one token and Alice gets nothing, even though it was Alice who worked to solve the problem. A common way this occurs in practice is when a contract rewards people for calling out bad behavior in a protocol by giving a bad actor's deposit to the person who proved they were misbehaving.\n\nThe race condition that happens the most on the network today is the race condition in the ERC20 token standard. The ERC20 token standard includes a function called 'approve' which allows an address to approve another address to spend tokens on their behalf. Assume that Alice has approved Eve to spend n of her tokens, then Alice decides to change Eve's approval to m tokens. Alice submits a function call to approve with the value n for Eve. Eve runs a Ethereum node so knows that Alice is going to change her approval to m. Eve then submits a tranferFrom request sending n of Alice's tokens to herself, but gives it a much higher gas price than Alice's transaction. The transferFrom executes first so gives Eve n tokens and sets Eve's approval to zero. Then Alice's transaction executes and sets Eve's approval to m. Eve then sends those m tokens to herself as well. Thus Eve gets n + m tokens even thought she should have gotten at most max(n,m).\n\n## Remediation\nA possible way to remedy for race conditions in submission of information in exchange for a reward is called a commit reveal hash scheme. Instead of submitting the answer the party who has the answer submits hash(salt, address, answer) [salt being some number of their choosing] the contract stores this hash and the sender's address. To claim the reward the sender then submits a transaction with the salt, and answer. The contract hashes (salt, msg.sender, answer) and checks the hash produced against the stored hash, if the hash matches the contract releases the reward.\n\nThe best fix for the ERC20 race condition is to add a field to the inputs of approve which is the expected current value and to have approve revert if Eve's current allowance is not what Alice indicated she was expecting. However this means that your contract no longer conforms to the ERC20 standard. If it important to your project to have the contract conform to ERC20, you can add a safe approve function. From the user perspective it is possible to mediate the ERC20 race condition by setting approvals to zero before changing them.\n\n## References\n[General Article on Race Conditions](https://medium.com/coinmonks/solidity-transaction-ordering-attacks-1193a014884e)\n[ERC20 Race Condition](https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#)\n", 130 | "content": { 131 | "Title": "Transaction Order Dependence", 132 | "Relationships": "[CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')](https://cwe.mitre.org/data/definitions/362.html)", 133 | "Description": "The Ethereum network processes transactions in blocks with new blocks getting confirmed around every 17 seconds. The miners look at transactions they have received and select which transactions to include in a block, based who has paid a high enough gas price to be included. Additionally, when transactions are sent to the Ethereum network they are forwarded to each node for processing. Thus, a person who is running an Ethereum node can tell which transactions are going to occur before they are finalized.A race condition vulnerability occurs when code depends on the order of the transactions submitted to it.\n\n\nThe simplest example of a race condition is when a smart contract give a reward for submitting information. Say a contract will give out 1 token to the first person who solves a math problem. Alice solves the problem and submits the answer to the network with a standard gas price. Eve runs an Ethereum node and can see the answer to the math problem in the transaction that Alice submitted to the network. So Eve submits the answer to the network with a much higher gas price and thus it gets processed and committed before Alice's transaction. Eve receives one token and Alice gets nothing, even though it was Alice who worked to solve the problem. A common way this occurs in practice is when a contract rewards people for calling out bad behavior in a protocol by giving a bad actor's deposit to the person who proved they were misbehaving.\n\n\nThe race condition that happens the most on the network today is the race condition in the ERC20 token standard. The ERC20 token standard includes a function called 'approve' which allows an address to approve another address to spend tokens on their behalf. Assume that Alice has approved Eve to spend n of her tokens, then Alice decides to change Eve's approval to m tokens. Alice submits a function call to approve with the value n for Eve. Eve runs a Ethereum node so knows that Alice is going to change her approval to m. Eve then submits a tranferFrom request sending n of Alice's tokens to herself, but gives it a much higher gas price than Alice's transaction. The transferFrom executes first so gives Eve n tokens and sets Eve's approval to zero. Then Alice's transaction executes and sets Eve's approval to m. Eve then sends those m tokens to herself as well. Thus Eve gets n + m tokens even thought she should have gotten at most max(n,m).", 134 | "Remediation": "A possible way to remedy for race conditions in submission of information in exchange for a reward is called a commit reveal hash scheme. Instead of submitting the answer the party who has the answer submits hash(salt, address, answer) [salt being some number of their choosing] the contract stores this hash and the sender's address. To claim the reward the sender then submits a transaction with the salt, and answer. The contract hashes (salt, msg.sender, answer) and checks the hash produced against the stored hash, if the hash matches the contract releases the reward.\n\n\nThe best fix for the ERC20 race condition is to add a field to the inputs of approve which is the expected current value and to have approve revert if Eve's current allowance is not what Alice indicated she was expecting. However this means that your contract no longer conforms to the ERC20 standard. If it important to your project to have the contract conform to ERC20, you can add a safe approve function. From the user perspective it is possible to mediate the ERC20 race condition by setting approvals to zero before changing them." 135 | } 136 | }, 137 | "SWC-115": { 138 | "markdown": "# Title \nAuthorization through tx.origin\n\n## Relationships\n[CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html)\n\n## Description \n`tx.origin` is a global variable in Solidity which returns the address of the account that sent the transaction. Using the variable for authorization could make a contract vulnerable if an authorized account calls into a malicious contract. A call could be made to the vulnerable contract that passes the authorization check since `tx.origin` returns the original sender of the transaction which in this case is the authorized account.\n\n## Remediation\n\n`tx.origin` should not be used for authorization. Use `msg.sender` instead.\n\n## References\n- [Solidity Documentation - tx.origin](https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin)\n- [Ethereum Smart Contract Best Practices - Avoid using tx.origin](https://consensys.github.io/smart-contract-best-practices/recommendations/#avoid-using-txorigin)\n- [SigmaPrime - Visibility](https://github.com/sigp/solidity-security-blog#tx-origin)\n", 139 | "content": { 140 | "Title": "Authorization through tx.origin", 141 | "Relationships": "[CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html)", 142 | "Description": "`tx.origin` is a global variable in Solidity which returns the address of the account that sent the transaction. Using the variable for authorization could make a contract vulnerable if an authorized account calls into a malicious contract. A call could be made to the vulnerable contract that passes the authorization check since `tx.origin` returns the original sender of the transaction which in this case is the authorized account.", 143 | "Remediation": "`tx.origin` should not be used for authorization. Use `msg.sender` instead." 144 | } 145 | }, 146 | "SWC-116": { 147 | "markdown": "# Title \nTimestamp Dependence\n\n## Relationships\n[CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html)\n\n## Description \n\nContracts often need access to the current timestamp to trigger time-dependent events. As Ethereum is decentralized, nodes can synchronize time only to some degree. Moreover, malicious miners can alter the timestamp of their blocks, especially if they can gain advantages by doing so. However, miners can't set timestamp smaller than the previous one (otherwise the block will be rejected), nor can they set the timestamp too far ahead in the future. Taking all of the above into consideration, developers can't rely on the preciseness of the provided timestamp.\n\n## Remediation\n\nDevelopers should write smart contracts with the notion that block timestamp and real timestamp may vary up to half a minute. Alternatively, they can use block number or external source of timestamp via oracles.\n\n## References\n\n* [Safety: Timestamp dependence](https://github.com/ethereum/wiki/wiki/Safety#timestamp-dependence)\n* [Ethereum Smart Contract Best Practices - Timestamp Dependence](https://consensys.github.io/smart-contract-best-practices/recommendations/#timestamp-dependence)\n* [How do Ethereum mining nodes maintain a time consistent with the network?](https://ethereum.stackexchange.com/questions/5924/how-do-ethereum-mining-nodes-maintain-a-time-consistent-with-the-network/5926#5926)\n* [Solidity: Timestamp dependency, is it possible to do safely?](https://ethereum.stackexchange.com/questions/15047/solidity-timestamp-dependency-is-it-possible-to-do-safely)\n", 148 | "content": { 149 | "Title": "Timestamp Dependence", 150 | "Relationships": "[CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html)", 151 | "Description": "Contracts often need access to the current timestamp to trigger time-dependent events. As Ethereum is decentralized, nodes can synchronize time only to some degree. Moreover, malicious miners can alter the timestamp of their blocks, especially if they can gain advantages by doing so. However, miners can't set timestamp smaller than the previous one (otherwise the block will be rejected), nor can they set the timestamp too far ahead in the future. Taking all of the above into consideration, developers can't rely on the preciseness of the provided timestamp.", 152 | "Remediation": "Developers should write smart contracts with the notion that block timestamp and real timestamp may vary up to half a minute. Alternatively, they can use block number or external source of timestamp via oracles." 153 | } 154 | }, 155 | "SWC-117": { 156 | "markdown": "# Title\nSignature Malleability\n\n## Relationships\n[CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html)\n\n## Description\n\nThe implementation of a cryptographic signature system in Ethereum contracts often assumes that the signature is unique, but signatures can be altered without the possession of the private key and still be valid. The EVM specification defines several so-called ‘precompiled’ contracts one of them being `ecrecover` which executes the elliptic curve public key recovery. A malicious user can slightly modify the three values _v_, _r_ and _s_ to create other valid signatures. A system that performs signature verification on contract level might be susceptible to attacks if the signature is part of the signed message hash. Valid signatures could be created by a malicious user to replay previously signed messages. \n\n## Remediation\n\nA signature should never be included into a signed message hash to check if previously messages have been processed by the contract. \n\n## References\n[Bitcoin Transaction Malleability](https://eklitzke.org/bitcoin-transaction-malleability)\n[CTF - Challenge](https://ropsten.etherscan.io/address/0x0daabce0a1261b582e0d949ebca9dff4c22c88ef#code)\n", 157 | "content": { 158 | "Title": "Signature Malleability", 159 | "Relationships": "[CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html)", 160 | "Description": "The implementation of a cryptographic signature system in Ethereum contracts often assumes that the signature is unique, but signatures can be altered without the possession of the private key and still be valid. The EVM specification defines several so-called ‘precompiled’ contracts one of them being `ecrecover` which executes the elliptic curve public key recovery. A malicious user can slightly modify the three values _v_, _r_ and _s_ to create other valid signatures. A system that performs signature verification on contract level might be susceptible to attacks if the signature is part of the signed message hash. Valid signatures could be created by a malicious user to replay previously signed messages.", 161 | "Remediation": "A signature should never be included into a signed message hash to check if previously messages have been processed by the contract." 162 | } 163 | }, 164 | "SWC-118": { 165 | "markdown": "# Title \nIncorrect Constructor Name \n\n## Relationships\n[CWE-665: Improper Initialization](http://cwe.mitre.org/data/definitions/665.html)\n\n## Description \nConstructors are special functions that are called only once during the contract creation. They often perform critical, privileged actions such as setting the owner of the contract. Before Solidity version 0.4.22, the only way of defining a constructor was to create a function with the same name as the contract class containing it. A function meant to become a constructor becomes a normal, callable function if its name doesn't exactly match the contract name.\nThis behavior sometimes leads to security issues, in particular when smart contract code is re-used with a different name but the name of the constructor function is not changed accordingly. \n\n## Remediation\n\nSolidity version 0.4.22 introduces a new `constructor` keyword that make a constructor definitions clearer. It is therefore recommended to upgrade the contract to a recent version of the Solidity compiler and change to the new constructor declaration. \n\n## References\n\n- [SigmaPrime - Constructors with Care](https://blog.sigmaprime.io/solidity-security.html#constructors)\n", 166 | "content": { 167 | "Title": "Incorrect Constructor Name", 168 | "Relationships": "[CWE-665: Improper Initialization](http://cwe.mitre.org/data/definitions/665.html)", 169 | "Description": "Constructors are special functions that are called only once during the contract creation. They often perform critical, privileged actions such as setting the owner of the contract. Before Solidity version 0.4.22, the only way of defining a constructor was to create a function with the same name as the contract class containing it. A function meant to become a constructor becomes a normal, callable function if its name doesn't exactly match the contract name.\nThis behavior sometimes leads to security issues, in particular when smart contract code is re-used with a different name but the name of the constructor function is not changed accordingly.", 170 | "Remediation": "Solidity version 0.4.22 introduces a new `constructor` keyword that make a constructor definitions clearer. It is therefore recommended to upgrade the contract to a recent version of the Solidity compiler and change to the new constructor declaration." 171 | } 172 | }, 173 | "SWC-119": { 174 | "markdown": "# Title \nShadowing State Variables\n\n## Relationships\n[CWE-710: Improper Adherence to Coding Standards](http://cwe.mitre.org/data/definitions/710.html)\n\n## Description \n\nSolidity allows for ambiguous naming of state variables when inheritance is used. Contract `A` with a variable `x` could inherit contract `B` that also has a state variable `x` defined. This would result in two separate versions of `x`, one of them being accessed from contract `A` and the other one from contract `B`. In more complex contract systems this condition could go unnoticed and subsequently lead to security issues. \n\nShadowing state variables can also occur within a single contract when there are multiple definitions on the contract and function level. \n\n## Remediation\n\nReview storage variable layouts for your contract systems carefully and remove any ambiguities. Always check for compiler warnings as they can flag the issue within a single contract.\n\n## References\n- [Issue on Solidity's Github - Shadowing of inherited state variables should be an error (override keyword)](https://github.com/ethereum/solidity/issues/2563)\n- [Issue on Solidity's Github - Warn about shadowing state variables](https://github.com/ethereum/solidity/issues/973)\n", 175 | "content": { 176 | "Title": "Shadowing State Variables", 177 | "Relationships": "[CWE-710: Improper Adherence to Coding Standards](http://cwe.mitre.org/data/definitions/710.html)", 178 | "Description": "Solidity allows for ambiguous naming of state variables when inheritance is used. Contract `A` with a variable `x` could inherit contract `B` that also has a state variable `x` defined. This would result in two separate versions of `x`, one of them being accessed from contract `A` and the other one from contract `B`. In more complex contract systems this condition could go unnoticed and subsequently lead to security issues. \n\n\nShadowing state variables can also occur within a single contract when there are multiple definitions on the contract and function level.", 179 | "Remediation": "Review storage variable layouts for your contract systems carefully and remove any ambiguities. Always check for compiler warnings as they can flag the issue within a single contract." 180 | } 181 | }, 182 | "SWC-120": { 183 | "markdown": "# Title \nWeak Sources of Randomness from Chain Attributes\n\n## Relationships\n[CWE-330: Use of Insufficiently Random Values](https://cwe.mitre.org/data/definitions/330.html)\n\n## Description \n\nAbility to generate random numbers is very helpful in all kinds of applications. One obvious example is gambling DApps, where pseudo-random number generator is used to pick the winner. However, creating a strong enough source of randomness in Ethereum is very challenging. For example, use of `block.timestamp` is insecure, as a miner can choose to provide any timestamp within a few seconds and still get his block accepted by others. Use of `blockhash`, `block.difficulty` and other fields is also insecure, as they're controlled by the miner. If the stakes are high, the miner can mine lots of blocks in a short time by renting hardware, pick the block that has required block hash for him to win, and drop all others.\n\n## Remediation\n\n* Using [commitment scheme](https://en.wikipedia.org/wiki/Commitment_scheme), e.g. [RANDAO](https://github.com/randao/randao).\n* Using external sources of randomness via oracles, e.g. [Oraclize](http://www.oraclize.it/). Note that this approach requires trusting in oracle, thus it may be reasonable to use multiple oracles.\n* Using Bitcoin block hashes, as they are more expensive to mine.\n\n## References\n\n* [How can I securely generate a random number in my smart contract?](https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract)\n* [When can BLOCKHASH be safely used for a random number? When would it be unsafe?](https://ethereum.stackexchange.com/questions/419/when-can-blockhash-be-safely-used-for-a-random-number-when-would-it-be-unsafe)\n* [The Run smart contract](https://etherscan.io/address/0xcac337492149bdb66b088bf5914bedfbf78ccc18)\n", 184 | "content": { 185 | "Title": "Weak Sources of Randomness from Chain Attributes", 186 | "Relationships": "[CWE-330: Use of Insufficiently Random Values](https://cwe.mitre.org/data/definitions/330.html)", 187 | "Description": "Ability to generate random numbers is very helpful in all kinds of applications. One obvious example is gambling DApps, where pseudo-random number generator is used to pick the winner. However, creating a strong enough source of randomness in Ethereum is very challenging. For example, use of `block.timestamp` is insecure, as a miner can choose to provide any timestamp within a few seconds and still get his block accepted by others. Use of `blockhash`, `block.difficulty` and other fields is also insecure, as they're controlled by the miner. If the stakes are high, the miner can mine lots of blocks in a short time by renting hardware, pick the block that has required block hash for him to win, and drop all others.", 188 | "Remediation": "- Using [commitment scheme](https://en.wikipedia.org/wiki/Commitment_scheme), e.g. [RANDAO](https://github.com/randao/randao).\n- Using external sources of randomness via oracles, e.g. [Oraclize](http://www.oraclize.it/). Note that this approach requires trusting in oracle, thus it may be reasonable to use multiple oracles.\n- Using Bitcoin block hashes, as they are more expensive to mine." 189 | } 190 | }, 191 | "SWC-121": { 192 | "markdown": "# Title \nMissing Protection against Signature Replay Attacks\n\n## Relationships\n[CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html)\n\n## Description \n\nIt is sometimes necessary to perform signature verification in smart contracts to achieve better usability or to save gas cost. A secure implementation needs to protect against Signature Replay Attacks by for example keeping track of all processed message hashes and only allowing new message hashes to be processed. A malicious user could attack a contract without such a control and get message hash that was sent by another user processed multiple times. \n\n\n## Remediation\n\nIn order to protect against signature replay attacks consider the following recommendations:\n\n- Store every message hash that has been processed by the smart contract. When new messages are received check against the already existing ones and only proceed with the business logic if it's a new message hash. \n- Include the address of the contract that processes the message. This ensures that the message can only be used in a single contract. \n- Under no circumstances generate the message hash including the signature. The `ecrecover` function is susceptible to signature malleability (see also SWC-117).\n\n## References\n\n- [Medium - Replay Attack Vulnerability in Ethereum Smart Contracts Introduced by transferProxy()](https://medium.com/cypher-core/replay-attack-vulnerability-in-ethereum-smart-contracts-introduced-by-transferproxy-124bf3694e25)\n\n", 193 | "content": { 194 | "Title": "Missing Protection against Signature Replay Attacks", 195 | "Relationships": "[CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html)", 196 | "Description": "It is sometimes necessary to perform signature verification in smart contracts to achieve better usability or to save gas cost. A secure implementation needs to protect against Signature Replay Attacks by for example keeping track of all processed message hashes and only allowing new message hashes to be processed. A malicious user could attack a contract without such a control and get message hash that was sent by another user processed multiple times.", 197 | "Remediation": "In order to protect against signature replay attacks consider the following recommendations:\n\n\n- Store every message hash that has been processed by the smart contract. When new messages are received check against the already existing ones and only proceed with the business logic if it's a new message hash. \n- Include the address of the contract that processes the message. This ensures that the message can only be used in a single contract. \n- Under no circumstances generate the message hash including the signature. The `ecrecover` function is susceptible to signature malleability (see also SWC-117)." 198 | } 199 | }, 200 | "SWC-122": { 201 | "markdown": "# Title \nLack of Proper Signature Verification \n\n## Relationships\n[CWE-345: Insufficient Verification of Data Authenticity](https://cwe.mitre.org/data/definitions/345.html)\n\n## Description \n\nIt is a common pattern for smart contract systems to allow users to sign messages off-chain instead of directly requesting users to do an on-chain transaction because of the flexibility and increased transferability that this provides. Smart contract systems that process signed messages have to implement their own logic to recover the authenticity from the signed messages before they process them further. A limitation for such systems is that smart contracts can not directly interact with them because they can not sign messages. Some signature verification implementations attempt to solve this problem by assuming the validity of a signed message based on other methods that do not have this limitation. An example of such a method is to rely on `msg.sender` and assume that if a signed message originated from the sender address then it has also been created by the sender address. This can lead to vulnerabilities especially in scenarios where proxies can be used to relay transactions.\n\n## Remediation\n\nIt is not recommended to use alternate verification schemes that do not require proper signature verification through `ecrecover()`. \n\n## References\n\n- [Consensys Diligence 0x Audit Report - Insecure signature validator](https://github.com/ConsenSys/0x_audit_report_2018-07-23#32-mixinsignaturevalidator-insecure-signature-validator-signaturetypecaller)\n", 202 | "content": { 203 | "Title": "Lack of Proper Signature Verification", 204 | "Relationships": "[CWE-345: Insufficient Verification of Data Authenticity](https://cwe.mitre.org/data/definitions/345.html)", 205 | "Description": "It is a common pattern for smart contract systems to allow users to sign messages off-chain instead of directly requesting users to do an on-chain transaction because of the flexibility and increased transferability that this provides. Smart contract systems that process signed messages have to implement their own logic to recover the authenticity from the signed messages before they process them further. A limitation for such systems is that smart contracts can not directly interact with them because they can not sign messages. Some signature verification implementations attempt to solve this problem by assuming the validity of a signed message based on other methods that do not have this limitation. An example of such a method is to rely on `msg.sender` and assume that if a signed message originated from the sender address then it has also been created by the sender address. This can lead to vulnerabilities especially in scenarios where proxies can be used to relay transactions.", 206 | "Remediation": "It is not recommended to use alternate verification schemes that do not require proper signature verification through `ecrecover()`." 207 | } 208 | }, 209 | "SWC-123": { 210 | "markdown": "# Title\nRequirement Violation\n\n## Relationships\n\n[CWE-573: Improper Following of Specification by Caller](https://cwe.mitre.org/data/definitions/573.html)\n\n## Description\n\nThe Solidity `require()` construct is meant to validate external inputs of a function. In most cases, such external inputs are provided by callers, but they may also be returned by callees. In the former case, we refer to them as precondition violations. Violations of a requirement can indicate one of two possible issues:\n\n1. A bug exists in the contract that provided the external input.\n2. The condition used to express the requirement is too strong.\n\n## Remediation\n\nIf the required logical condition is too strong, it should be weakened to allow all valid external inputs.\n\nOtherwise, the bug must be in the contract that provided the external input and one should consider fixing its code by making sure no invalid inputs are provided.\n\n## References\n\n- [The use of revert(), assert(), and require() in Solidity, and the new REVERT opcode in the EVM](https://media.consensys.net/when-to-use-revert-assert-and-require-in-solidity-61fb2c0e5a57)\n", 211 | "content": { 212 | "Title": "Requirement Violation", 213 | "Relationships": "[CWE-573: Improper Following of Specification by Caller](https://cwe.mitre.org/data/definitions/573.html)", 214 | "Description": "The Solidity `require()` construct is meant to validate external inputs of a function. In most cases, such external inputs are provided by callers, but they may also be returned by callees. In the former case, we refer to them as precondition violations. Violations of a requirement can indicate one of two possible issues:\n\n\n1. A bug exists in the contract that provided the external input.\n1. The condition used to express the requirement is too strong.", 215 | "Remediation": "If the required logical condition is too strong, it should be weakened to allow all valid external inputs.\n\n\nOtherwise, the bug must be in the contract that provided the external input and one should consider fixing its code by making sure no invalid inputs are provided." 216 | } 217 | }, 218 | "SWC-124": { 219 | "markdown": "# Title\r\nWrite to Arbitrary Storage Location\r\n\r\n## Relationships\r\n\r\n[CWE-123: Write-what-where Condition](https://cwe.mitre.org/data/definitions/123.html)\r\n\r\n## Description\r\n\r\nA smart contract's data (e.g., storing the owner of the contract) is persistently stored\r\nat some storage location (i.e., a key or address) on the EVM level. The contract is\r\nresponsible for ensuring that only authorized user or contract accounts may write to\r\nsensitive storage locations. If an attacker is able to write to arbitrary storage\r\nlocations of a contract, the authorization checks may easily be circumvented. This can\r\nallow an attacker to corrupt the storage; for instance, by overwriting a field that stores\r\nthe address of the contract owner.\r\n\r\n## Remediation\r\n\r\nAs a general advice, given that all data structures share the same storage (address)\r\nspace, one should make sure that writes to one data structure cannot inadvertently\r\noverwrite entries of another data structure.\r\n\r\n## References\r\n\r\n- [Entry to Underhanded Solidity Coding Contest 2017 (honorable mention)](https://github.com/Arachnid/uscc/tree/master/submissions-2017/doughoyte)\r\n", 220 | "content": { 221 | "Title": "Write to Arbitrary Storage Location", 222 | "Relationships": "[CWE-123: Write-what-where Condition](https://cwe.mitre.org/data/definitions/123.html)", 223 | "Description": "A smart contract's data (e.g., storing the owner of the contract) is persistently stored\nat some storage location (i.e., a key or address) on the EVM level. The contract is\nresponsible for ensuring that only authorized user or contract accounts may write to\nsensitive storage locations. If an attacker is able to write to arbitrary storage\nlocations of a contract, the authorization checks may easily be circumvented. This can\nallow an attacker to corrupt the storage; for instance, by overwriting a field that stores\nthe address of the contract owner.", 224 | "Remediation": "As a general advice, given that all data structures share the same storage (address)\nspace, one should make sure that writes to one data structure cannot inadvertently\noverwrite entries of another data structure." 225 | } 226 | }, 227 | "SWC-125": { 228 | "markdown": "# Title \nIncorrect Inheritance Order\n\n## Relationships\n[CWE-696: Incorrect Behavior Order](https://cwe.mitre.org/data/definitions/696.html)\n\n## Description \nSolidity supports multiple inheritance, meaning that one contract can inherit several contracts. Multiple inheritance introduces ambiguity called [Diamond Problem](https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem): if two or more base contracts define the same function, which one should be called in the child contract? Solidity deals with this ambiguity by using reverse [C3 Linearization](https://en.wikipedia.org/wiki/C3_linearization), which sets a priority between base contracts.\n\nThat way, base contracts have different priorities, so the order of inheritance matters. Neglecting inheritance order can lead to unexpected behavior.\n\n## Remediation\nWhen inheriting multiple contracts, especially if they have identical functions, a developer should carefully specify inheritance in the correct order. The rule of thumb is to inherit contracts from more /general/ to more /specific/.\n\n## References \n* [Smart Contract Best Practices - Multiple Inheritance Caution](https://consensys.github.io/smart-contract-best-practices/recommendations/#multiple-inheritance-caution)\n* [Solidity docs - Multiple Inheritance and Linearization](https://solidity.readthedocs.io/en/v0.4.25/contracts.html#multiple-inheritance-and-linearization)\n* [Solidity anti-patterns: Fun with inheritance DAG abuse](https://pdaian.com/blog/solidity-anti-patterns-fun-with-inheritance-dag-abuse)\n", 229 | "content": { 230 | "Title": "Incorrect Inheritance Order", 231 | "Relationships": "[CWE-696: Incorrect Behavior Order](https://cwe.mitre.org/data/definitions/696.html)", 232 | "Description": "Solidity supports multiple inheritance, meaning that one contract can inherit several contracts. Multiple inheritance introduces ambiguity called [Diamond Problem](https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem): if two or more base contracts define the same function, which one should be called in the child contract? Solidity deals with this ambiguity by using reverse [C3 Linearization](https://en.wikipedia.org/wiki/C3_linearization), which sets a priority between base contracts.\n\n\nThat way, base contracts have different priorities, so the order of inheritance matters. Neglecting inheritance order can lead to unexpected behavior.", 233 | "Remediation": "When inheriting multiple contracts, especially if they have identical functions, a developer should carefully specify inheritance in the correct order. The rule of thumb is to inherit contracts from more /general/ to more /specific/." 234 | } 235 | }, 236 | "SWC-126": { 237 | "markdown": "# Title\nInsufficient Gas Griefing\n\n## Relationships\n[CWE-691: Insufficient Control Flow Management](https://cwe.mitre.org/data/definitions/691.html)\n\n## Description\nInsufficient gas griefing attacks can be performed on contracts which accept data and use it in a sub-call on another contract. If the sub-call fails, either the whole transaction is reverted, or execution is continued. In the case of a relayer contract, the user who executes the transaction, the 'forwarder', can effectively censor transactions by using just enough gas to execute the transaction, but not enough for the sub-call to succeed.\n\n## Remediation\nThere are two options to prevent insufficient gas griefing:\n\n- Only allow trusted users to relay transactions.\n- Require that the forwarder provides enough gas.\n\n## References\n- [Consensys Smart Contract Best Practices](https://consensys.github.io/smart-contract-best-practices/known_attacks/#insufficient-gas-griefing)\n- [What does griefing mean?](https://ethereum.stackexchange.com/questions/62829/what-does-griefing-mean)\n- [Griefing Attacks: Are they profitable for the attacker?](https://ethereum.stackexchange.com/questions/73261/griefing-attacks-are-they-profitable-for-the-attacker)", 238 | "content": { 239 | "Title": "Insufficient Gas Griefing", 240 | "Relationships": "[CWE-691: Insufficient Control Flow Management](https://cwe.mitre.org/data/definitions/691.html)", 241 | "Description": "Insufficient gas griefing attacks can be performed on contracts which accept data and use it in a sub-call on another contract. If the sub-call fails, either the whole transaction is reverted, or execution is continued. In the case of a relayer contract, the user who executes the transaction, the 'forwarder', can effectively censor transactions by using just enough gas to execute the transaction, but not enough for the sub-call to succeed.", 242 | "Remediation": "There are two options to prevent insufficient gas griefing:\n\n\n- Only allow trusted users to relay transactions.\n- Require that the forwarder provides enough gas." 243 | } 244 | }, 245 | "SWC-127": { 246 | "markdown": "# Title \nArbitrary Jump with Function Type Variable\n\n## Relationships\n[CWE-695: Use of Low-Level Functionality](https://cwe.mitre.org/data/definitions/695.html)\n\n## Description \nSolidity supports function types. That is, a variable of function type can be assigned with a reference to a function with a matching signature. The function saved to such variable can be called just like a regular function.\n\nThe problem arises when a user has the ability to arbitrarily change the function type variable and thus execute random code instructions. As Solidity doesn't support pointer arithmetics, it's impossible to change such variable to an arbitrary value. However, if the developer uses assembly instructions, such as `mstore` or assign operator, in the worst case scenario an attacker is able to point a function type variable to any code instruction, violating required validations and required state changes.\n\n## Remediation\nThe use of assembly should be minimal. A developer should not allow a user to assign arbitrary values to function type variables.\n\n## References \n* [Solidity CTF](https://medium.com/authio/solidity-ctf-part-2-safe-execution-ad6ded20e042)\n* [Solidity docs - Solidity Assembly](https://solidity.readthedocs.io/en/v0.4.25/assembly.html)\n* [Solidity docs - Function Types](https://solidity.readthedocs.io/en/v0.4.25/types.html#function-types)\n", 247 | "content": { 248 | "Title": "Arbitrary Jump with Function Type Variable", 249 | "Relationships": "[CWE-695: Use of Low-Level Functionality](https://cwe.mitre.org/data/definitions/695.html)", 250 | "Description": "Solidity supports function types. That is, a variable of function type can be assigned with a reference to a function with a matching signature. The function saved to such variable can be called just like a regular function.\n\n\nThe problem arises when a user has the ability to arbitrarily change the function type variable and thus execute random code instructions. As Solidity doesn't support pointer arithmetics, it's impossible to change such variable to an arbitrary value. However, if the developer uses assembly instructions, such as `mstore` or assign operator, in the worst case scenario an attacker is able to point a function type variable to any code instruction, violating required validations and required state changes.", 251 | "Remediation": "The use of assembly should be minimal. A developer should not allow a user to assign arbitrary values to function type variables." 252 | } 253 | }, 254 | "SWC-128": { 255 | "markdown": "# Title\nDoS With Block Gas Limit\n\n## Relationships\n[CWE-400: Uncontrolled Resource Consumption](https://cwe.mitre.org/data/definitions/400.html)\n\n## Description\n\nWhen smart contracts are deployed or functions inside them are called, the execution of these actions always requires a certain amount of gas, based of how much computation is needed to complete them. The Ethereum network specifies a block gas limit and the sum of all transactions included in a block can not exceed the threshold. \n\nProgramming patterns that are harmless in centralized applications can lead to Denial of Service conditions in smart contracts when the cost of executing a function exceeds the block gas limit. Modifying an array of unknown size, that increases in size over time, can lead to such a Denial of Service condition.\n\n## Remediation\n\nCaution is advised when you expect to have large arrays that grow over time. Actions that require looping across the entire data structure should be avoided. \n\nIf you absolutely must loop over an array of unknown size, then you should plan for it to potentially take multiple blocks, and therefore require multiple transactions.\n\n## References\n* [Ethereum Design Rationale](https://github.com/ethereum/wiki/wiki/Design-Rationale#gas-and-fees)\n* [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)\n* [Clear Large Array Without Blowing Gas Limit](https://ethereum.stackexchange.com/questions/3373/how-to-clear-large-arrays-without-blowing-the-gas-limit)\n* [GovernMental jackpot payout DoS Gas](https://www.reddit.com/r/ethereum/comments/4ghzhv/governmentals_1100_eth_jackpot_payout_is_stuck/)\n\n", 256 | "content": { 257 | "Title": "DoS With Block Gas Limit", 258 | "Relationships": "[CWE-400: Uncontrolled Resource Consumption](https://cwe.mitre.org/data/definitions/400.html)", 259 | "Description": "When smart contracts are deployed or functions inside them are called, the execution of these actions always requires a certain amount of gas, based of how much computation is needed to complete them. The Ethereum network specifies a block gas limit and the sum of all transactions included in a block can not exceed the threshold. \n\n\nProgramming patterns that are harmless in centralized applications can lead to Denial of Service conditions in smart contracts when the cost of executing a function exceeds the block gas limit. Modifying an array of unknown size, that increases in size over time, can lead to such a Denial of Service condition.", 260 | "Remediation": "Caution is advised when you expect to have large arrays that grow over time. Actions that require looping across the entire data structure should be avoided. \n\n\nIf you absolutely must loop over an array of unknown size, then you should plan for it to potentially take multiple blocks, and therefore require multiple transactions." 261 | } 262 | }, 263 | "SWC-129": { 264 | "markdown": "# Title\nTypographical Error\n\n## Relationships\n[CWE-480: Use of Incorrect Operator](https://cwe.mitre.org/data/definitions/480.html)\n\n## Description\nA typographical error can occur for example when the intent of a defined operation is to sum a number to a variable (+=) but it has accidentally been defined in a wrong way (=+), introducing a typo which happens to be a valid operator. Instead of calculating the sum it initializes the variable again. \n\nThe unary + operator is deprecated in new solidity compiler versions.\n\n## Remediation\nThe weakness can be avoided by performing pre-condition checks on any math operation or using a vetted library for arithmetic calculations such as SafeMath developed by OpenZeppelin.\n\n## References\n* [HackerGold Bug Analysis](https://blog.zeppelin.solutions/hackergold-bug-analysis-68d893cad738)\n* [SafeMath by OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol)\n* [Disallow Unary plus](https://github.com/ethereum/solidity/issues/1760)\n", 265 | "content": { 266 | "Title": "Typographical Error", 267 | "Relationships": "[CWE-480: Use of Incorrect Operator](https://cwe.mitre.org/data/definitions/480.html)", 268 | "Description": "A typographical error can occur for example when the intent of a defined operation is to sum a number to a variable (+=) but it has accidentally been defined in a wrong way (=+), introducing a typo which happens to be a valid operator. Instead of calculating the sum it initializes the variable again. \n\n\nThe unary + operator is deprecated in new solidity compiler versions.", 269 | "Remediation": "The weakness can be avoided by performing pre-condition checks on any math operation or using a vetted library for arithmetic calculations such as SafeMath developed by OpenZeppelin." 270 | } 271 | }, 272 | "SWC-130": { 273 | "markdown": "# Title\nRight-To-Left-Override control character (U+202E)\n\n## Relationships\n[CWE-451: User Interface (UI) Misrepresentation of Critical Information](http://cwe.mitre.org/data/definitions/451.html)\n\n## Description\nMalicious actors can use the Right-To-Left-Override unicode character to force RTL text rendering and confuse users as to the real intent of a contract. \n\n## Remediation\nThere are very few legitimate uses of the U+202E character. It should not appear in the source code of a smart contract.\n\n## References\n* [Outsmarting Smart Contracts](https://youtu.be/P_Mtd5Fc_3E?t=1813)", 274 | "content": { 275 | "Title": "Right-To-Left-Override control character (U+202E)", 276 | "Relationships": "[CWE-451: User Interface (UI) Misrepresentation of Critical Information](http://cwe.mitre.org/data/definitions/451.html)", 277 | "Description": "Malicious actors can use the Right-To-Left-Override unicode character to force RTL text rendering and confuse users as to the real intent of a contract.", 278 | "Remediation": "There are very few legitimate uses of the U+202E character. It should not appear in the source code of a smart contract." 279 | } 280 | }, 281 | "SWC-131": { 282 | "markdown": "# Title\nPresence of unused variables\n\n## Relationships\n[CWE-1164: Irrelevant Code](https://cwe.mitre.org/data/definitions/1164.html)\n\n## Description\n Unused variables are allowed in Solidity and they do not pose a direct security issue. It is best practice though to avoid them as they can:\n\n* cause an increase in computations (and unnecessary gas consumption)\n* indicate bugs or malformed data structures and they are generally a sign of poor code quality\n* cause code noise and decrease readability of the code\n\n## Remediation\nRemove all unused variables from the code base. \n\n## References\n* [Unused local variables warnings discussion](https://github.com/ethereum/solidity/issues/718)\n* [Shadowing of inherited state variables discussion](https://github.com/ethereum/solidity/issues/2563)\n", 283 | "content": { 284 | "Title": "Presence of unused variables", 285 | "Relationships": "[CWE-1164: Irrelevant Code](https://cwe.mitre.org/data/definitions/1164.html)", 286 | "Description": "Unused variables are allowed in Solidity and they do not pose a direct security issue. It is best practice though to avoid them as they can:\n\n\n- cause an increase in computations (and unnecessary gas consumption)\n- indicate bugs or malformed data structures and they are generally a sign of poor code quality\n- cause code noise and decrease readability of the code", 287 | "Remediation": "Remove all unused variables from the code base." 288 | } 289 | }, 290 | "SWC-132": { 291 | "markdown": "# Title\nUnexpected Ether balance\n\n## Relationships\n[CWE-667: Improper Locking](https://cwe.mitre.org/data/definitions/667.html)\n\n## Description\nContracts can behave erroneously when they strictly assume a specific Ether balance. It is always possible to forcibly send ether to a contract (without triggering its fallback function), using selfdestruct, or by mining to the account. In the worst case scenario this could lead to DOS conditions that might render the contract unusable. \n\n## Remediation\nAvoid strict equality checks for the Ether balance in a contract.\n\n## References\n* [Consensys Best Practices: Forcibly Sending Ether](https://consensys.github.io/smart-contract-best-practices/known_attacks/#forcibly-sending-ether-to-a-contract)\n* [Sigmaprime: Unexpected Ether](https://blog.sigmaprime.io/solidity-security.html#ether)\n* [Gridlock (a smart contract bug)](https://medium.com/@nmcl/gridlock-a-smart-contract-bug-73b8310608a9)\n", 292 | "content": { 293 | "Title": "Unexpected Ether balance", 294 | "Relationships": "[CWE-667: Improper Locking](https://cwe.mitre.org/data/definitions/667.html)", 295 | "Description": "Contracts can behave erroneously when they strictly assume a specific Ether balance. It is always possible to forcibly send ether to a contract (without triggering its fallback function), using selfdestruct, or by mining to the account. In the worst case scenario this could lead to DOS conditions that might render the contract unusable.", 296 | "Remediation": "Avoid strict equality checks for the Ether balance in a contract." 297 | } 298 | }, 299 | "SWC-133": { 300 | "markdown": "# Title\nHash Collisions With Multiple Variable Length Arguments\n\n## Relationships\n[CWE-294: Authentication Bypass by Capture-replay](https://cwe.mitre.org/data/definitions/294.html)\n\n## Description\nUsing `abi.encodePacked()` with multiple variable length arguments can, in certain situations, lead to a hash collision. Since `abi.encodePacked()` packs all elements in order regardless of whether they're part of an array, you can move elements between arrays and, so long as all elements are in the same order, it will return the same encoding. In a signature verification situation, an attacker could exploit this by modifying the position of elements in a previous function call to effectively bypass authorization.\n\n## Remediation\nWhen using `abi.encodePacked()`, it's crucial to ensure that a matching signature cannot be achieved using different parameters. To do so, either do not allow users access to parameters used in `abi.encodePacked()`, or use fixed length arrays. Alternatively, you can simply use `abi.encode()` instead.\n\nIt is also recommended that you use replay protection (see [SWC-121](./SWC-121.md)), although an attacker can still bypass this by [front-running](./SWC-114.md).\n\n## References\n- [Solidity Non-standard Packed Mode](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html#non-standard-packed-mode)\n- [Hash Collision Attack](https://learncryptography.com/hash-functions/hash-collision-attack)\n", 301 | "content": { 302 | "Title": "Hash Collisions With Multiple Variable Length Arguments", 303 | "Relationships": "[CWE-294: Authentication Bypass by Capture-replay](https://cwe.mitre.org/data/definitions/294.html)", 304 | "Description": "Using `abi.encodePacked()` with multiple variable length arguments can, in certain situations, lead to a hash collision. Since `abi.encodePacked()` packs all elements in order regardless of whether they're part of an array, you can move elements between arrays and, so long as all elements are in the same order, it will return the same encoding. In a signature verification situation, an attacker could exploit this by modifying the position of elements in a previous function call to effectively bypass authorization.", 305 | "Remediation": "When using `abi.encodePacked()`, it's crucial to ensure that a matching signature cannot be achieved using different parameters. To do so, either do not allow users access to parameters used in `abi.encodePacked()`, or use fixed length arrays. Alternatively, you can simply use `abi.encode()` instead.\n\n\nIt is also recommended that you use replay protection (see [SWC-121](./SWC-121.md)), although an attacker can still bypass this by [front-running](./SWC-114.md)." 306 | } 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmartContractSecurity/SWC-registry-python/7a0b93dec1a5c2bc706ed6c0c2aadf1a8b549b77/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_get_entry_info.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import json 3 | import os 4 | 5 | from unittest.mock import MagicMock 6 | from swc_registry.get_entry_info import SWC 7 | from swc_registry.get_entry_info import SWCRegistry 8 | 9 | 10 | class TestMethods(unittest.TestCase): 11 | def setUp(self): 12 | with open( 13 | os.path.dirname(__file__) + "/../swc_registry/swc-definition.json", encoding="utf-8" 14 | ) as f: 15 | self.object = json.load(f) 16 | self.swc = SWC("SWC-100") 17 | SWCRegistry()._load_from_file() 18 | 19 | def test_get_title(self): 20 | self.assertEqual(self.swc.title, self.object["SWC-100"]["content"]["Title"]) 21 | 22 | def test_get_relationships(self): 23 | self.assertEqual( 24 | self.swc.relationships, self.object["SWC-100"]["content"]["Relationships"] 25 | ) 26 | 27 | def test_get_description(self): 28 | self.assertEqual( 29 | self.swc.description, self.object["SWC-100"]["content"]["Description"] 30 | ) 31 | 32 | def test_get_remediation(self): 33 | self.assertEqual( 34 | self.swc.remediation, self.object["SWC-100"]["content"]["Remediation"] 35 | ) 36 | 37 | def test_get_last_version(self): 38 | # Act 39 | after_content = SWCRegistry().content 40 | after_content["SWC-100"]["content"]["Title"] = "Brick" 41 | SWCRegistry._get_latest_version = MagicMock(return_value=after_content) 42 | 43 | SWCRegistry().update() 44 | 45 | # Assert 46 | new_title = self.swc.title 47 | self.assertEqual(new_title, "Brick") 48 | 49 | 50 | if __name__ == "__main__": 51 | unittest.main() 52 | --------------------------------------------------------------------------------