From e8228f1aa6ee5e49e6ad622f16cf20063584323d Mon Sep 17 00:00:00 2001 From: "Pieter De Cremer (Semgrep)" Date: Thu, 11 Jan 2024 09:22:09 +0100 Subject: [PATCH 1/3] Add fixes to python cryptography rules (#3267) * Add fixes to python cryptography rules * Move rule test syntaxt to reflect focus metavariable changes * update mode recommendation to gcn * update fixtest to reflect changes to fix --- .../insecure-cipher-algorithms-arc4.fixed.py | 17 ++++++++++ .../insecure-cipher-algorithms-arc4.yaml | 12 ++++++- ...secure-cipher-algorithms-blowfish.fixed.py | 18 ++++++++++ .../insecure-cipher-algorithms-blowfish.yaml | 11 ++++++- .../insecure-cipher-algorithms.fixed.py | 17 ++++++++++ .../security/insecure-cipher-algorithms.yaml | 11 ++++++- .../insecure-cipher-mode-ecb.fixed.py | 17 ++++++++++ .../security/insecure-cipher-mode-ecb.yaml | 5 +-- .../insecure-hash-algorithms-md5.fixed.py | 10 ++++++ .../insecure-hash-algorithms-md5.yaml | 8 ++++- .../insufficient-dsa-key-size.fixed.py | 18 ++++++++++ .../security/insufficient-dsa-key-size.yaml | 3 ++ .../insufficient-rsa-key-size.fixed.py | 33 +++++++++++++++++++ .../security/insufficient-rsa-key-size.py | 12 +++---- .../security/insufficient-rsa-key-size.yaml | 3 ++ 15 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 python/cryptography/security/insecure-cipher-algorithms-arc4.fixed.py create mode 100644 python/cryptography/security/insecure-cipher-algorithms-blowfish.fixed.py create mode 100644 python/cryptography/security/insecure-cipher-algorithms.fixed.py create mode 100644 python/cryptography/security/insecure-cipher-mode-ecb.fixed.py create mode 100644 python/cryptography/security/insecure-hash-algorithms-md5.fixed.py create mode 100644 python/cryptography/security/insufficient-dsa-key-size.fixed.py create mode 100644 python/cryptography/security/insufficient-rsa-key-size.fixed.py diff --git a/python/cryptography/security/insecure-cipher-algorithms-arc4.fixed.py b/python/cryptography/security/insecure-cipher-algorithms-arc4.fixed.py new file mode 100644 index 0000000000..063ca70214 --- /dev/null +++ b/python/cryptography/security/insecure-cipher-algorithms-arc4.fixed.py @@ -0,0 +1,17 @@ +# cf. https://github.com/PyCQA/bandit/blob/b78c938c0bd03d201932570f5e054261e10c5750/examples/ciphers.py + +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers import algorithms +from cryptography.hazmat.primitives.ciphers import modes +from cryptography.hazmat.backends import default_backend +from struct import pack + +# ruleid:insecure-cipher-algorithm-arc4 +cipher = Cipher(algorithms.AES(key), mode=None, backend=default_backend()) +encryptor = cipher.encryptor() +ct = encryptor.update(b"a secret message") + +# ok:insecure-cipher-algorithm-arc4 +cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) +encryptor = cipher.encryptor() +ct = encryptor.update(b"a secret message") + encryptor.finalize() diff --git a/python/cryptography/security/insecure-cipher-algorithms-arc4.yaml b/python/cryptography/security/insecure-cipher-algorithms-arc4.yaml index a914878d06..d144ff1d60 100644 --- a/python/cryptography/security/insecure-cipher-algorithms-arc4.yaml +++ b/python/cryptography/security/insecure-cipher-algorithms-arc4.yaml @@ -1,10 +1,12 @@ rules: - id: insecure-cipher-algorithm-arc4 - pattern: cryptography.hazmat.primitives.ciphers.algorithms.ARC4(...) message: >- ARC4 (Alleged RC4) is a stream cipher with serious weaknesses in its initial stream output. Its use is strongly discouraged. ARC4 does not use mode constructions. Use a strong symmetric cipher such as EAS instead. + With the `cryptography` package it is recommended to use the `Fernet` which is a secure implementation + of AES in CBC mode with a 128-bit key. + Alternatively, keep using the `Cipher` class from the hazmat primitives but use the AES algorithm instead. metadata: source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L98 cwe: @@ -28,3 +30,11 @@ rules: severity: WARNING languages: - python + patterns: + - pattern: cryptography.hazmat.primitives.ciphers.algorithms.$ARC4($KEY) + - pattern-inside: cryptography.hazmat.primitives.ciphers.Cipher(...) + - metavariable-regex: + metavariable: $ARC4 + regex: ^(ARC4)$ + - focus-metavariable: $ARC4 + fix: AES diff --git a/python/cryptography/security/insecure-cipher-algorithms-blowfish.fixed.py b/python/cryptography/security/insecure-cipher-algorithms-blowfish.fixed.py new file mode 100644 index 0000000000..edb9fd8ad6 --- /dev/null +++ b/python/cryptography/security/insecure-cipher-algorithms-blowfish.fixed.py @@ -0,0 +1,18 @@ +# cf. https://github.com/PyCQA/bandit/blob/b78c938c0bd03d201932570f5e054261e10c5750/examples/ciphers.py + +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers import algorithms +from cryptography.hazmat.primitives.ciphers import modes +from cryptography.hazmat.backends import default_backend +from struct import pack + + +# ruleid:insecure-cipher-algorithm-blowfish +cipher = Cipher(algorithms.AES(key), mode=None, backend=default_backend()) +encryptor = cipher.encryptor() +ct = encryptor.update(b"a secret message") + +# ok:insecure-cipher-algorithm-blowfish +cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) +encryptor = cipher.encryptor() +ct = encryptor.update(b"a secret message") + encryptor.finalize() diff --git a/python/cryptography/security/insecure-cipher-algorithms-blowfish.yaml b/python/cryptography/security/insecure-cipher-algorithms-blowfish.yaml index 96a16b48a2..2005b698c6 100644 --- a/python/cryptography/security/insecure-cipher-algorithms-blowfish.yaml +++ b/python/cryptography/security/insecure-cipher-algorithms-blowfish.yaml @@ -1,9 +1,11 @@ rules: - id: insecure-cipher-algorithm-blowfish - pattern: cryptography.hazmat.primitives.ciphers.algorithms.Blowfish(...) message: >- Blowfish is a block cipher developed by Bruce Schneier. It is known to be susceptible to attacks when using weak keys. The author has recommended that users of Blowfish move to newer algorithms such as AES. + With the `cryptography` package it is recommended to use `Fernet` which is a secure implementation + of AES in CBC mode with a 128-bit key. + Alternatively, keep using the `Cipher` class from the hazmat primitives but use the AES algorithm instead. metadata: source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L98 cwe: @@ -28,3 +30,10 @@ rules: severity: WARNING languages: - python + patterns: + - pattern: cryptography.hazmat.primitives.ciphers.algorithms.$BLOWFISH($KEY) + - metavariable-regex: + metavariable: $BLOWFISH + regex: ^(Blowfish)$ + - focus-metavariable: $BLOWFISH + fix: AES diff --git a/python/cryptography/security/insecure-cipher-algorithms.fixed.py b/python/cryptography/security/insecure-cipher-algorithms.fixed.py new file mode 100644 index 0000000000..539c88d319 --- /dev/null +++ b/python/cryptography/security/insecure-cipher-algorithms.fixed.py @@ -0,0 +1,17 @@ +# cf. https://github.com/PyCQA/bandit/blob/b78c938c0bd03d201932570f5e054261e10c5750/examples/ciphers.py + +from cryptography.hazmat.primitives.ciphers import Cipher +from cryptography.hazmat.primitives.ciphers import algorithms +from cryptography.hazmat.primitives.ciphers import modes +from cryptography.hazmat.backends import default_backend +from struct import pack + +# ruleid:insecure-cipher-algorithm-idea +cipher = Cipher(algorithms.AES(key), mode=None, backend=default_backend()) +encryptor = cipher.encryptor() +ct = encryptor.update(b"a secret message") + +# ok:insecure-cipher-algorithm-idea +cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) +encryptor = cipher.encryptor() +ct = encryptor.update(b"a secret message") + encryptor.finalize() diff --git a/python/cryptography/security/insecure-cipher-algorithms.yaml b/python/cryptography/security/insecure-cipher-algorithms.yaml index 2748dfc16b..37289904a8 100644 --- a/python/cryptography/security/insecure-cipher-algorithms.yaml +++ b/python/cryptography/security/insecure-cipher-algorithms.yaml @@ -1,11 +1,13 @@ rules: - id: insecure-cipher-algorithm-idea - pattern: cryptography.hazmat.primitives.ciphers.algorithms.IDEA(...) message: >- IDEA (International Data Encryption Algorithm) is a block cipher created in 1991. It is an optional component of the OpenPGP standard. This cipher is susceptible to attacks when using weak keys. It is recommended that you do not use this cipher for new applications. Use a strong symmetric cipher such as EAS instead. + With the `cryptography` package it is recommended to use `Fernet` which is a secure implementation + of AES in CBC mode with a 128-bit key. + Alternatively, keep using the `Cipher` class from the hazmat primitives but use the AES algorithm instead. metadata: source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L98 cwe: @@ -30,3 +32,10 @@ rules: severity: WARNING languages: - python + patterns: + - pattern: cryptography.hazmat.primitives.ciphers.algorithms.$IDEA($KEY) + - metavariable-regex: + metavariable: $IDEA + regex: ^(IDEA)$ + - focus-metavariable: $IDEA + fix: AES diff --git a/python/cryptography/security/insecure-cipher-mode-ecb.fixed.py b/python/cryptography/security/insecure-cipher-mode-ecb.fixed.py new file mode 100644 index 0000000000..334ca7dbdf --- /dev/null +++ b/python/cryptography/security/insecure-cipher-mode-ecb.fixed.py @@ -0,0 +1,17 @@ +# cf. https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/examples/cipher-modes.py + +from cryptography.hazmat.primitives.ciphers.modes import CBC +from cryptography.hazmat.primitives.ciphers.modes import ECB + + +# Insecure mode +# ruleid: insecure-cipher-mode-ecb +mode = cryptography.hazmat.primitives.ciphers.modes.GCM(iv) + +# Secure cipher and mode +# ok: insecure-cipher-mode-ecb +cipher = AES.new(key, blockalgo.MODE_CTR, iv) + +# Secure mode +# ok: insecure-cipher-mode-ecb +mode = CBC(iv) diff --git a/python/cryptography/security/insecure-cipher-mode-ecb.yaml b/python/cryptography/security/insecure-cipher-mode-ecb.yaml index ea4c79c92d..8f48154191 100644 --- a/python/cryptography/security/insecure-cipher-mode-ecb.yaml +++ b/python/cryptography/security/insecure-cipher-mode-ecb.yaml @@ -1,11 +1,10 @@ rules: - id: insecure-cipher-mode-ecb - pattern: cryptography.hazmat.primitives.ciphers.modes.ECB(...) message: >- ECB (Electronic Code Book) is the simplest mode of operation for block ciphers. Each block of data is encrypted in the same way. This means identical plaintext blocks will always result in identical ciphertext blocks, which can leave significant patterns in the output. - Use a different, more secure mode instead. + Use a different, cryptographically strong mode instead, such as GCM. metadata: source-rule-url: https://github.com/PyCQA/bandit/blob/d5f8fa0d89d7b11442fc6ec80ca42953974354c8/bandit/blacklists/calls.py#L101 cwe: @@ -30,3 +29,5 @@ rules: severity: WARNING languages: - python + pattern: cryptography.hazmat.primitives.ciphers.modes.ECB($IV) + fix: cryptography.hazmat.primitives.ciphers.modes.GCM($IV) diff --git a/python/cryptography/security/insecure-hash-algorithms-md5.fixed.py b/python/cryptography/security/insecure-hash-algorithms-md5.fixed.py new file mode 100644 index 0000000000..f56a5ebfde --- /dev/null +++ b/python/cryptography/security/insecure-hash-algorithms-md5.fixed.py @@ -0,0 +1,10 @@ +# cf. https://github.com/PyCQA/bandit/blob/b78c938c0bd03d201932570f5e054261e10c5750/examples/crypto-md5.py + +from cryptography.hazmat.primitives import hashes + +# ruleid:insecure-hash-algorithm-md5 +hashes.SHA256() +# ok:insecure-hash-algorithm-md5 +hashes.SHA256() +# ok:insecure-hash-algorithm-md5 +hashes.SHA3_256() diff --git a/python/cryptography/security/insecure-hash-algorithms-md5.yaml b/python/cryptography/security/insecure-hash-algorithms-md5.yaml index 6dccc4f184..b34cf9b516 100644 --- a/python/cryptography/security/insecure-hash-algorithms-md5.yaml +++ b/python/cryptography/security/insecure-hash-algorithms-md5.yaml @@ -1,6 +1,5 @@ rules: - id: insecure-hash-algorithm-md5 - pattern: cryptography.hazmat.primitives.hashes.MD5(...) message: >- Detected MD5 hash algorithm which is considered insecure. MD5 is not collision resistant and is therefore not suitable as a cryptographic @@ -32,3 +31,10 @@ rules: severity: WARNING languages: - python + patterns: + - pattern: cryptography.hazmat.primitives.hashes.$MD5() + - metavariable-regex: + metavariable: $MD5 + regex: ^(MD5)$ + - focus-metavariable: $MD5 + fix: SHA256 diff --git a/python/cryptography/security/insufficient-dsa-key-size.fixed.py b/python/cryptography/security/insufficient-dsa-key-size.fixed.py new file mode 100644 index 0000000000..ef412c935a --- /dev/null +++ b/python/cryptography/security/insufficient-dsa-key-size.fixed.py @@ -0,0 +1,18 @@ +from cryptography.hazmat import backends +from cryptography.hazmat.primitives.asymmetric import dsa + +# ok: insufficient-dsa-key-size +dsa.generate_private_key(key_size=2048, + backend=backends.default_backend()) + +# ok: insufficient-dsa-key-size +dsa.generate_private_key(2048, + backend=backends.default_backend()) + +# ruleid: insufficient-dsa-key-size +dsa.generate_private_key(key_size=2048, + backend=backends.default_backend()) + +# ruleid: insufficient-dsa-key-size +dsa.generate_private_key(2048, + backend=backends.default_backend()) diff --git a/python/cryptography/security/insufficient-dsa-key-size.yaml b/python/cryptography/security/insufficient-dsa-key-size.yaml index cf5ab0bb9b..6976642173 100644 --- a/python/cryptography/security/insufficient-dsa-key-size.yaml +++ b/python/cryptography/security/insufficient-dsa-key-size.yaml @@ -8,6 +8,9 @@ rules: - metavariable-comparison: metavariable: $SIZE comparison: $SIZE < 2048 + - focus-metavariable: $SIZE + fix: | + 2048 message: >- Detected an insufficient key size for DSA. NIST recommends a key size of 2048 or higher. diff --git a/python/cryptography/security/insufficient-rsa-key-size.fixed.py b/python/cryptography/security/insufficient-rsa-key-size.fixed.py new file mode 100644 index 0000000000..22cb4a0437 --- /dev/null +++ b/python/cryptography/security/insufficient-rsa-key-size.fixed.py @@ -0,0 +1,33 @@ +import os +from cryptography.hazmat import backends +from cryptography.hazmat.primitives.asymmetric import rsa + +rsa.generate_private_key(public_exponent=65537, +# ok: insufficient-rsa-key-size + key_size=2048, + backend=backends.default_backend()) + +rsa.generate_private_key(65537, +# ok: insufficient-rsa-key-size + 2048, + backends.default_backend()) + +rsa.generate_private_key(public_exponent=65537, +# ok: insufficient-rsa-key-size + key_size=os.getenv("KEY_SIZE"), + backend=backends.default_backend()) + +rsa.generate_private_key(65537, +# ok: insufficient-rsa-key-size + 2048, + backends.default_backend()) + +rsa.generate_private_key(public_exponent=65537, +# ruleid: insufficient-rsa-key-size + key_size=2048, + backend=backends.default_backend()) + +rsa.generate_private_key(65537, +# ruleid: insufficient-rsa-key-size + 2048, + backends.default_backend()) diff --git a/python/cryptography/security/insufficient-rsa-key-size.py b/python/cryptography/security/insufficient-rsa-key-size.py index cbd5378f32..8f1f45b298 100644 --- a/python/cryptography/security/insufficient-rsa-key-size.py +++ b/python/cryptography/security/insufficient-rsa-key-size.py @@ -2,32 +2,32 @@ from cryptography.hazmat import backends from cryptography.hazmat.primitives.asymmetric import rsa -# ok: insufficient-rsa-key-size rsa.generate_private_key(public_exponent=65537, +# ok: insufficient-rsa-key-size key_size=2048, backend=backends.default_backend()) -# ok: insufficient-rsa-key-size rsa.generate_private_key(65537, +# ok: insufficient-rsa-key-size 2048, backends.default_backend()) -# ok: insufficient-rsa-key-size rsa.generate_private_key(public_exponent=65537, +# ok: insufficient-rsa-key-size key_size=os.getenv("KEY_SIZE"), backend=backends.default_backend()) -# ok: insufficient-rsa-key-size rsa.generate_private_key(65537, +# ok: insufficient-rsa-key-size 2048, backends.default_backend()) -# ruleid: insufficient-rsa-key-size rsa.generate_private_key(public_exponent=65537, +# ruleid: insufficient-rsa-key-size key_size=1024, backend=backends.default_backend()) -# ruleid: insufficient-rsa-key-size rsa.generate_private_key(65537, +# ruleid: insufficient-rsa-key-size 1024, backends.default_backend()) diff --git a/python/cryptography/security/insufficient-rsa-key-size.yaml b/python/cryptography/security/insufficient-rsa-key-size.yaml index a2898d3623..1ec1dcd035 100644 --- a/python/cryptography/security/insufficient-rsa-key-size.yaml +++ b/python/cryptography/security/insufficient-rsa-key-size.yaml @@ -8,6 +8,9 @@ rules: - metavariable-comparison: metavariable: $SIZE comparison: $SIZE < 2048 + - focus-metavariable: $SIZE + fix : | + 2048 message: >- Detected an insufficient key size for RSA. NIST recommends a key size of 2048 or higher. From d9fe6c66de9a1e2cd8515b66b80eb64e31d12d31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 08:36:33 +0100 Subject: [PATCH 2/3] Bump jinja2 from 2.11.3 to 3.1.3 (#3271) Bumps [jinja2](https://github.com/pallets/jinja) from 2.11.3 to 3.1.3. - [Release notes](https://github.com/pallets/jinja/releases) - [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/jinja/compare/2.11.3...3.1.3) --- updated-dependencies: - dependency-name: jinja2 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Pipfile | 2 +- Pipfile.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Pipfile b/Pipfile index 67ac5b0669..a7a292cc8c 100644 --- a/Pipfile +++ b/Pipfile @@ -4,7 +4,7 @@ url = "https://pypi.org/simple" verify_ssl = true [dev-packages] -jinja2 = "~=2.11.3" +jinja2 = "~=3.1.3" pytest = "*" semgrep = "*" pyyaml = "*" diff --git a/Pipfile.lock b/Pipfile.lock index f486329a09..2e87da7092 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "40d5608e6fdc1066084f413eb1f976c2fd5ea39fd0c78aa7a01ae120c11a614b" + "sha256": "762f3c7cbb0a3ecd999e7b644a02421c6132ab10439b5eb9a2531519c86351b9" }, "pipfile-spec": 6, "requires": { @@ -433,12 +433,12 @@ }, "jinja2": { "hashes": [ - "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", - "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" + "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa", + "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==2.11.3" + "markers": "python_version >= '3.7'", + "version": "==3.1.3" }, "jsonschema": { "hashes": [ From 0c04c57ee0294e12a887569e4858b28d99f8085f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 07:46:43 +0000 Subject: [PATCH 3/3] Bump tj-actions/changed-files from 23.1 to 41 in /.github/workflows (#3256) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 23.1 to 41. - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/v23.1...v41) --- updated-dependencies: - dependency-name: tj-actions/changed-files dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Pieter De Cremer (Semgrep) --- .github/workflows/semgrep-rules-test-historical.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semgrep-rules-test-historical.yml b/.github/workflows/semgrep-rules-test-historical.yml index a0dda1d676..2c8d9faf5b 100644 --- a/.github/workflows/semgrep-rules-test-historical.yml +++ b/.github/workflows/semgrep-rules-test-historical.yml @@ -22,7 +22,7 @@ jobs: python-version: 3.9.2 - name: Get changed files id: changed-files - uses: tj-actions/changed-files@v23.1 + uses: tj-actions/changed-files@v41 with: path: semgrep-rules separator: ","