diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 08a6c9275..6c8cf1053 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,6 +40,13 @@ repos: - id: flake8 additional_dependencies: [flake8-docstrings, flake8-bugbear, flake8-builtins, flake8-print, flake8-pytest-style, flake8-return, flake8-simplify, flake8-annotations] +- repo: https://github.com/PyCQA/bandit + rev: 1.7.0 + hooks: + - id: bandit + args: [-x, 'tests'] + + #- repo: https://github.com/pre-commit/mirrors-mypy # rev: v0.740 # hooks: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2685dbdea..dffbd1abd 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -45,10 +45,15 @@ stages: poetry run pre-commit run docformatter --all-files displayName: 'Docstring formating (docformatter)' + - script: | + poetry run pre-commit run bandit --all-files + displayName: 'Potential security issues (bandit)' + - script: | poetry run sphinx-build docs/ generated_docs displayName: 'Documentation build (sphinx)' + - stage: "Tests" jobs: - job: "Tests" diff --git a/miio/airconditioningcompanionMCN.py b/miio/airconditioningcompanionMCN.py index 4d583fb62..1c2113322 100644 --- a/miio/airconditioningcompanionMCN.py +++ b/miio/airconditioningcompanionMCN.py @@ -132,7 +132,7 @@ def __init__( model: str = MODEL_ACPARTNER_MCN02, ) -> None: if start_id is None: - start_id = random.randint(0, 999) + start_id = random.randint(0, 999) # nosec super().__init__(ip, token, start_id, debug, lazy_discover) if model != MODEL_ACPARTNER_MCN02: diff --git a/miio/extract_tokens.py b/miio/extract_tokens.py index 59c9c9393..bf9f8af37 100644 --- a/miio/extract_tokens.py +++ b/miio/extract_tokens.py @@ -2,12 +2,12 @@ import logging import sqlite3 import tempfile -import xml.etree.ElementTree as ET from pprint import pformat as pf from typing import Iterator import attr import click +import defusedxml.ElementTree as ET from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes @@ -80,7 +80,9 @@ def decrypt_ztoken(ztoken): keystring = "00000000000000000000000000000000" key = bytes.fromhex(keystring) - cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend()) + cipher = Cipher( # nosec + algorithms.AES(key), modes.ECB(), backend=default_backend() + ) decryptor = cipher.decryptor() token = decryptor.update(bytes.fromhex(ztoken[:64])) + decryptor.finalize() diff --git a/miio/protocol.py b/miio/protocol.py index 9a7d59ad3..8c6ec09e3 100644 --- a/miio/protocol.py +++ b/miio/protocol.py @@ -57,7 +57,7 @@ def verify_token(token: bytes): @staticmethod def md5(data: bytes) -> bytes: """Calculates a md5 hashsum for the given bytes object.""" - checksum = hashlib.md5() + checksum = hashlib.md5() # nosec checksum.update(data) return checksum.digest() diff --git a/miio/updater.py b/miio/updater.py index 3eb76dbf3..1ea89807e 100644 --- a/miio/updater.py +++ b/miio/updater.py @@ -55,7 +55,7 @@ def __init__(self, file, interface=None): with open(file, "rb") as f: self.payload = f.read() self.server.payload = self.payload - self.md5 = hashlib.md5(self.payload).hexdigest() + self.md5 = hashlib.md5(self.payload).hexdigest() # nosec _LOGGER.info("Using local %s (md5: %s)" % (file, self.md5)) @staticmethod @@ -93,5 +93,5 @@ def serve_once(self): if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) - upd = OneShotServer("/tmp/test") + upd = OneShotServer("/tmp/test") # nosec upd.serve_once() diff --git a/miio/vacuum_cli.py b/miio/vacuum_cli.py index 8beb24f54..97cffae4f 100644 --- a/miio/vacuum_cli.py +++ b/miio/vacuum_cli.py @@ -627,7 +627,8 @@ def update_firmware(vac: miio.Vacuum, url: str, md5: str, ip: str): try: state = vac.update_state() progress = vac.update_progress() - except: # we may not get our messages through during upload # noqa + except: # noqa # nosec + # we may not get our messages through during uploads continue if state == UpdateState.Installing: diff --git a/poetry.lock b/poetry.lock index 3f3d3e7e1..5a4615f2b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -159,6 +159,14 @@ pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] ssh = ["bcrypt (>=3.1.5)"] test = ["pytest (>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] +[[package]] +name = "defusedxml" +version = "0.6.0" +description = "XML bomb protection for Python stdlib modules" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + [[package]] name = "distlib" version = "0.3.1" @@ -835,7 +843,7 @@ docs = ["sphinx", "sphinx_click", "sphinxcontrib-apidoc", "sphinx_rtd_theme"] [metadata] lock-version = "1.1" python-versions = "^3.6.5" -content-hash = "94ae90925ebb324489695a32c48375dccd8f6ed8b21da8f1e1fc83a316d1502e" +content-hash = "56085dcde8f728f9cac961433c52b7e368cf17e53a4825802bb55e195f24b5dc" [metadata.files] alabaster = [ @@ -993,6 +1001,10 @@ cryptography = [ {file = "cryptography-3.3.2-cp36-abi3-win_amd64.whl", hash = "sha256:7951a966613c4211b6612b0352f5bf29989955ee592c4a885d8c7d0f830d0433"}, {file = "cryptography-3.3.2.tar.gz", hash = "sha256:5a60d3780149e13b7a6ff7ad6526b38846354d11a15e21068e57073e29e19bed"}, ] +defusedxml = [ + {file = "defusedxml-0.6.0-py2.py3-none-any.whl", hash = "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93"}, + {file = "defusedxml-0.6.0.tar.gz", hash = "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"}, +] distlib = [ {file = "distlib-0.3.1-py2.py3-none-any.whl", hash = "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb"}, {file = "distlib-0.3.1.zip", hash = "sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1"}, diff --git a/pyproject.toml b/pyproject.toml index 958aa7d8f..62714e61b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,7 @@ netifaces = "^0" android_backup = { version = "^0", optional = true } importlib_metadata = { version = "^1", markers = "python_version <= '3.7'" } croniter = "^0" +defusedxml = "^0.6" sphinx = { version = "^3", optional = true } sphinx_click = { version = "^2", optional = true }